From c1b8533cb41c2e33d63311dac120ff7b0ddd4c29 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Wed, 27 Mar 2024 21:22:35 -0400 Subject: [PATCH] [2186] Simplify myNB Files --- docs/examples/click_counter/load.py | 4 +- myNotebook.py | 95 ++++++++++++----------------- plugins/coriolis.py | 8 +-- plugins/edsm.py | 8 +-- plugins/inara.py | 4 +- prefs.py | 22 +++---- 6 files changed, 62 insertions(+), 79 deletions(-) diff --git a/docs/examples/click_counter/load.py b/docs/examples/click_counter/load.py index ad90a084..f7f23837 100644 --- a/docs/examples/click_counter/load.py +++ b/docs/examples/click_counter/load.py @@ -7,6 +7,8 @@ from __future__ import annotations import logging import tkinter as tk +from tkinter import ttk + import myNotebook as nb # noqa: N813 from config import appname, config @@ -63,7 +65,7 @@ class ClickCounter: # setup our config in a "Click Count: number" nb.Label(frame, text='Click Count').grid(row=current_row) - nb.Entry(frame, textvariable=self.click_count).grid(row=current_row, column=1) + ttk.Entry(frame, textvariable=self.click_count).grid(row=current_row, column=1) current_row += 1 # Always increment our row counter, makes for far easier tkinter design. return frame diff --git a/myNotebook.py b/myNotebook.py index efae591c..528664ba 100644 --- a/myNotebook.py +++ b/myNotebook.py @@ -1,12 +1,9 @@ """ Custom `ttk.Notebook` to fix various display issues. -Hacks to fix various display issues with notebooks and their child widgets on -OSX and Windows. +Hacks to fix various display issues with notebooks and their child widgets on Windows. - Windows: page background should be White, not SystemButtonFace -- OSX: page background should be a darker gray than systemWindowBody - selected tab foreground should be White when the window is active Entire file may be imported by plugins. """ @@ -26,24 +23,17 @@ class Notebook(ttk.Notebook): def __init__(self, master: ttk.Frame | None = None, **kw): - ttk.Notebook.__init__(self, master, **kw) + super().__init__(master, **kw) style = ttk.Style() - - if sys.platform == 'win32': - style.configure('nb.TFrame', background=PAGEBG) - style.configure('nb.TButton', background=PAGEBG) - style.configure('nb.TCheckbutton', foreground=PAGEFG, background=PAGEBG) - style.configure('nb.TMenubutton', foreground=PAGEFG, background=PAGEBG) - style.configure('nb.TRadiobutton', foreground=PAGEFG, background=PAGEBG) - self.grid(padx=10, pady=10, sticky=tk.NSEW) - else: - self.grid(padx=10, pady=10, sticky=tk.NSEW) + style.configure('nb.TFrame', background=PAGEBG) + style.configure('nb.TButton', background=PAGEBG) + style.configure('nb.TCheckbutton', foreground=PAGEFG, background=PAGEBG) + style.configure('nb.TMenubutton', foreground=PAGEFG, background=PAGEBG) + style.configure('nb.TRadiobutton', foreground=PAGEFG, background=PAGEBG) + self.grid(padx=10, pady=10, sticky=tk.NSEW) -# FIXME: The real fix for this 'dynamic type' would be to split this whole -# thing into being a module with per-platform files, as we've done with config -# That would also make the code cleaner. -class Frame(sys.platform == 'darwin' and tk.Frame or ttk.Frame): # type: ignore +class Frame(tk.Frame or ttk.Frame): # type: ignore """Custom t(t)k.Frame class to fix some display issues.""" def __init__(self, master: ttk.Notebook | None = None, **kw): @@ -60,26 +50,25 @@ class Label(tk.Label): """Custom tk.Label class to fix some display issues.""" def __init__(self, master: ttk.Frame | None = None, **kw): - # This format chosen over `sys.platform in (...)` as mypy and friends dont understand that - if sys.platform == 'win32': - kw['foreground'] = kw.pop('foreground', PAGEFG) - kw['background'] = kw.pop('background', PAGEBG) - else: - kw['foreground'] = kw.pop('foreground', ttk.Style().lookup('TLabel', 'foreground')) - kw['background'] = kw.pop('background', ttk.Style().lookup('TLabel', 'background')) - tk.Label.__init__(self, master, **kw) # Just use tk.Label on all platforms + kw['foreground'] = kw.pop('foreground', PAGEFG if sys.platform == 'win32' + else ttk.Style().lookup('TLabel', 'foreground')) + kw['background'] = kw.pop('background', PAGEBG if sys.platform == 'win32' + else ttk.Style().lookup('TLabel', 'background')) + super().__init__(master, **kw) -class Entry(sys.platform == 'darwin' and tk.Entry or ttk.Entry): # type: ignore +class Entry(ttk.Entry): # type: ignore """Custom t(t)k.Entry class to fix some display issues.""" + # DEPRECATED: Migrate to ttk.Entry. Will remove in 5.12 or later. def __init__(self, master: ttk.Frame | None = None, **kw): - ttk.Entry.__init__(self, master, **kw) + super().__init__(master, **kw) -class Button(sys.platform == 'darwin' and tk.Button or ttk.Button): # type: ignore +class Button(tk.Button or ttk.Button): # type: ignore """Custom t(t)k.Button class to fix some display issues.""" + # DEPRECATED: Migrate to ttk.Button. Will remove in 5.12 or later. def __init__(self, master: ttk.Frame | None = None, **kw): if sys.platform == 'win32': ttk.Button.__init__(self, master, style='nb.TButton', **kw) @@ -87,47 +76,39 @@ class Button(sys.platform == 'darwin' and tk.Button or ttk.Button): # type: ign ttk.Button.__init__(self, master, **kw) -class ColoredButton(sys.platform == 'darwin' and tk.Label or tk.Button): # type: ignore +class ColoredButton(tk.Label or tk.Button): # type: ignore """Custom t(t)k.ColoredButton class to fix some display issues.""" + # DEPRECATED: Migrate to tk.Button. Will remove in 5.12 or later. def __init__(self, master: ttk.Frame | None = None, **kw): tk.Button.__init__(self, master, **kw) -class Checkbutton(sys.platform == 'darwin' and tk.Checkbutton or ttk.Checkbutton): # type: ignore +class Checkbutton(ttk.Checkbutton): """Custom t(t)k.Checkbutton class to fix some display issues.""" - def __init__(self, master: ttk.Frame | None = None, **kw): - if sys.platform == 'win32': - ttk.Checkbutton.__init__(self, master, style='nb.TCheckbutton', **kw) - else: - ttk.Checkbutton.__init__(self, master, **kw) + def __init__(self, master=None, **kw): + style = 'nb.TCheckbutton' if sys.platform == 'win32' else None + super().__init__(master, style=style, **kw) # type: ignore -class Radiobutton(sys.platform == 'darwin' and tk.Radiobutton or ttk.Radiobutton): # type: ignore +class Radiobutton(ttk.Radiobutton): """Custom t(t)k.Radiobutton class to fix some display issues.""" def __init__(self, master: ttk.Frame | None = None, **kw): - if sys.platform == 'win32': - ttk.Radiobutton.__init__(self, master, style='nb.TRadiobutton', **kw) - else: - ttk.Radiobutton.__init__(self, master, **kw) + style = 'nb.TRadiobutton' if sys.platform == 'win32' else None + super().__init__(master, style=style, **kw) # type: ignore -class OptionMenu(sys.platform == 'darwin' and tk.OptionMenu or ttk.OptionMenu): # type: ignore - """Custom t(t)k.OptionMenu class to fix some display issues.""" +class OptionMenu(ttk.OptionMenu): + """Custom ttk.OptionMenu class to fix some display issues.""" def __init__(self, master, variable, default=None, *values, **kw): - if sys.platform == 'win32': - # OptionMenu derives from Menubutton at the Python level, so uses Menubutton's style - ttk.OptionMenu.__init__(self, master, variable, default, *values, style='nb.TMenubutton', **kw) - self['menu'].configure(background=PAGEBG) - # Workaround for https://bugs.python.org/issue25684 - for i in range(0, self['menu'].index('end')+1): - self['menu'].entryconfig(i, variable=variable) - else: - ttk.OptionMenu.__init__(self, master, variable, default, *values, **kw) - self['menu'].configure(background=ttk.Style().lookup('TMenu', 'background')) - # Workaround for https://bugs.python.org/issue25684 - for i in range(0, self['menu'].index('end')+1): - self['menu'].entryconfig(i, variable=variable) + style = 'nb.TMenubutton' if sys.platform == 'win32' else ttk.Style().lookup('TMenu', 'background') + menu_background = PAGEBG if sys.platform == 'win32' else ttk.Style().lookup('TMenu', 'background') + + super().__init__(master, variable, default, *values, style=style, **kw) + self['menu'].configure(background=menu_background) + + for i in range(self['menu'].index('end') + 1): + self['menu'].entryconfig(i, variable=variable) diff --git a/plugins/coriolis.py b/plugins/coriolis.py index c142c686..20da16b1 100644 --- a/plugins/coriolis.py +++ b/plugins/coriolis.py @@ -106,12 +106,12 @@ def plugin_prefs(parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> tk.Fr # LANG: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL nb.Label(conf_frame, text=_('Normal URL')).grid(sticky=tk.W, row=cur_row, column=0, padx=PADX, pady=PADY) - nb.Entry(conf_frame, + ttk.Entry(conf_frame, textvariable=coriolis_config.normal_textvar).grid( sticky=tk.EW, row=cur_row, column=1, padx=PADX, pady=BOXY ) # LANG: Generic 'Reset' button label - nb.Button(conf_frame, text=_("Reset"), + ttk.Button(conf_frame, text=_("Reset"), command=lambda: coriolis_config.normal_textvar.set(value=DEFAULT_NORMAL_URL)).grid( sticky=tk.W, row=cur_row, column=2, padx=PADX, pady=0 ) @@ -119,11 +119,11 @@ def plugin_prefs(parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> tk.Fr # LANG: Settings>Coriolis: Label for 'alpha/beta game version' URL nb.Label(conf_frame, text=_('Beta URL')).grid(sticky=tk.W, row=cur_row, column=0, padx=PADX, pady=PADY) - nb.Entry(conf_frame, textvariable=coriolis_config.beta_textvar).grid( + ttk.Entry(conf_frame, textvariable=coriolis_config.beta_textvar).grid( sticky=tk.EW, row=cur_row, column=1, padx=PADX, pady=BOXY ) # LANG: Generic 'Reset' button label - nb.Button(conf_frame, text=_('Reset'), + ttk.Button(conf_frame, text=_('Reset'), command=lambda: coriolis_config.beta_textvar.set(value=DEFAULT_BETA_URL)).grid( sticky=tk.W, row=cur_row, column=2, padx=PADX, pady=0 ) diff --git a/plugins/edsm.py b/plugins/edsm.py index 46d05f4c..146dd5ab 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -113,10 +113,10 @@ class This: self.cmdr_text: nb.Label | None = None self.user_label: nb.Label | None = None - self.user: nb.Entry | None = None + self.user: ttk.Entry | None = None self.apikey_label: nb.Label | None = None - self.apikey: nb.Entry | None = None + self.apikey: ttk.Entry | None = None this = This() @@ -345,14 +345,14 @@ def plugin_prefs(parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> tk.Fr # LANG: EDSM Commander name label in EDSM settings this.user_label = nb.Label(frame, text=_('Commander Name')) this.user_label.grid(row=cur_row, padx=PADX, pady=PADY, sticky=tk.W) - this.user = nb.Entry(frame) + this.user = ttk.Entry(frame) this.user.grid(row=cur_row, column=1, padx=PADX, pady=BOXY, sticky=tk.EW) cur_row += 1 # LANG: EDSM API key label this.apikey_label = nb.Label(frame, text=_('API Key')) this.apikey_label.grid(row=cur_row, padx=PADX, pady=PADY, sticky=tk.W) - this.apikey = nb.Entry(frame, show="*", width=50) + this.apikey = ttk.Entry(frame, show="*", width=50) this.apikey.grid(row=cur_row, column=1, padx=PADX, pady=BOXY, sticky=tk.EW) cur_row += 1 diff --git a/plugins/inara.py b/plugins/inara.py index 0e0eb7bf..d96e05ef 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -125,7 +125,7 @@ class This: self.log: 'tk.IntVar' self.log_button: nb.Checkbutton self.label: HyperlinkLabel - self.apikey: nb.Entry + self.apikey: ttk.Entry self.apikey_label: tk.Label self.events: dict[Credentials, Deque[Event]] = defaultdict(deque) @@ -292,7 +292,7 @@ def plugin_prefs(parent: ttk.Notebook, cmdr: str, is_beta: bool) -> tk.Frame: # LANG: Inara API key label this.apikey_label = nb.Label(frame, text=_('API Key')) # Inara setting this.apikey_label.grid(row=cur_row, padx=PADX, pady=PADY, sticky=tk.W) - this.apikey = nb.Entry(frame, show="*", width=50) + this.apikey = ttk.Entry(frame, show="*", width=50) this.apikey.grid(row=cur_row, column=1, padx=PADX, pady=BOXY, sticky=tk.EW) cur_row += 1 diff --git a/prefs.py b/prefs.py index 862bda27..ef43c5de 100644 --- a/prefs.py +++ b/prefs.py @@ -361,12 +361,12 @@ class PreferencesDialog(tk.Toplevel): # Type ignored due to incorrect type annotation. a 2 tuple does padding for each side self.outdir_label.grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=row.get()) # type: ignore - self.outdir_entry = nb.Entry(output_frame, takefocus=False) + self.outdir_entry = ttk.Entry(output_frame, takefocus=False) self.outdir_entry.grid(columnspan=2, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get()) text = (_('Browse...')) # LANG: NOT-macOS Settings - files location selection button - self.outbutton = nb.Button( + self.outbutton = ttk.Button( output_frame, text=text, # Technically this is different from the label in Settings > Output, as *this* is used @@ -399,7 +399,7 @@ class PreferencesDialog(tk.Toplevel): logdir = default self.logdir.set(logdir) - self.logdir_entry = nb.Entry(config_frame, takefocus=False) + self.logdir_entry = ttk.Entry(config_frame, takefocus=False) # Location of the Journal files nb.Label( @@ -413,7 +413,7 @@ class PreferencesDialog(tk.Toplevel): text = (_('Browse...')) # LANG: NOT-macOS Setting - files location selection button with row as cur_row: - self.logbutton = nb.Button( + self.logbutton = ttk.Button( config_frame, text=text, # LANG: Settings > Configuration - Label for Journal files location @@ -423,7 +423,7 @@ class PreferencesDialog(tk.Toplevel): if config.default_journal_dir_path: # Appearance theme and language setting - nb.Button( + ttk.Button( config_frame, # LANG: Settings > Configuration - Label on 'reset journal files location to default' button text=_('Default'), @@ -465,7 +465,7 @@ class PreferencesDialog(tk.Toplevel): text=_('Hotkey') # LANG: Hotkey/Shortcut settings prompt on Windows ).grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row) - self.hotkey_text = nb.Entry(config_frame, width=30, justify=tk.CENTER) + self.hotkey_text = ttk.Entry(config_frame, width=30, justify=tk.CENTER) self.hotkey_text.insert( 0, # No hotkey/shortcut currently defined @@ -623,7 +623,7 @@ class PreferencesDialog(tk.Toplevel): self.loglevel_dropdown.configure(width=15) self.loglevel_dropdown.grid(column=1, pady=self.BOXY, sticky=tk.W, row=cur_row) - nb.Button( + ttk.Button( config_frame, # LANG: Label on button used to open a filesystem folder text=_('Open Log Folder'), # Button that opens a folder in Explorer/Finder @@ -726,7 +726,7 @@ class PreferencesDialog(tk.Toplevel): self.theme_label_0.grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row) # Main window - self.theme_button_0 = nb.ColoredButton( + self.theme_button_0 = tk.Button( appearance_frame, # LANG: Appearance - Example 'Normal' text text=_('Station'), @@ -739,7 +739,7 @@ class PreferencesDialog(tk.Toplevel): with row as cur_row: self.theme_label_1 = nb.Label(appearance_frame, text=self.theme_prompts[1]) self.theme_label_1.grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row) - self.theme_button_1 = nb.ColoredButton( + self.theme_button_1 = tk.Button( appearance_frame, text=' Hutton Orbital ', # Do not translate background='grey4', @@ -870,7 +870,7 @@ class PreferencesDialog(tk.Toplevel): padx=self.PADX, pady=self.PADY, sticky=tk.W, row=row.get() ) - plugdirentry = nb.Entry(plugins_frame, justify=tk.LEFT) + plugdirentry = ttk.Entry(plugins_frame, justify=tk.LEFT) self.displaypath(plugdir, plugdirentry) plugdirentry.grid(columnspan=2, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get()) @@ -882,7 +882,7 @@ class PreferencesDialog(tk.Toplevel): text=_("Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name").format(EXT='.disabled') ).grid(columnspan=2, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) - nb.Button( + ttk.Button( plugins_frame, # LANG: Label on button used to open a filesystem folder text=_('Open'), # Button that opens a folder in Explorer/Finder