mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-13 07:47:14 +03:00
themes: Use defined constants for which theme throughout
This has been relying on knowledge of the magic numbers for far too long. As part of this, remove all the obfuscating "oh, default is 0, and we want that or any other theme, so treat this like a boolean" nonsense. Also, stop assuming that "> 1" is a synonym for "transparent theme". Just Do The Equality Check.
This commit is contained in:
parent
0f5f625cfd
commit
62e285b52e
@ -1799,18 +1799,14 @@ class AppWindow(object):
|
||||
|
||||
def onenter(self, event=None) -> None:
|
||||
"""Handle when our window gains focus."""
|
||||
# TODO: This assumes that 1) transparent is at least 2, 2) there are
|
||||
# no new themes added after that.
|
||||
if config.get_int('theme') > 1:
|
||||
if config.get_int('theme') == theme.THEME_TRANSPARENT:
|
||||
self.w.attributes("-transparentcolor", '')
|
||||
self.blank_menubar.grid_remove()
|
||||
self.theme_menubar.grid(row=0, columnspan=2, sticky=tk.NSEW)
|
||||
|
||||
def onleave(self, event=None) -> None:
|
||||
"""Handle when our window loses focus."""
|
||||
# TODO: This assumes that 1) transparent is at least 2, 2) there are
|
||||
# no new themes added after that.
|
||||
if config.get_int('theme') > 1 and event.widget == self.w:
|
||||
if config.get_int('theme') == theme.THEME_TRANSPARENT and event.widget == self.w:
|
||||
self.w.attributes("-transparentcolor", 'grey4')
|
||||
self.theme_menubar.grid_remove()
|
||||
self.blank_menubar.grid(row=0, columnspan=2, sticky=tk.NSEW)
|
||||
@ -1887,7 +1883,7 @@ sys.path: {sys.path}'''
|
||||
)
|
||||
|
||||
if args.reset_ui:
|
||||
config.set('theme', 0) # 'Default' theme uses ID 0
|
||||
config.set('theme', theme.THEME_DEFAULT)
|
||||
config.set('ui_transparency', 100) # 100 is completely opaque
|
||||
config.delete('font', suppress=True)
|
||||
config.delete('font_size', suppress=True)
|
||||
|
15
prefs.py
15
prefs.py
@ -308,6 +308,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
button.bind("<Return>", lambda event: self.apply())
|
||||
self.protocol("WM_DELETE_WINDOW", self._destroy)
|
||||
|
||||
# FIXME: Why are these being called when *creating* the Settings window?
|
||||
# Selectively disable buttons depending on output settings
|
||||
self.cmdrchanged()
|
||||
self.themevarchanged()
|
||||
@ -733,13 +734,14 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# Appearance theme and language setting
|
||||
nb.Radiobutton(
|
||||
# LANG: Label for 'Default' theme radio button
|
||||
appearance_frame, text=_('Default'), variable=self.theme, value=0, command=self.themevarchanged
|
||||
appearance_frame, text=_('Default'), variable=self.theme,
|
||||
value=theme.THEME_DEFAULT, command=self.themevarchanged
|
||||
).grid(columnspan=3, padx=self.BUTTONX, sticky=tk.W, row=row.get())
|
||||
|
||||
# Appearance theme setting
|
||||
nb.Radiobutton(
|
||||
# LANG: Label for 'Dark' theme radio button
|
||||
appearance_frame, text=_('Dark'), variable=self.theme, value=1, command=self.themevarchanged
|
||||
appearance_frame, text=_('Dark'), variable=self.theme, value=theme.THEME_DARK, command=self.themevarchanged
|
||||
).grid(columnspan=3, padx=self.BUTTONX, sticky=tk.W, row=row.get())
|
||||
|
||||
if sys.platform == 'win32':
|
||||
@ -748,7 +750,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# LANG: Label for 'Transparent' theme radio button
|
||||
text=_('Transparent'), # Appearance theme setting
|
||||
variable=self.theme,
|
||||
value=2,
|
||||
value=theme.THEME_TRANSPARENT,
|
||||
command=self.themevarchanged
|
||||
).grid(columnspan=3, padx=self.BUTTONX, sticky=tk.W, row=row.get())
|
||||
|
||||
@ -1149,7 +1151,12 @@ class PreferencesDialog(tk.Toplevel):
|
||||
"""Update theme examples."""
|
||||
self.theme_button_0['foreground'], self.theme_button_1['foreground'] = self.theme_colors
|
||||
|
||||
state = tk.NORMAL if self.theme.get() else tk.DISABLED
|
||||
if self.theme.get() == theme.THEME_DEFAULT:
|
||||
state = tk.DISABLED # type: ignore
|
||||
|
||||
else:
|
||||
state = tk.NORMAL # type: ignore
|
||||
|
||||
self.theme_label_0['state'] = state
|
||||
self.theme_label_1['state'] = state
|
||||
self.theme_button_0['state'] = state
|
||||
|
107
theme.py
107
theme.py
@ -259,24 +259,7 @@ class _Theme(object):
|
||||
if not config.get_str('dark_highlight'):
|
||||
config.set('dark_highlight', 'white')
|
||||
|
||||
if theme:
|
||||
# Dark
|
||||
(r, g, b) = root.winfo_rgb(config.get_str('dark_text'))
|
||||
self.current = {
|
||||
'background': 'grey4', # OSX inactive dark titlebar color
|
||||
'foreground': config.get_str('dark_text'),
|
||||
'activebackground': config.get_str('dark_text'),
|
||||
'activeforeground': 'grey4',
|
||||
'disabledforeground': f'#{int(r/384):02x}{int(g/384):02x}{int(b/384):02x}',
|
||||
'highlight': config.get_str('dark_highlight'),
|
||||
# Font only supports Latin 1 / Supplement / Extended, and a
|
||||
# few General Punctuation and Mathematical Operators
|
||||
# LANG: Label for commander name in main window
|
||||
'font': (theme > 1 and not 0x250 < ord(_('Cmdr')[0]) < 0x3000 and
|
||||
tk_font.Font(family='Euro Caps', size=10, weight=tk_font.NORMAL) or
|
||||
'TkDefaultFont'),
|
||||
}
|
||||
else:
|
||||
if theme == self.THEME_DEFAULT:
|
||||
# (Mostly) system colors
|
||||
style = ttk.Style()
|
||||
self.current = {
|
||||
@ -292,9 +275,30 @@ class _Theme(object):
|
||||
'font': 'TkDefaultFont',
|
||||
}
|
||||
|
||||
# Apply current theme to a widget and its children, and register it for future updates
|
||||
else: # Dark *or* Transparent
|
||||
(r, g, b) = root.winfo_rgb(config.get_str('dark_text'))
|
||||
self.current = {
|
||||
'background': 'grey4', # OSX inactive dark titlebar color
|
||||
'foreground': config.get_str('dark_text'),
|
||||
'activebackground': config.get_str('dark_text'),
|
||||
'activeforeground': 'grey4',
|
||||
'disabledforeground': f'#{int(r/384):02x}{int(g/384):02x}{int(b/384):02x}',
|
||||
'highlight': config.get_str('dark_highlight'),
|
||||
# Font only supports Latin 1 / Supplement / Extended, and a
|
||||
# few General Punctuation and Mathematical Operators
|
||||
# LANG: Label for commander name in main window
|
||||
'font': (theme > 1 and not 0x250 < ord(_('Cmdr')[0]) < 0x3000 and
|
||||
tk_font.Font(family='Euro Caps', size=10, weight=tk_font.NORMAL) or
|
||||
'TkDefaultFont'),
|
||||
}
|
||||
|
||||
def update(self, widget: tk.Widget) -> None:
|
||||
"""
|
||||
Apply current theme to a widget and its children.
|
||||
|
||||
Also, register it for future updates.
|
||||
:param widget: Target widget.
|
||||
"""
|
||||
assert isinstance(widget, tk.Widget) or isinstance(widget, tk.BitmapImage), widget
|
||||
if not self.current:
|
||||
return # No need to call this for widgets created in plugin_app()
|
||||
@ -375,8 +379,7 @@ class _Theme(object):
|
||||
|
||||
# Apply configured theme
|
||||
|
||||
def apply(self, root: tk.Tk) -> None: # noqa: CCR001
|
||||
|
||||
def apply(self, root: tk.Tk) -> None: # noqa: CCR001, C901
|
||||
theme = config.get_int('theme')
|
||||
self._colors(root, theme)
|
||||
|
||||
@ -392,25 +395,31 @@ class _Theme(object):
|
||||
for widget in pair:
|
||||
widget.grid_remove()
|
||||
if isinstance(pair[0], tk.Menu):
|
||||
if theme:
|
||||
if theme == self.THEME_DEFAULT:
|
||||
root['menu'] = pair[0]
|
||||
|
||||
else: # Dark *or* Transparent
|
||||
root['menu'] = ''
|
||||
pair[theme].grid(**gridopts)
|
||||
else:
|
||||
root['menu'] = pair[0]
|
||||
|
||||
else:
|
||||
pair[theme].grid(**gridopts)
|
||||
|
||||
if self.active == theme:
|
||||
return # Don't need to mess with the window manager
|
||||
|
||||
else:
|
||||
self.active = theme
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
from AppKit import NSAppearance, NSApplication, NSMiniaturizableWindowMask, NSResizableWindowMask
|
||||
root.update_idletasks() # need main window to be created
|
||||
appearance = NSAppearance.appearanceNamed_(theme and
|
||||
'NSAppearanceNameDarkAqua' or
|
||||
'NSAppearanceNameAqua')
|
||||
if theme == self.THEME_DEFAULT:
|
||||
appearance = NSAppearance.appearanceNamed_('NSAppearanceNameAqua')
|
||||
|
||||
else: # Dark (Transparent only on win32)
|
||||
appearance = NSAppearance.appearanceNamed_('NSAppearanceNameDarkAqua')
|
||||
|
||||
for window in NSApplication.sharedApplication().windows():
|
||||
window.setStyleMask_(window.styleMask() & ~(
|
||||
NSMiniaturizableWindowMask | NSResizableWindowMask)) # disable zoom
|
||||
@ -426,14 +435,30 @@ class _Theme(object):
|
||||
GetWindowLongW = ctypes.windll.user32.GetWindowLongW # noqa: N806 # ctypes
|
||||
SetWindowLongW = ctypes.windll.user32.SetWindowLongW # noqa: N806 # ctypes
|
||||
|
||||
root.overrideredirect(theme and True or False)
|
||||
root.attributes("-transparentcolor", theme > 1 and 'grey4' or '')
|
||||
# FIXME: Lose the "treat this like a boolean" bullshit
|
||||
if theme == self.THEME_DEFAULT:
|
||||
root.overrideredirect(False)
|
||||
|
||||
else:
|
||||
root.overrideredirect(True)
|
||||
|
||||
if theme == self.THEME_TRANSPARENT:
|
||||
root.attributes("-transparentcolor", 'grey4')
|
||||
|
||||
else:
|
||||
root.attributes("-transparentcolor", '')
|
||||
|
||||
root.withdraw()
|
||||
root.update_idletasks() # Size and windows styles get recalculated here
|
||||
hwnd = ctypes.windll.user32.GetParent(root.winfo_id())
|
||||
SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) & ~WS_MAXIMIZEBOX) # disable maximize
|
||||
SetWindowLongW(hwnd, GWL_EXSTYLE, theme > 1 and WS_EX_APPWINDOW |
|
||||
WS_EX_LAYERED or WS_EX_APPWINDOW) # Add to taskbar
|
||||
|
||||
if theme == self.THEME_TRANSPARENT:
|
||||
SetWindowLongW(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYERED) # Add to taskbar
|
||||
|
||||
else:
|
||||
SetWindowLongW(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW) # Add to taskbar
|
||||
|
||||
root.deiconify()
|
||||
root.wait_visibility() # need main window to be displayed before returning
|
||||
|
||||
@ -446,11 +471,25 @@ class _Theme(object):
|
||||
children = Window()
|
||||
nchildren = c_uint()
|
||||
XQueryTree(dpy, root.winfo_id(), byref(xroot), byref(parent), byref(children), byref(nchildren))
|
||||
XChangeProperty(dpy, parent, motif_wm_hints_property, motif_wm_hints_property, 32,
|
||||
PropModeReplace, theme and motif_wm_hints_dark or motif_wm_hints_normal, 5)
|
||||
if theme == self.THEME_DEFAULT:
|
||||
wm_hints = motif_wm_hints_normal
|
||||
|
||||
else: # Dark *or* Transparent
|
||||
wm_hints = motif_wm_hints_dark
|
||||
|
||||
XChangeProperty(
|
||||
dpy, parent, motif_wm_hints_property, motif_wm_hints_property, 32, PropModeReplace, wm_hints, 5
|
||||
)
|
||||
|
||||
XFlush(dpy)
|
||||
|
||||
else:
|
||||
root.overrideredirect(theme and 1 or 0)
|
||||
if theme == self.THEME_DEFAULT:
|
||||
root.overrideredirect(False)
|
||||
|
||||
else: # Dark *or* Transparent
|
||||
root.overrideredirect(True)
|
||||
|
||||
root.deiconify()
|
||||
root.wait_visibility() # need main window to be displayed before returning
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user