"""Thèmes et palette de la GUI V6 (G4 — alignement maquette). Reprend les 4 thèmes et les tokens couleur exacts de ``docs/ui_mockup_v6.html``. customtkinter n'a pas de variables CSS : on colore chaque widget via la palette résolue ici. Les tokens semi-transparents de la maquette (rgba) sont rendus en hex approchés sur le fond du thème. Import de ce module : aucun widget créé (compatible ``--self-test``). """ from __future__ import annotations from typing import Dict, List # Palette complète par thème (tokens alignés sur la maquette HTML). PALETTES: Dict[str, dict] = { # Défaut maquette — sombre indigo / accent rose. "sombre": { "appearance": "dark", "bg": "#1a1a2e", "card": "#16213e", "card_border": "#0f3460", "primary": "#e94560", "primary_dim": "#c73652", "accent": "#f5a623", "text": "#e0e0e0", "text_dim": "#9ca3af", "text_muted": "#6b7280", "success": "#10b981", "warning": "#f59e0b", "danger": "#ef4444", "blue": "#3b82f6", "divider": "#23233a", "btn_sec_bg": "#222a40", "btn_sec_border": "#333a4d", }, # Clair — fond gris moyen, cartes blanches. "clair": { "appearance": "light", "bg": "#cdd2da", "card": "#ffffff", "card_border": "#9aa3b0", "primary": "#c93050", "primary_dim": "#a82545", "accent": "#b45309", "text": "#0d1117", "text_dim": "#1f2937", "text_muted": "#374151", "success": "#047857", "warning": "#b45309", "danger": "#b91c1c", "blue": "#1d4ed8", "divider": "#e6e9ee", "btn_sec_bg": "#eef0f3", "btn_sec_border": "#9aa3b0", }, # Médical — fond bleu structuré. "medical": { "appearance": "light", "bg": "#b8ceea", "card": "#eef5ff", "card_border": "#6897ca", "primary": "#1a56db", "primary_dim": "#1340b0", "accent": "#0369a1", "text": "#071427", "text_dim": "#0f2a4a", "text_muted": "#1e3a5f", "success": "#166534", "warning": "#92400e", "danger": "#991b1b", "blue": "#1e40af", "divider": "#dbe8fb", "btn_sec_bg": "#e2edfc", "btn_sec_border": "#6897ca", }, # Neutre — gris sombre. "neutre": { "appearance": "dark", "bg": "#1f2937", "card": "#374151", "card_border": "#6b7280", "primary": "#818cf8", "primary_dim": "#6366f1", "accent": "#fbbf24", "text": "#f9fafb", "text_dim": "#e5e7eb", "text_muted": "#d1d5db", "success": "#34d399", "warning": "#fbbf24", "danger": "#f87171", "blue": "#60a5fa", "divider": "#2f3a49", "btn_sec_bg": "#3d4a5c", "btn_sec_border": "#6b7280", }, } DEFAULT_THEME = "clair" THEME_LABELS = { "sombre": "🌙 Sombre", "clair": "☀️ Clair", "medical": "🏥 Médical", "neutre": "🌿 Neutre", } # Token de palette utilisé pour colorer un statut licence. _STATUS_TOKEN = { "active": "success", "grace": "warning", "expired": "danger", "revoked": "danger", "invalid": "danger", "unavailable": "warning", "autre_poste": "warning", "none": "text_muted", } def theme_names() -> List[str]: return list(PALETTES.keys()) def get_palette(name: str) -> dict: return PALETTES.get(name, PALETTES[DEFAULT_THEME]) def status_color(theme_name: str, status: str) -> str: """Couleur hex pour un statut licence, dans le thème donné.""" palette = get_palette(theme_name) return palette[_STATUS_TOKEN.get(status, "text_muted")] def apply_theme(name: str = DEFAULT_THEME) -> dict: """Applique le mode d'apparence customtkinter et retourne la palette.""" palette = get_palette(name) import customtkinter as ctk ctk.set_appearance_mode(palette["appearance"]) return palette