"""Central Tk style configuration for the native dashboard.""" from __future__ import annotations from typing import Any def _settings_checkbox_image( root: Any, *, size: int, gap: int, fill: str, border: str, mark: str | None = None, ) -> Any: """Create one scaled checkbox indicator from the launcher palette.""" import tkinter as tk image = tk.PhotoImage(master=root, width=size + gap, height=size) border_width = max(1, round(size / 16)) image.put(fill, to=(0, 0, size, size)) image.put(border, to=(0, 0, size, border_width)) image.put(border, to=(0, size - border_width, size, size)) image.put(border, to=(0, 0, border_width, size)) image.put(border, to=(size - border_width, 0, size, size)) if mark is not None: stroke = max(2, round(size / 8)) for source_x, source_y in ( (4, 8), (5, 9), (6, 10), (7, 11), (8, 10), (9, 9), (10, 8), (11, 7), (12, 6), ): x = round(source_x * size / 16) y = round(source_y * size / 16) image.put( mark, to=( x, y, min(size - border_width, x + stroke), min(size - border_width, y + stroke), ), ) return image def _configure_settings_checkbox_indicator( root: Any, style: Any, launcher_ui_scale: float, ) -> None: """Replace the platform X indicator with the launcher's checkmark.""" element_name = "Settings.Checkbutton.indicator" if element_name in style.element_names(): return size = max(16, round(16 * launcher_ui_scale)) gap = max(9, round(9 * launcher_ui_scale)) palettes = { "unchecked": ("#100d0c", "#6a4d38", None), "unchecked_active": ("#211916", "#d98927", None), "unchecked_focus": ("#100d0c", "#f4bd61", None), "checked": ("#d98927", "#f4bd61", "#24170f"), "checked_active": ("#efaa4c", "#fff0c2", "#24170f"), "checked_focus": ("#d98927", "#fff0c2", "#24170f"), "disabled": ("#171412", "#30251f", None), "checked_disabled": ("#6c4826", "#776b62", "#30251f"), } images = { name: _settings_checkbox_image( root, size=size, gap=gap, fill=fill, border=border, mark=mark, ) for name, (fill, border, mark) in palettes.items() } style.element_create( element_name, "image", images["unchecked"], ("disabled selected", images["checked_disabled"]), ("disabled", images["disabled"]), ("pressed selected", images["checked_active"]), ("active selected", images["checked_active"]), ("focus selected", images["checked_focus"]), ("selected", images["checked"]), ("pressed", images["unchecked_active"]), ("active", images["unchecked_active"]), ("focus", images["unchecked_focus"]), ) style.layout( "Settings.TCheckbutton", [ ( "Checkbutton.padding", { "sticky": "nswe", "children": [ (element_name, {"side": "left", "sticky": ""}), ( "Checkbutton.focus", { "side": "left", "sticky": "w", "children": [ ( "Checkbutton.label", {"sticky": "nswe"}, ) ], }, ), ], }, ), ], ) setattr(root, "_ptlinux_settings_checkbox_images", tuple(images.values())) def configure_dashboard_style(root: Any, ttk: Any, launcher_ui_scale: float) -> None: style = ttk.Style(root) style.theme_use("clam") style.configure("Root.TFrame", background="#0c0908") style.configure("Surface.TFrame", background="#191311") style.configure("Hero.TFrame", background="#24170f") style.configure("Card.TFrame", background="#211916") style.configure( "Brand.TLabel", background="#0c0908", foreground="#f5d18b", font=("Georgia", 21, "bold"), ) style.configure( "Tagline.TLabel", background="#0c0908", foreground="#a8998a", font=("Sans", 8), ) style.configure( "Section.TLabel", background="#191311", foreground="#f0d7a2", font=("Sans", 9, "bold"), ) style.configure( "HeroTitle.TLabel", background="#24170f", foreground="#fff2d3", font=("Georgia", 17, "bold"), ) style.configure( "HeroText.TLabel", background="#24170f", foreground="#d6c6b3", font=("Sans", 10), ) style.configure( "Status.TLabel", background="#191311", foreground="#dfd1c1", font=("Sans", 9), ) style.configure( "Muted.TLabel", background="#191311", foreground="#aa9a8b", font=("Sans", 8), ) style.configure( "ServerHeading.TLabel", background="#191311", foreground="#d8aa61", font=("Sans", 8, "bold"), padding=(0, 3), ) style.configure( "ServerOnline.TLabel", background="#102719", foreground="#58e27a", font=("Sans", 8, "bold"), padding=(8, 3), anchor="w", ) style.configure( "ServerOffline.TLabel", background="#301514", foreground="#ff6258", font=("Sans", 8, "bold"), padding=(8, 3), anchor="w", ) style.configure( "ServerUnknown.TLabel", background="#211916", foreground="#b8a99a", font=("Sans", 8), padding=(8, 3), anchor="w", ) style.configure( "Speed.TLabel", background="#191311", foreground="#e5b66c", font=("Monospace", 8, "bold"), ) style.configure( "SettingsTitle.TLabel", background="#191311", foreground="#fff0d2", font=("Georgia", 16, "bold"), ) style.configure( "SettingsText.TLabel", background="#191311", foreground="#e5b66c", font=("Sans", 8, "bold"), ) style.configure( "SettingsHint.TLabel", background="#191311", foreground="#aa9a8b", font=("Sans", 8), ) style.configure( "SettingsCard.TLabelframe", background="#191311", bordercolor="#4a3528", lightcolor="#4a3528", darkcolor="#120e0c", borderwidth=1, relief="solid", ) style.configure( "SettingsCard.TLabelframe.Label", background="#191311", foreground="#f0d7a2", font=("Sans", 9, "bold"), ) style.configure("SettingsCard.TFrame", background="#191311") style.configure( "Update.Treeview", background="#100d0c", fieldbackground="#100d0c", foreground="#ded1c4", rowheight=max(24, round(24 * launcher_ui_scale)), bordercolor="#4a3528", ) style.configure( "Update.Treeview.Heading", background="#2a201c", foreground="#f0d7a2", font=("Sans", 8, "bold"), bordercolor="#4a3528", lightcolor="#4a3528", darkcolor="#120e0c", relief="flat", ) style.map( "Update.Treeview.Heading", background=[("active", "#2a201c"), ("pressed", "#2a201c")], foreground=[("active", "#f0d7a2"), ("pressed", "#f0d7a2")], relief=[("active", "flat"), ("pressed", "flat")], ) style.map( "Update.Treeview", background=[("selected", "#6a482d")], foreground=[("selected", "#ffffff")], ) style.configure("SettingsFooter.TFrame", background="#100d0c") style.configure( "SettingsFooter.TLabel", background="#100d0c", foreground="#aa9a8b", font=("Sans", 8), ) style.configure( "Settings.TEntry", fieldbackground="#100d0c", foreground="#f8ead2", insertcolor="#f4bd61", selectbackground="#6a482d", selectforeground="#fff8e9", font=("Sans", 9), padding=(10, 7), bordercolor="#4a3528", lightcolor="#4a3528", darkcolor="#4a3528", borderwidth=1, relief="flat", focuscolor="#f4bd61", focusthickness=1, ) style.map( "Settings.TEntry", fieldbackground=[ ("disabled", "#171412"), ("!disabled", "#100d0c"), ], foreground=[ ("disabled", "#776b62"), ("!disabled", "#f8ead2"), ], bordercolor=[ ("disabled", "#30251f"), ("focus", "#f4bd61"), ("!disabled", "#4a3528"), ], lightcolor=[ ("focus", "#f4bd61"), ("!focus", "#4a3528"), ], darkcolor=[ ("focus", "#f4bd61"), ("!focus", "#4a3528"), ], ) style.configure( "Settings.TCombobox", fieldbackground="#100d0c", background="#191311", foreground="#f8ead2", arrowcolor="#e5b66c", selectbackground="#6a482d", selectforeground="#fff8e9", font=("Sans", 9), padding=(10, 7), arrowsize=max(12, round(12 * launcher_ui_scale)), bordercolor="#4a3528", lightcolor="#4a3528", darkcolor="#4a3528", borderwidth=1, relief="flat", focuscolor="#f4bd61", focusthickness=1, ) style.map( "Settings.TCombobox", fieldbackground=[ ("disabled", "#171412"), ("readonly", "#100d0c"), ], background=[ ("disabled", "#171412"), ("pressed", "#32251f"), ("active", "#2a201c"), ("readonly", "#191311"), ], foreground=[ ("disabled", "#776b62"), ("readonly", "#f8ead2"), ], arrowcolor=[ ("disabled", "#776b62"), ("pressed", "#fff0c2"), ("active", "#f4bd61"), ("readonly", "#e5b66c"), ], bordercolor=[ ("disabled", "#30251f"), ("focus", "#f4bd61"), ("active", "#6a4d38"), ("readonly", "#4a3528"), ], lightcolor=[ ("focus", "#f4bd61"), ("!focus", "#4a3528"), ], darkcolor=[ ("focus", "#f4bd61"), ("!focus", "#4a3528"), ], ) root.option_add("*TCombobox*Listbox.background", "#100d0c") root.option_add("*TCombobox*Listbox.foreground", "#f8ead2") root.option_add("*TCombobox*Listbox.selectBackground", "#6a482d") root.option_add("*TCombobox*Listbox.selectForeground", "#fff8e9") root.option_add("*TCombobox*Listbox.font", "Sans 9") root.option_add("*TCombobox*Listbox.borderWidth", 1) root.option_add("*TCombobox*Listbox.highlightThickness", 1) root.option_add("*TCombobox*Listbox.highlightBackground", "#4a3528") root.option_add("*TCombobox*Listbox.highlightColor", "#f4bd61") root.option_add("*TCombobox*Listbox.relief", "flat") root.option_add("*TCombobox*Listbox.activeStyle", "none") style.configure( "Realm.TCombobox", fieldbackground="#211916", background="#211916", foreground="#fff0d2", arrowcolor="#d8aa61", bordercolor="#4a3528", lightcolor="#4a3528", darkcolor="#4a3528", font=("Sans", 9, "bold"), padding=(10, 7), relief="flat", ) style.map( "Realm.TCombobox", fieldbackground=[ ("disabled", "#171412"), ("readonly", "#211916"), ], background=[ ("disabled", "#171412"), ("active", "#2a201c"), ("readonly", "#211916"), ], foreground=[ ("disabled", "#887a70"), ("readonly", "#fff0d2"), ], arrowcolor=[ ("disabled", "#887a70"), ("active", "#f0d7a2"), ("readonly", "#d8aa61"), ], bordercolor=[ ("disabled", "#4a3528"), ("focus", "#6a4d38"), ("readonly", "#4a3528"), ], ) root.option_add("*realm_selector*Listbox.background", "#211916") root.option_add("*realm_selector*Listbox.foreground", "#fff0d2") root.option_add("*realm_selector*Listbox.selectBackground", "#2a201c") root.option_add("*realm_selector*Listbox.selectForeground", "#f0d7a2") root.option_add("*realm_selector*Listbox.font", "Sans 9 bold") root.option_add("*realm_selector*Listbox.justify", "center") root.option_add("*realm_selector*Listbox.selectBorderWidth", 4) root.option_add("*realm_selector*Listbox.borderWidth", 1) root.option_add("*realm_selector*Listbox.highlightThickness", 0) root.option_add("*realm_selector*Listbox.relief", "flat") root.option_add("*realm_selector*Listbox.activeStyle", "none") _configure_settings_checkbox_indicator(root, style, launcher_ui_scale) style.configure( "Settings.TCheckbutton", background="#171210", foreground="#d8cbbd", font=("Sans", 9), padding=(9, 7), relief="flat", focuscolor="#f4bd61", focusthickness=1, ) style.map( "Settings.TCheckbutton", background=[ ("disabled", "#15110f"), ("pressed", "#2a201c"), ("active", "#241b17"), ("selected", "#211916"), ("!selected", "#171210"), ], foreground=[ ("disabled", "#776b62"), ("active", "#fff0d2"), ("selected", "#f8ead2"), ], ) style.configure( "PreloaderStatus.TLabel", background="#0c0908", foreground="#dfd1c1", font=("Sans", 10), ) style.configure( "PreloaderMuted.TLabel", background="#0c0908", foreground="#aa9a8b", font=("Sans", 9), ) style.configure( "NewsTitle.TLabel", background="#211916", foreground="#fff0d2", font=("Sans", 9, "bold"), ) style.configure( "NewsMeta.TLabel", background="#211916", foreground="#d8aa61", font=("Sans", 9, "bold"), ) style.configure( "NewsBody.TLabel", background="#211916", foreground="#c9baaa", font=("Sans", 8), ) style.configure( "NewsTab.TButton", background="#191311", foreground="#9f8d7c", font=("Sans", 8, "bold"), padding=(10, 4), bordercolor="#32251f", borderwidth=1, relief="flat", focusthickness=0, ) style.map( "NewsTab.TButton", background=[("active", "#2a201c")], foreground=[("active", "#f0d7a2")], bordercolor=[("focus", "#f4bd61"), ("active", "#4a3528")], ) style.configure( "NewsTabActive.TButton", background="#2a201c", foreground="#f0d7a2", font=("Sans", 8, "bold"), padding=(10, 4), bordercolor="#6a4d38", borderwidth=1, relief="flat", focusthickness=0, ) style.map( "NewsTabActive.TButton", background=[("active", "#32251f")], foreground=[("active", "#fff0d2")], bordercolor=[("focus", "#f4bd61")], ) style.configure( "News.Vertical.TScrollbar", background="#4a3528", troughcolor="#191311", arrowcolor="#d8aa61", bordercolor="#191311", lightcolor="#4a3528", darkcolor="#32251f", ) style.map( "News.Vertical.TScrollbar", background=[ ("pressed", "#765034"), ("active", "#62452f"), ("!disabled", "#4a3528"), ], arrowcolor=[ ("pressed", "#fff0c2"), ("active", "#f0c77f"), ("!disabled", "#d8aa61"), ], lightcolor=[ ("pressed", "#765034"), ("active", "#62452f"), ("!disabled", "#4a3528"), ], darkcolor=[ ("pressed", "#4b3021"), ("active", "#3d2a21"), ("!disabled", "#32251f"), ], ) style.configure( "Play.TButton", background="#d98927", foreground="#fff8e9", font=("Sans", 10, "bold"), padding=(20, 10), bordercolor="#f4bd61", borderwidth=1, relief="flat", focuscolor="#fff0c2", focusthickness=2, ) style.map( "Play.TButton", background=[("active", "#efaa4c"), ("disabled", "#6c4826")], foreground=[("disabled", "#bca889")], bordercolor=[("focus", "#fff0c2")], ) style.configure( "Secondary.TButton", background="#0b0a09", foreground="#f2b657", font=("Sans", 8, "bold"), padding=(12, 8), bordercolor="#d89332", borderwidth=1, relief="flat", focuscolor="#f4bd61", focusthickness=2, ) style.map( "Secondary.TButton", background=[("active", "#271b10"), ("disabled", "#171412")], foreground=[("active", "#ffd17c"), ("disabled", "#887a70")], bordercolor=[("focus", "#f4bd61")], ) style.configure( "LauncherUpdate.TButton", background="#f4bd61", foreground="#24170f", font=("Sans", 8, "bold"), padding=(12, 8), bordercolor="#ffe3a3", borderwidth=2, relief="flat", focuscolor="#24170f", focusthickness=2, ) style.map( "LauncherUpdate.TButton", background=[("active", "#ffd47f"), ("disabled", "#7b5d37")], foreground=[("active", "#120b06"), ("disabled", "#d0bea2")], bordercolor=[("focus", "#ffffff")], ) style.configure( "LauncherManualUpdate.TButton", background="#a63f2f", foreground="#fff4e9", font=("Sans", 8, "bold"), padding=(12, 8), bordercolor="#e98769", borderwidth=2, relief="flat", focuscolor="#ffffff", focusthickness=2, ) style.map( "LauncherManualUpdate.TButton", background=[("active", "#c95842"), ("disabled", "#60352e")], foreground=[("active", "#ffffff"), ("disabled", "#c9ada5")], bordercolor=[("focus", "#ffffff")], ) style.configure( "UpdateBadge.TLabel", background="#d98927", foreground="#1a1008", font=("Sans", 7, "bold"), padding=(7, 3), ) style.configure( "Activity.TButton", background="#0c0908", foreground="#f8fafc", font=("Monospace", 8, "bold"), padding=(3, 2), borderwidth=0, relief="flat", ) style.map( "Activity.TButton", background=[("active", "#24170f")], foreground=[("active", "#ffffff")], ) style.configure( "News.TButton", background="#211916", foreground="#e5b66c", font=("Sans", 9, "bold"), padding=(0, 3), ) style.map("News.TButton", foreground=[("active", "#ffe0a0")]) style.configure( "Depot.Horizontal.TProgressbar", background="#d68c34", troughcolor="#34251f", bordercolor="#34251f", lightcolor="#e4a34c", darkcolor="#b66c25", )