Exemplo n.º 1
0
    def __init__(self, master):

        self.ser = serial.Serial('/dev/cu.wchusbserial1490')
        sleep(3)

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        plug.load_plugins()

        if platform != 'darwin':
            if platform == 'win32':
                self.w.wm_iconbitmap(default='EDMarketConnector.ico')
            else:
                from PIL import Image, ImageTk
                self.w.tk.call(
                    'wm', 'iconphoto', self.w, '-default',
                    ImageTk.PhotoImage(Image.open("EDMarketConnector.png")))
            self.theme_icon = tk.PhotoImage(
                data=
                'R0lGODlhFAAQAMZVAAAAAAEAAAIBAAMBAAQCAAYDAAcDAAkEAAoEAAwGAQ8IARAIAREJARYKABkLARsMASMQASgSAiUUAy0UAjAVAioXBDIWAy4YBC4ZBS8ZBTkZA0EdBDsgBkUfA0MkB00iA1AjA1IlBFQmBE4qCFgoBVkoBFArCF0qBVQtCGUrBGMtBWYtBWA0Cm8xBW8xBm8yBXMzBXU1Bms5C3s1BXs2BXw2BX02BXw4B4A5B3Q/DIJGDYNGDYJHDoNHDYdJDppGCItLD4xLDo5MDo5MD5hSD59VEKdaEbJgErtlE7tlFLxlE8BpFMJpFMNpFMZrFdFxFtl1F995GOB6GOF6GP+LG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAEKAH8ALAAAAAAUABAAAAejgACCgiODhoeGBABPPgACj48DA4gAk00cSRUYGZycEogBAE4LCUM8Oj2pOzlQBAKHSBeKlABKBq+DHkS0g0wJiCZFvABHJBuHBSxADFRTUs/PUUsiKhaIKEZBKTM13TU0Nj8IIRqThjJCK8MnFIgKMMMAJRGGAQUvvAIPLocBAjgdPggcKMLAgRi0GjxYyNBBCwjwQoEKQLEiABA3HMU7NOFQIAA7'
            )
            self.theme_minimize = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f,\n   0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n'
            )
            self.theme_close = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x1c, 0x38, 0x38, 0x1c, 0x70, 0x0e,\n   0xe0, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x07, 0x70, 0x0e, 0x38, 0x1c,\n   0x1c, 0x38, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00 };\n'
            )

        frame = tk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)

        self.cmdr_label = tk.Label(frame)
        self.ship_label = tk.Label(frame)
        self.system_label = tk.Label(frame)
        self.station_label = tk.Label(frame)

        self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
        self.ship_label.grid(row=2, column=0, sticky=tk.W)
        self.system_label.grid(row=3, column=0, sticky=tk.W)
        self.station_label.grid(row=4, column=0, sticky=tk.W)

        self.cmdr = tk.Label(frame, anchor=tk.W)
        self.ship = HyperlinkLabel(frame, url=self.shipyard_url)
        self.system = HyperlinkLabel(frame,
                                     compound=tk.RIGHT,
                                     url=self.system_url,
                                     popup_copy=True)
        self.station = HyperlinkLabel(
            frame,
            url=self.station_url,
            popup_copy=lambda x: x != self.STATION_UNDOCKED)

        self.cmdr.grid(row=1, column=1, sticky=tk.EW)
        self.ship.grid(row=2, column=1, sticky=tk.EW)
        self.system.grid(row=3, column=1, sticky=tk.EW)
        self.station.grid(row=4, column=1, sticky=tk.EW)

        for plugname in plug.PLUGINS:
            appitem = plug.get_plugin_app(plugname, frame)
            if appitem:
                if isinstance(appitem, tuple) and len(appitem) == 2:
                    row = frame.grid_size()[1]
                    appitem[0].grid(row=row, column=0, sticky=tk.W)
                    appitem[1].grid(row=row, column=1, sticky=tk.EW)
                else:
                    appitem.grid(columnspan=2, sticky=tk.W)

        self.button = ttk.Button(
            frame,
            text=_('Update'),
            width=28,
            default=tk.ACTIVE,
            state=tk.DISABLED)  # Update button in main window
        self.theme_button = tk.Label(frame,
                                     width=platform == 'darwin' and 32 or 28,
                                     state=tk.DISABLED)
        self.status = tk.Label(frame, name='status', anchor=tk.W)

        row = frame.grid_size()[1]
        self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        theme.register_alternate((self.button, self.theme_button), {
            'row': row,
            'columnspan': 2,
            'sticky': tk.NSEW
        })
        self.status.grid(columnspan=2, sticky=tk.EW)
        self.button.bind('<Button-1>', self.getandsend)
        theme.button_bind(self.theme_button, self.getandsend)

        for child in frame.winfo_children():
            child.grid_configure(padx=5, pady=(platform != 'win32' and 2 or 0))

        self.menubar = tk.Menu()
        if platform == 'darwin':
            # Can't handle (de)iconify if topmost is set, so suppress iconify button
            # http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
            root.call('tk::unsupported::MacWindowStyle', 'style', root,
                      'document', 'closeBox horizontalZoom resizable')

            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            self.system_menu = tk.Menu(self.menubar, name='apple')
            self.system_menu.add_command(
                command=lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.system_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.menubar.add_cascade(menu=self.system_menu)
            self.file_menu = tk.Menu(self.menubar, name='file')
            self.file_menu.add_command(command=self.save_raw)
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, name='edit')
            self.edit_menu.add_command(accelerator='Command-c',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(self.menubar, name='view')
            self.view_menu.add_command(command=lambda: stats.StatsDialog(self))
            self.menubar.add_cascade(menu=self.view_menu)
            window_menu = tk.Menu(self.menubar, name='window')
            self.menubar.add_cascade(menu=window_menu)
            self.w['menu'] = self.menubar
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand(
                'tkAboutDialog',
                lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand(
                "::tk::mac::ShowPreferences",
                lambda: prefs.PreferencesDialog(self.w, self.postprefs))
            self.w.createcommand(
                "::tk::mac::ReopenApplication",
                self.w.deiconify)  # click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW",
                            self.w.withdraw)  # close button shouldn't quit app
        else:
            self.file_menu = self.view_menu = tk.Menu(self.menubar,
                                                      tearoff=tk.FALSE)
            self.file_menu.add_command(command=lambda: stats.StatsDialog(self))
            self.file_menu.add_command(command=self.save_raw)
            self.file_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.file_menu.add_command(command=lambda: prefs.PreferencesDialog(
                self.w, self.postprefs))
            self.file_menu.add_separator()
            self.file_menu.add_command(command=self.onexit)
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(accelerator='Ctrl+C',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            if platform == 'win32':
                # Must be added after at least one "real" menu entry
                self.always_ontop = tk.BooleanVar(
                    value=config.getint('always_ontop'))
                self.system_menu = tk.Menu(self.menubar,
                                           name='system',
                                           tearoff=tk.FALSE)
                self.system_menu.add_separator()
                self.system_menu.add_checkbutton(
                    label=_('Always on top'),
                    variable=self.always_ontop,
                    command=self.ontop_changed)  # Appearance setting
                self.menubar.add_cascade(menu=self.system_menu)
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
            theme.register(
                self.menubar
            )  # menus and children aren't automatically registered
            theme.register(self.file_menu)
            theme.register(self.edit_menu)

            # Alternate title bar and menu for dark theme
            self.theme_menubar = tk.Frame(frame)
            self.theme_menubar.columnconfigure(2, weight=1)
            theme_titlebar = tk.Label(self.theme_menubar,
                                      text=applongname,
                                      image=self.theme_icon,
                                      anchor=tk.W,
                                      compound=tk.LEFT)
            theme_titlebar.grid(columnspan=3, padx=2, sticky=tk.NSEW)
            self.drag_offset = None
            theme_titlebar.bind('<Button-1>', self.drag_start)
            theme_titlebar.bind('<B1-Motion>', self.drag_continue)
            theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
            if platform == 'win32':  # Can't work out how to deiconify on Linux
                theme_minimize = tk.Label(self.theme_menubar,
                                          image=self.theme_minimize)
                theme_minimize.grid(row=0, column=3, padx=2)
                theme.button_bind(theme_minimize,
                                  self.oniconify,
                                  image=self.theme_minimize)
            theme_close = tk.Label(self.theme_menubar, image=self.theme_close)
            theme_close.grid(row=0, column=4, padx=2)
            theme.button_bind(theme_close, self.onexit, image=self.theme_close)
            self.theme_file_menu = tk.Label(self.theme_menubar, anchor=tk.W)
            self.theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W)
            theme.button_bind(
                self.theme_file_menu, lambda e: self.file_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            self.theme_edit_menu = tk.Label(self.theme_menubar, anchor=tk.W)
            self.theme_edit_menu.grid(row=1, column=1, sticky=tk.W)
            theme.button_bind(
                self.theme_edit_menu, lambda e: self.edit_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            theme.register_highlight(theme_titlebar)
            theme.register(
                self.theme_minimize)  # images aren't automatically registered
            theme.register(self.theme_close)
            theme.register_alternate((self.menubar, self.theme_menubar), {
                'row': 0,
                'columnspan': 2,
                'sticky': tk.NSEW
            })

        self.set_labels()

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match:
                if platform == 'darwin':
                    if int(
                            match.group(2)
                    ) >= 0:  # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                        self.w.geometry(config.get('geometry'))
                elif platform == 'win32':
                    # Check that the titlebar will be at least partly on screen
                    import ctypes
                    from ctypes.wintypes import POINT
                    # https://msdn.microsoft.com/en-us/library/dd145064
                    MONITOR_DEFAULTTONULL = 0
                    if ctypes.windll.user32.MonitorFromPoint(
                            POINT(
                                int(match.group(1)) + 16,
                                int(match.group(2)) + 16),
                            MONITOR_DEFAULTTONULL):
                        self.w.geometry(config.get('geometry'))
                else:
                    self.w.geometry(config.get('geometry'))
        self.w.attributes('-topmost', config.getint('always_ontop') and 1 or 0)
        self.w.resizable(tk.TRUE, tk.FALSE)

        theme.register(frame)
        theme.register_highlight(self.ship)
        theme.register_highlight(self.system)
        theme.register_highlight(self.station)
        theme.apply(self.w)

        self.w.bind("<Map>", self.onmap)  # Special handling for overrideredict
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)
        self.w.bind_all('<<Invoke>>', self.getandsend)  # Hotkey monitoring
        self.w.bind_all('<<JournalEvent>>',
                        self.journal_event)  # Journal monitoring
        self.w.bind_all('<<Quit>>', self.onexit)  # Updater

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.postprefs)
        else:
            self.login()

        self.ser.write(b'!0Initialising...\n')
        self.ser.flush()
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        if platform == 'win32':
            self.w.wm_iconbitmap(default='EDMarketConnector.ico')
        elif platform == 'linux2':
            from PIL import Image, ImageTk
            icon = ImageTk.PhotoImage(Image.open("EDMarketConnector.png"))
            self.w.tk.call('wm', 'iconphoto', self.w, '-default', icon)
            style = ttk.Style()
            style.theme_use('clam')
        elif platform == 'darwin':
            # Default ttk font choice looks bad on El Capitan
            font = tkFont.Font(family='TkDefaultFont',
                               size=13,
                               weight=tkFont.NORMAL)
            style = ttk.Style()
            style.configure('TLabel', font=font)
            style.configure('TButton', font=font)
            style.configure('TLabelframe.Label', font=font)
            style.configure('TCheckbutton', font=font)
            style.configure('TRadiobutton', font=font)
            style.configure('TEntry', font=font)

        frame = ttk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(4, weight=1)

        ttk.Label(frame, text=_('Cmdr') + ':').grid(row=0,
                                                    column=0,
                                                    sticky=tk.W)  # Main window
        ttk.Label(frame,
                  text=_('System') + ':').grid(row=1, column=0,
                                               sticky=tk.W)  # Main window
        ttk.Label(frame,
                  text=_('Station') + ':').grid(row=2, column=0,
                                                sticky=tk.W)  # Main window

        self.cmdr = ttk.Label(frame, width=-21)
        self.system = HyperlinkLabel(frame,
                                     compound=tk.RIGHT,
                                     url=self.system_url,
                                     popup_copy=True)
        self.station = HyperlinkLabel(
            frame,
            url=self.station_url,
            popup_copy=lambda x: x != self.STATION_UNDOCKED)
        self.button = ttk.Button(
            frame,
            name='update',
            text=_('Update'),
            command=self.getandsend,
            default=tk.ACTIVE,
            state=tk.DISABLED)  # Update button in main window
        self.status = ttk.Label(frame, name='status', width=-25)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        self.cmdr.grid(row=0, column=1, sticky=tk.EW)
        self.system.grid(row=1, column=1, sticky=tk.EW)
        self.station.grid(row=2, column=1, sticky=tk.EW)
        self.button.grid(row=3, column=0, columnspan=2, sticky=tk.NSEW)
        self.status.grid(row=4, column=0, columnspan=2, sticky=tk.EW)

        for child in frame.winfo_children():
            child.grid_configure(padx=5,
                                 pady=(platform == 'darwin' and 3 or 2))

        menubar = tk.Menu()
        if platform == 'darwin':
            from Foundation import NSBundle
            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            apple_menu = tk.Menu(menubar, name='apple')
            apple_menu.add_command(
                label=_("About {APP}").format(APP=applongname),
                command=lambda: self.w.call('tk::mac::standardAboutPanel'
                                            ))  # App menu entry on OSX
            apple_menu.add_command(
                label=_("Check for Updates..."),
                command=lambda: self.updater.checkForUpdates())
            menubar.add_cascade(menu=apple_menu)
            self.edit_menu = tk.Menu(menubar, name='edit')
            self.edit_menu.add_command(
                label=_('Copy'),
                accelerator='Command-c',
                state=tk.DISABLED,
                command=self.copy)  # As in Copy and Paste
            menubar.add_cascade(label=_('Edit'),
                                menu=self.edit_menu)  # Menu title
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(menubar, name='view')
            self.view_menu.add_command(label=_('Status'),
                                       state=tk.DISABLED,
                                       command=lambda: stats.StatsDialog(
                                           self.w, self.session))  # Menu item
            menubar.add_cascade(label=_('View'),
                                menu=self.view_menu)  # Menu title on OSX
            window_menu = tk.Menu(menubar, name='window')
            menubar.add_cascade(label=_('Window'),
                                menu=window_menu)  # Menu title on OSX
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand(
                'tkAboutDialog',
                lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand(
                "::tk::mac::ShowPreferences",
                lambda: prefs.PreferencesDialog(self.w, self.login))
            self.w.createcommand(
                "::tk::mac::ReopenApplication",
                self.w.deiconify)  # click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW",
                            self.w.withdraw)  # close button shouldn't quit app
        else:
            file_menu = self.view_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            file_menu.add_command(label=_('Status'),
                                  state=tk.DISABLED,
                                  command=lambda: stats.StatsDialog(
                                      self.w, self.session))  # Menu item
            file_menu.add_command(
                label=_("Check for Updates..."),
                command=lambda: self.updater.checkForUpdates())
            file_menu.add_command(
                label=_("Settings"),
                command=lambda: prefs.PreferencesDialog(
                    self.w, self.login))  # Item in the File menu on Windows
            file_menu.add_separator()
            file_menu.add_command(
                label=_("Exit"),
                command=self.onexit)  # Item in the File menu on Windows
            menubar.add_cascade(label=_("File"),
                                menu=file_menu)  # Menu title on Windows
            self.edit_menu = tk.Menu(menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(
                label=_('Copy'),
                accelerator='Ctrl+C',
                state=tk.DISABLED,
                command=self.copy)  # As in Copy and Paste
            menubar.add_cascade(label=_('Edit'),
                                menu=self.edit_menu)  # Menu title
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
        if platform == 'linux2':
            # Fix up menu to use same styling as everything else
            (fg, bg, afg, abg) = (style.lookup('TLabel.label', 'foreground'),
                                  style.lookup('TLabel.label', 'background'),
                                  style.lookup('TButton.label', 'foreground',
                                               ['active']),
                                  style.lookup('TButton.label', 'background',
                                               ['active']))
            menubar.configure(fg=fg,
                              bg=bg,
                              activeforeground=afg,
                              activebackground=abg)
            file_menu.configure(fg=fg,
                                bg=bg,
                                activeforeground=afg,
                                activebackground=abg)
            self.edit_menu.configure(fg=fg,
                                     bg=bg,
                                     activeforeground=afg,
                                     activebackground=abg)
        self.w['menu'] = menubar

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match and (
                    platform != 'darwin' or int(match.group(2)) > 0
            ):  # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                self.w.geometry(config.get('geometry'))
        self.w.update_idletasks()
        self.w.wait_visibility()
        (w, h) = (self.w.winfo_width(), self.w.winfo_height())
        self.w.minsize(w, h)  # Minimum size = initial size
        if platform != 'linux2':  # update_idletasks() doesn't allow for the menubar on Linux
            self.w.maxsize(-1, h)  # Maximum height = initial height

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)  # user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)  # user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'),
                           config.getint('hotkey_mods'))

        # Install log monitoring
        self.w.bind_all('<<Jump>>', self.system_change)  # user-generated
        if (config.getint('output') & config.OUT_LOG_AUTO) and (
                config.getint('output') &
            (config.OUT_LOG_AUTO | config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.login)
        else:
            self.login()
Exemplo n.º 3
0
    def __init__(self, master):

        self.holdofftime = config.getint('querytime') + companion.holdoff
        self.session = companion.Session()
        self.edsm = edsm.EDSM()

        self.w = master
        self.w.title(applongname)
        self.w.rowconfigure(0, weight=1)
        self.w.columnconfigure(0, weight=1)

        # Special handling for overrideredict
        self.w.bind("<Map>", self.onmap)

        plug.load_plugins()

        if platform != 'darwin':
            if platform == 'win32':
                self.w.wm_iconbitmap(default='EDMarketConnector.ico')
            else:
                from PIL import Image, ImageTk
                self.w.tk.call(
                    'wm', 'iconphoto', self.w, '-default',
                    ImageTk.PhotoImage(Image.open("EDMarketConnector.png")))
            self.theme_icon = tk.PhotoImage(
                data=
                'R0lGODlhEAAQAMYAAAAAAAEAAAEBAQICAgQEAwYFBAsHBAoIBgwIBAwIBQ0IBA8JBBAJBBAKBRMMBRkPBhoQBykWCSoWCCoXCTsfCzwfCkAhDEIjDD8kC0AlDEEmC0EmDEcoDk4oDU8pDU4qEFMrD1ktDlotD1ouD1g0EWAyEWU0EV03EmA4EWo2EW03EWQ6Emw4EWo9FGo+E3Y8FH5AFH1IFoBJFo1RGo1SGY1SGpBTGZFTGZJTGZhYG6piHa1kHa5kHbBkHr9uIMt0IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEKAEAALAAAAAAQABAAAAd7gACCg4SFhoeHGCiIhRs5JwMCkpKGGTIFODaaNjc/D4QaMQMAk5MuEIQOO6OFAiscCIQNPQk8NTO4NDofLwayPi0mIMPDLAcqvoIBDiQWkaUCAykKhAsXAoYCHRKEDDAjIyIiIyEEHhHYhAPr7BQlE+mMABXo8oTx9oWBADs='
            )
            self.theme_minimize = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f,\n   0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n'
            )
            self.theme_close = tk.BitmapImage(
                data=
                '#define im_width 16\n#define im_height 16\nstatic unsigned char im_bits[] = {\n   0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x1c, 0x38, 0x38, 0x1c, 0x70, 0x0e,\n   0xe0, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x07, 0x70, 0x0e, 0x38, 0x1c,\n   0x1c, 0x38, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00 };\n'
            )

        frame = tk.Frame(self.w, name=appname.lower())
        frame.grid(sticky=tk.NSEW)
        frame.columnconfigure(1, weight=1)

        self.cmdr_label = tk.Label(frame)
        self.system_label = tk.Label(frame)
        self.station_label = tk.Label(frame)

        self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
        self.system_label.grid(row=2, column=0, sticky=tk.W)
        self.station_label.grid(row=3, column=0, sticky=tk.W)

        self.cmdr = tk.Label(frame, anchor=tk.W)
        self.system = HyperlinkLabel(frame,
                                     compound=tk.RIGHT,
                                     url=self.system_url,
                                     popup_copy=True)
        self.station = HyperlinkLabel(
            frame,
            url=self.station_url,
            popup_copy=lambda x: x != self.STATION_UNDOCKED)

        self.cmdr.grid(row=1, column=1, sticky=tk.EW)
        self.system.grid(row=2, column=1, sticky=tk.EW)
        self.station.grid(row=3, column=1, sticky=tk.EW)

        for plugname in plug.PLUGINS:
            appitem = plug.get_plugin_app(plugname, frame)
            if appitem:
                appitem.grid(columnspan=2, sticky=tk.W)

        self.button = ttk.Button(
            frame,
            text=_('Update'),
            width=28,
            command=self.getandsend,
            default=tk.ACTIVE,
            state=tk.DISABLED)  # Update button in main window
        self.theme_button = tk.Label(frame,
                                     width=platform == 'darwin' and 32 or 28,
                                     state=tk.DISABLED)
        self.status = tk.Label(frame, name='status', anchor=tk.W)

        row = frame.grid_size()[1]
        self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
        theme.register_alternate((self.button, self.theme_button), {
            'row': row,
            'columnspan': 2,
            'sticky': tk.NSEW
        })
        self.status.grid(columnspan=2, sticky=tk.EW)

        theme.button_bind(self.theme_button, self.getandsend)
        self.w.bind('<Return>', self.getandsend)
        self.w.bind('<KP_Enter>', self.getandsend)

        for child in frame.winfo_children():
            child.grid_configure(padx=5, pady=(platform == 'win32' and 1 or 3))

        self.menubar = tk.Menu()
        if platform == 'darwin':
            # Can't handle (de)iconify if topmost is set, so suppress iconify button
            # http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
            root.call('tk::unsupported::MacWindowStyle', 'style', root,
                      'document', 'closeBox horizontalZoom resizable')

            # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
            self.file_menu = tk.Menu(self.menubar, name='apple')
            self.file_menu.add_command(
                command=lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.file_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, name='edit')
            self.edit_menu.add_command(accelerator='Command-c',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            self.w.bind('<Command-c>', self.copy)
            self.view_menu = tk.Menu(self.menubar, name='view')
            self.view_menu.add_command(
                state=tk.DISABLED,
                command=lambda: stats.StatsDialog(self.w, self.session))
            self.menubar.add_cascade(menu=self.view_menu)
            window_menu = tk.Menu(self.menubar, name='window')
            self.menubar.add_cascade(menu=window_menu)
            self.w['menu'] = self.menubar
            # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
            self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
            self.w.createcommand(
                'tkAboutDialog',
                lambda: self.w.call('tk::mac::standardAboutPanel'))
            self.w.createcommand("::tk::mac::Quit", self.onexit)
            self.w.createcommand(
                "::tk::mac::ShowPreferences",
                lambda: prefs.PreferencesDialog(self.w, self.postprefs))
            self.w.createcommand(
                "::tk::mac::ReopenApplication",
                self.w.deiconify)  # click on app in dock = restore
            self.w.protocol("WM_DELETE_WINDOW",
                            self.w.withdraw)  # close button shouldn't quit app
        else:
            self.file_menu = self.view_menu = tk.Menu(self.menubar,
                                                      tearoff=tk.FALSE)
            self.file_menu.add_command(
                state=tk.DISABLED,
                command=lambda: stats.StatsDialog(self.w, self.session))
            self.file_menu.add_command(
                command=lambda: self.updater.checkForUpdates())
            self.file_menu.add_command(command=lambda: prefs.PreferencesDialog(
                self.w, self.postprefs))
            self.file_menu.add_separator()
            self.file_menu.add_command(command=self.onexit)
            self.menubar.add_cascade(menu=self.file_menu)
            self.edit_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
            self.edit_menu.add_command(accelerator='Ctrl+C',
                                       state=tk.DISABLED,
                                       command=self.copy)
            self.menubar.add_cascade(menu=self.edit_menu)
            if platform == 'win32':
                # Must be added after at least one "real" menu entry
                self.always_ontop = tk.BooleanVar(
                    value=config.getint('always_ontop'))
                system_menu = tk.Menu(self.menubar,
                                      name='system',
                                      tearoff=tk.FALSE)
                system_menu.add_separator()
                system_menu.add_checkbutton(
                    label=_('Always on top'),
                    variable=self.always_ontop,
                    command=self.ontop_changed)  # Appearance setting
                self.menubar.add_cascade(menu=system_menu)  # Gets index 0
            self.w.bind('<Control-c>', self.copy)
            self.w.protocol("WM_DELETE_WINDOW", self.onexit)
            theme.register(
                self.menubar
            )  # menus and children aren't automatically registered
            theme.register(self.file_menu)
            theme.register(self.edit_menu)

            # Alternate title bar and menu for dark theme
            self.theme_menubar = tk.Frame(frame)
            self.theme_menubar.columnconfigure(2, weight=1)
            theme_titlebar = tk.Label(self.theme_menubar,
                                      text=applongname,
                                      image=self.theme_icon,
                                      anchor=tk.W,
                                      compound=tk.LEFT)
            theme_titlebar.grid(columnspan=3, sticky=tk.NSEW)
            self.drag_offset = None
            theme_titlebar.bind('<Button-1>', self.drag_start)
            theme_titlebar.bind('<B1-Motion>', self.drag_continue)
            theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
            if platform == 'win32':  # Can't work out how to deiconify on Linux
                theme_minimize = tk.Label(self.theme_menubar,
                                          image=self.theme_minimize)
                theme_minimize.grid(row=0, column=3)
                theme.button_bind(theme_minimize,
                                  self.oniconify,
                                  image=self.theme_minimize)
            theme_close = tk.Label(self.theme_menubar, image=self.theme_close)
            theme_close.grid(row=0, column=4)
            theme.button_bind(theme_close, self.onexit, image=self.theme_close)
            self.theme_file_menu = tk.Label(self.theme_menubar, anchor=tk.W)
            self.theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W)
            theme.button_bind(
                self.theme_file_menu, lambda e: self.file_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            self.theme_edit_menu = tk.Label(self.theme_menubar,
                                            anchor=tk.W)  # Menu title
            self.theme_edit_menu.grid(row=1, column=1, sticky=tk.W)
            theme.button_bind(
                self.theme_edit_menu, lambda e: self.edit_menu.tk_popup(
                    e.widget.winfo_rootx(),
                    e.widget.winfo_rooty() + e.widget.winfo_height()))
            theme.register_highlight(theme_titlebar)
            theme.register(
                self.theme_minimize)  # images aren't automatically registered
            theme.register(self.theme_close)
            theme.register_alternate((self.menubar, self.theme_menubar), {
                'row': 0,
                'columnspan': 2,
                'sticky': tk.NSEW
            })

        self.set_labels()

        # update geometry
        if config.get('geometry'):
            match = re.match('\+([\-\d]+)\+([\-\d]+)', config.get('geometry'))
            if match:
                if platform == 'darwin':
                    if int(
                            match.group(2)
                    ) >= 0:  # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
                        self.w.geometry(config.get('geometry'))
                elif platform == 'win32':
                    # Check that the titlebar will be at least partly on screen
                    import ctypes
                    from ctypes.wintypes import POINT
                    # https://msdn.microsoft.com/en-us/library/dd145064
                    MONITOR_DEFAULTTONULL = 0
                    if ctypes.windll.user32.MonitorFromPoint(
                            POINT(
                                int(match.group(1)) + 16,
                                int(match.group(2)) + 16),
                            MONITOR_DEFAULTTONULL):

                        self.w.geometry(config.get('geometry'))
                else:
                    self.w.geometry(config.get('geometry'))
        self.w.attributes('-topmost', config.getint('always_ontop') and 1 or 0)
        self.w.resizable(tk.TRUE, tk.FALSE)

        theme.register(frame)
        theme.register_highlight(self.system)
        theme.register_highlight(self.station)
        theme.apply(self.w)

        # Load updater after UI creation (for WinSparkle)
        import update
        self.updater = update.Updater(self.w)
        self.w.bind_all('<<Quit>>', self.onexit)  # user-generated

        # Install hotkey monitoring
        self.w.bind_all('<<Invoke>>', self.getandsend)  # user-generated
        hotkeymgr.register(self.w, config.getint('hotkey_code'),
                           config.getint('hotkey_mods'))

        # Install log monitoring
        monitor.set_callback(self.system_change)
        edproxy.set_callback(self.system_change)
        if (config.getint('output') & config.OUT_LOG_AUTO) and (
                config.getint('output') &
            (config.OUT_LOG_FILE | config.OUT_LOG_EDSM)):
            monitor.enable_logging()
            monitor.start(self.w)
            edproxy.start(self.w)

        # First run
        if not config.get('username') or not config.get('password'):
            prefs.PreferencesDialog(self.w, self.postprefs)
        else:
            self.login()