DD-THEMING.md
Versione: 1.0 Data: 2025-10-10 Scopo: Descrivere l’architettura del sistema di theming centralizzato di FIRE e definire le regole per il suo utilizzo. Documento Principale: FIRE 25.07 - ARCHITECTURE-OVERVIEW
1. Panoramica e Filosofia di Progettazione
Un’interfaccia utente professionale richiede una coerenza visiva rigorosa. I colori non sono decorativi, ma comunicano significato (es. rosso per un errore, verde per un successo). Per gestire questa coerenza in modo robusto e permettere la personalizzazione da parte dell’utente, FIRE adotta un sistema di theming centralizzato.
La filosofia di questo sistema è duplice:
- Disaccoppiare i componenti dalla logica dei colori: Un widget non deve mai avere un colore “hard-coded”. Deve solo sapere che ha bisogno del “colore di errore”, senza conoscerne il valore esadecimale.
- Fornire un’unica fonte di verità (Single Source of Truth): Tutta la logica dei colori è gestita da un unico componente, il
ThemeManager, per prevenire il “caos cromatico” e facilitare la manutenzione e la personalizzazione.
2. Architettura: Il ThemeManager
Il cuore del sistema è la classe statica ThemeManager (in fire/ui_components/theme_manager.py). Questa classe agisce come un servizio globale accessibile da qualsiasi punto dell’applicazione e ha le seguenti responsabilità:
- Definire i colori di default: Contiene dizionari che definiscono lo schema cromatico di base dell’applicazione, raggruppato logicamente (es. colori di base, colori per grafici, colori per severità).
- Gestire le personalizzazioni: All’avvio, legge le impostazioni dell’utente (se presenti) e sovrascrive i valori di default.
- Fornire un’API di accesso: Espone metodi
get...chiari e semantici per permettere ai componenti di richiedere i colori di cui hanno bisogno.
La Regola d’Oro: “Chiedi, Non Ricevere” (Dependency Inversion)
Questo è il principio fondamentale del nostro sistema di theming. Un widget non deve mai ricevere passivamente i colori dal suo parente o costruttore. Deve importare ThemeManager e chiedere attivamente il colore di cui ha bisogno.
✅ Corretto: Il widget è autosufficiente e disaccoppiato.
# In un qualsiasi file di un widget UI
from ..theme_manager import ThemeManager
class MioWidget(QWidget):
def __init__(self):
super().__init__()
# Il widget chiede direttamente il colore di cui ha bisogno
colore_errore = ThemeManager.get_color_for_severity("ERROR")
self.label_errore.setStyleSheet(f"color: {colore_errore};")❌ Sbagliato: Crea accoppiamento forte e rende i widget non riutilizzabili.
codePython
# Anti-pattern da evitare!
class MioWidget(QWidget):
# NON FARE COSÌ: il widget dipende dal suo parente
def __init__(self, colore_errore: str):
super().__init__()
self.label_errore.setStyleSheet(f"color: {colore_errore};")
3. Tipi di Colori e Metodi di Accesso
È fondamentale usare il metodo di accesso corretto in base allo scopo del colore.
-
get_color_for_severity(severity: str) → str
-
Scopo: Per elementi che indicano uno stato di severità (es. log, messaggi di validazione).
-
Input: “ERROR”, “WARNING”, “INFO”, “SUCCESS”.
-
Utilizzo: Per colorare il testo o lo sfondo di un messaggio.
-
-
get_color(semantic_name: str) → str
-
Scopo: Per elementi dell’interfaccia con un significato specifico e costante.
-
Input: “bg_panel”, “text_highlight”.
-
Utilizzo: Per impostare colori di sfondo, bordi o testo in widget custom.
-
-
get_raw_color(key: str) → str
-
Scopo: Per accedere a un colore definito direttamente dalla sua chiave, senza mappature intermedie. È il metodo da usare per componenti complessi come i grafici.
-
Input: “chart_upColor”, “chart_downColor”, “chart_wickUpColor”.
-
Utilizzo: Per configurare librerie di terze parti (es. Lightweight Charts) che richiedono un dizionario di colori.
-
4. Guide Pratiche
4.1. Come Aggiungere un Nuovo Colore Personalizzabile al Sistema
-
Apri il file fire/ui_components/theme_manager.py.
-
Scegli il gruppo corretto. Se è un colore generico, aggiungilo a BASE_COLORS. Se è per il grafico, a CHART_COLORS.
-
Aggiungi la definizione. Aggiungi una nuova voce al dizionario scelto, seguendo la sintassi:
“nuovo_nome_colore”: (“Descrizione che vedrà l’utente”, “#ValoreEsadecimaleDefault”) -
Usa il colore nel tuo widget. Nel tuo componente, importa ThemeManager e chiama il metodo di accesso più appropriato (solitamente get_raw_color per un colore appena aggiunto) per ottenerlo.
codePython
nuovo_colore = ThemeManager.get_raw_color("nuovo_nome_colore")
Il sistema si occuperà automaticamente di mostrare il nuovo colore nell’editor dei temi, rendendolo personalizzabile dall’utente senza ulteriori modifiche al codice.