Spaces:
Paused
Paused
File size: 2,852 Bytes
a5784e9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | """
GUI Launcher Theme Manager
Handles light/dark mode switching with persistence.
"""
from typing import Callable, List, Literal
import customtkinter as ctk
# Type alias for appearance modes
AppearanceMode = Literal["dark", "light", "system"]
# Module-level state
_current_mode: AppearanceMode = "dark"
_on_change_callbacks: List[Callable[[AppearanceMode], None]] = []
def get_appearance_mode() -> AppearanceMode:
"""Get the current appearance mode."""
return _current_mode
def set_appearance_mode(mode: AppearanceMode) -> None:
"""
Set the appearance mode and apply it.
Args:
mode: One of "dark", "light", or "system"
"""
global _current_mode
if mode not in ("dark", "light", "system"):
mode = "dark" # Default fallback
_current_mode = mode
ctk.set_appearance_mode(mode)
# Notify listeners
for callback in _on_change_callbacks:
try:
callback(mode)
except Exception:
pass
def toggle_appearance_mode() -> AppearanceMode:
"""
Toggle between dark and light mode.
Returns:
The new appearance mode after toggle
"""
if _current_mode == "dark":
set_appearance_mode("light")
else:
set_appearance_mode("dark")
return _current_mode
def is_dark_mode() -> bool:
"""Check if currently in dark mode."""
if _current_mode == "system":
# Check actual system setting
return ctk.get_appearance_mode().lower() == "dark"
return _current_mode == "dark"
def on_theme_change(callback: Callable[[AppearanceMode], None]) -> None:
"""
Register a callback to be called when theme changes.
Args:
callback: Function that takes the new mode as argument
"""
if callback not in _on_change_callbacks:
_on_change_callbacks.append(callback)
def remove_theme_callback(callback: Callable[[AppearanceMode], None]) -> None:
"""Remove a previously registered callback."""
if callback in _on_change_callbacks:
_on_change_callbacks.remove(callback)
def get_mode_display_name(mode: AppearanceMode) -> str:
"""
Get a user-friendly display name for the mode.
Args:
mode: The appearance mode
Returns:
Display name with emoji
"""
names = {
"dark": "🌙 Dark",
"light": "☀️ Light",
"system": "💻 System",
}
return names.get(mode, mode)
def get_available_modes() -> List[AppearanceMode]:
"""Get list of available appearance modes."""
return ["dark", "light", "system"]
# Initialize with CustomTkinter's default
def init_theme(mode: AppearanceMode = "dark") -> None:
"""
Initialize the theme system.
Should be called once at application startup.
Args:
mode: Initial appearance mode
"""
set_appearance_mode(mode)
|