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:

  1. 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.
  2. 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

  1. Apri il file fire/ui_components/theme_manager.py.

  2. Scegli il gruppo corretto. Se è un colore generico, aggiungilo a BASE_COLORS. Se è per il grafico, a CHART_COLORS.

  3. Aggiungi la definizione. Aggiungi una nuova voce al dizionario scelto, seguendo la sintassi:
    “nuovo_nome_colore”: (“Descrizione che vedrà l’utente”, “#ValoreEsadecimaleDefault”)

  4. 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.