Spaces:
Paused
Paused
| """ | |
| 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) | |