Files
CCMA/src/ccma/ui/theme.py
T
2026-06-27 10:36:03 +02:00

112 lines
4.5 KiB
Python

from pathlib import Path
from tkinter import TclError, ttk
def load_theme(root, mode: str) -> str:
style = ttk.Style(root)
variant = "light" if mode == "light" else "dark"
theme_name = f"forest-{variant}"
theme_path = (
Path(__file__).resolve().parent.parent / "assets" / "themes" / "forest" / f"forest-{variant}.tcl"
)
if theme_path.exists():
try:
if theme_name not in style.theme_names():
root.tk.call("source", str(theme_path))
style.theme_use(theme_name)
_configure_ccma_styles(style, variant)
return theme_name
except TclError:
pass
style.theme_use("clam")
_configure_fallback(style, variant)
_configure_ccma_styles(style, variant)
return "clam"
def _configure_fallback(style: ttk.Style, variant: str) -> None:
dark = variant == "dark"
background = "#14181f" if dark else "#f4f6f8"
surface = "#20262f" if dark else "#ffffff"
foreground = "#e6edf3" if dark else "#20252b"
accent = "#00a884" if dark else "#087f5b"
style.configure(".", background=background, foreground=foreground)
style.configure("TFrame", background=background)
style.configure("TLabel", background=background, foreground=foreground)
style.configure("TButton", background=surface, foreground=foreground)
style.configure("TEntry", fieldbackground=surface, foreground=foreground)
style.configure("Treeview", background=surface, fieldbackground=surface, foreground=foreground)
style.map("Treeview", background=[("selected", accent)], foreground=[("selected", "#ffffff")])
def _configure_ccma_styles(style: ttk.Style, variant: str) -> None:
dark = variant == "dark"
background = "#1b1f23" if dark else "#ffffff"
foreground = "#f0f4f8" if dark else "#202124"
muted = "#9aa4ad" if dark else "#5f6368"
accent = "#00d084" if dark else "#087f5b"
warning = "#ffb454"
danger = "#ff6b6b"
message_styles = {
"Error": (
"#5c2528" if dark else "#d04242",
"#3a1719" if dark else "#fde8e8",
"#ffd7d7" if dark else "#8a1f1f",
),
"Warning": (
"#6c4b19" if dark else "#d69b19",
"#3a2a12" if dark else "#fff4cc",
"#ffe2a8" if dark else "#7a4f00",
),
"Info": (
"#204f79" if dark else "#5b9bd8",
"#132c45" if dark else "#e5f1ff",
"#cde6ff" if dark else "#174a7c",
),
"Notification": (
"#1f5a3a" if dark else "#57ad75",
"#123222" if dark else "#e4f7ec",
"#c9f2dc" if dark else "#1f6b3d",
),
}
style.configure("Ribbon.TFrame", padding=(12, 9))
style.configure("AppTitle.TLabel", font=("TkDefaultFont", 14, "bold"))
style.configure("TabTitle.TLabel", font=("TkDefaultFont", 15, "bold"))
style.configure("Mono.TLabel", font=("TkFixedFont", 10), foreground=muted)
style.configure("Muted.TLabel", foreground=muted)
style.configure("Status.TLabel", font=("TkFixedFont", 9), foreground=muted)
style.configure("TimelineHeader.TLabel", font=("TkFixedFont", 11, "bold"), foreground=accent)
style.configure("Error.TLabel", foreground=danger)
style.configure("Warning.TLabel", foreground=warning)
style.configure("Accent.TButton", font=("TkDefaultFont", 10, "bold"))
style.configure("Card.TFrame", background=background, relief="solid", borderwidth=1)
style.configure("CardTitle.TLabel", background=background, foreground=muted, font=("TkFixedFont", 10))
style.configure(
"CardValue.TLabel", background=background, foreground=foreground, font=("TkDefaultFont", 15, "bold")
)
style.configure(
"CardError.TLabel", background=background, foreground=danger, font=("TkDefaultFont", 15, "bold")
)
style.configure(
"CardWarning.TLabel", background=background, foreground=warning, font=("TkDefaultFont", 15, "bold")
)
style.configure(
"Timeline.Treeview",
rowheight=42,
background=background,
fieldbackground=background,
foreground=foreground,
)
for name, (message_border, message_background, message_foreground) in message_styles.items():
style.configure(f"Message{name}Border.TFrame", background=message_border)
style.configure(
f"Message{name}.TFrame",
background=message_background,
)
style.configure(
f"Message{name}.TLabel",
background=message_background,
foreground=message_foreground,
font=("TkDefaultFont", 10),
)