Inhaltsverzeichnis
TUI Engine
Architettura e requisiti di qualità del TUI Rendering Engine.
Questi requisiti sono non negoziabili - definiscono lo standard minimo per qualità TUI simile alla GUI.
Requisiti di qualità
1. Rendering flicker-free
OBBLIGATORIO: - Double buffering con flush basato su diff - Ottimizzazione dirty-rect o run-length - Nessun loop di redraw full-screen
Perché: Il flicker distrugge l'esperienza utente e rende la TUI inutilizzabile per applicazioni professionali.
2. Layout deterministico + clipping
OBBLIGATORIO: - Implementare ciclo di vita Measure/Arrange/Paint - Clippare il disegno ai rettangoli assegnati - Nessuna operazione di scrittura out-of-bounds
3. Correttezza Unicode
OBBLIGATORIO: - Gestire correttamente wide character (East Asian Width) - Gestire correttamente combining mark - Calcolare correttamente larghezza emoji - Posizionamento cursore deve essere grapheme-aware
Problema: „Drifting Caret“ - il cursore deriva con i wide char.
Soluzione: Usare grapheme cluster per il calcolo del cursore.
4. Theme + State Layering
OBBLIGATORIO: - Supportare token di stile - Implementare stati stratificati: Base → Hover (se mouse) → Focus → Pressed → Disabled → Error/Validation - Indicatori focus consistenti su tutti i controlli
5. Input + Focus come first-class
OBBLIGATORIO: - Navigazione focus (Tab/Shift+Tab) - Ordinamento focus deterministico - Modello eventi input normalizzato: Tasti, input testo, resize, mouse opzionale
6. Performance e scalabilita
OBBLIGATORIO: - Virtualizzazione per surface grandi (tabelle/log/alberi) - Evitare repaint O(N) di righe/colonne offscreen - Uso memoria efficiente
7. Supporto immagini (SCADA/MES)
OBBLIGATORIO: - Implementare rilevamento capability - Catena fallback: 1. Kitty Graphics (preferito) 2. Sixel 3. Placeholder (frame + caption + "image unavailable")
Componenti engine
A) Layer Terminal Capability
TTerminalCaps = record SupportsAnsi: Boolean; SupportsAltScreen: Boolean; SupportsTrueColor: Boolean; Supports256Color: Boolean; SupportsMouse: Boolean; SupportsKittyGraphics: Boolean; SupportsSixel: Boolean; SupportsUnicodeWidth: Boolean; end; TTerminalIO = class procedure EnterAltScreen; procedure ExitAltScreen; procedure ShowCursor; procedure HideCursor; procedure WriteEscapeSequence(const ASeq: string); procedure WriteTextRun(const AText: string); procedure MoveCursor(AX, AY: Integer); procedure SetStyle(AStyle: TStyle); procedure BatchFlush; end;
B) Modello render: CellBuffer + DiffEngine
TCell = record Grapheme: string; (* Unicode Grapheme Cluster *) Fg: TColor; (* Foreground Color *) Bg: TColor; (* Background Color *) Attrs: TAttributes; (* Bold, Italic, Underline, ecc. *) Link: string; (* Opzionale: Hyperlink *) ImageRef: Integer; (* Opzionale: Riferimento immagine *) end; TCellBuffer = class private FCells: array of array of TCell; FWidth, FHeight: Integer; public procedure SetCell(AX, AY: Integer; const ACell: TCell); function GetCell(AX, AY: Integer): TCell; procedure Clear; procedure Resize(AWidth, AHeight: Integer); end;
DiffEngine:
TDiffEngine = class private FBackBuffer: TCellBuffer; (* Frame target *) FFrontBuffer: TCellBuffer; (* Ultimo frame flushato *) public procedure ComputeDiff(out ADirtyRects: TRectArray); procedure Flush(ATerminal: TTerminalIO); end;
Requisiti per DiffEngine:
- Movimenti cursore minimi
- Cambi stile minimi
- Stabile con resize veloce
C) Render Surface (API disegno)
TRenderSurface = class private FBuffer: TCellBuffer; FClipStack: TRectStack; public procedure FillRect(ARect: TRect; AChar: Char; AStyle: TStyle); procedure DrawText(AX, AY: Integer; const AText: string; AStyle: TStyle); procedure DrawBorder(ARect: TRect; ABorderStyle: TBorderStyle); procedure DrawImage(ARect: TRect; AImageRef: Integer); procedure ClipPush(ARect: TRect); procedure ClipPop; end;
Importante: Surface scrive solo in BackBuffer, non direttamente in TerminalIO.
D) Layout Engine
I controlli vengono disposti in rect. Container minimi: - Stack (verticale/orizzontale) - Dock (Left, Top, Right, Bottom, Fill) - Grid (successivo) - Overlay (per popup/modali)
E) Contratto rendering Widget/Control
IWvdSTUIRenderer = interface function Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; procedure Arrange(AControl: TWvdSControl; ARect: TRect); procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface); function HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; end;
Testing
Test snapshot
OBBLIGATORIO: - Dump BackBuffer in rappresentazione testuale stabile - Confronto con output atteso
Fixture Unicode
OBBLIGATORIO: - Test con wide character (cinese, giapponese) - Test con combining mark (e = e + accento) - Test con emoji
Test fallback immagini
OBBLIGATORIO: - Testare fallback Kitty → Sixel → Placeholder - Verificare rilevamento capability
Checklist verifica
Verifica TUI Engine: Rendering: - [ ] Nessun flicker al repaint ripetuto - [ ] Resize produce layout stabile - [ ] Nessun cursore bloccato - [ ] Nessun clipping rotto Unicode: - [ ] Wide character posizionati correttamente - [ ] Combining mark visualizzati correttamente - [ ] Larghezza emoji corretta Performance: - [ ] Table/List renderizza 10k righe con scroll - [ ] Nessun repaint O(N) per offscreen Immagini: - [ ] Kitty Graphics funziona (se supportato) - [ ] Fallback Sixel funziona - [ ] Placeholder se non supportato
Vedi anche
Zuletzt geändert: il 30/01/2026 alle 01:31