====== Controlli TUI ====== Linee guida di implementazione per controlli/widget nel target TUI. Questo pattern estende il concetto esistente "Model + Renderer" con requisiti specifici TUI. ===== Architettura ===== ==== Separazione Model + Renderer ==== Model (Target-neutral) Renderer (Target-specifico) ───────────────────── ───────────────────────────── Classe Pascal TWvdS* TUI: CellBuffer via RenderSurface - Properties, stato GUI: Canvas/GDI - Eventi, comandi Web: DOM/HTML - Nessuna dipendenza I/O ==== Deliverable per controllo ==== | Componente | Contenuto | ^ Unit Model | Properties, eventi, stato (target-neutral) | ^ Unit TUI Renderer | Paint, focus, gestione input | ^ Pack Manifest | Mapping tag PXAML → unit | ===== Unit Model (Target-neutral) ===== ==== Contiene ==== TWvdSButton = class(TWvdSControl) private FCaption: string; FEnabled: Boolean; FFocused: Boolean; FPressed: Boolean; FOnClick: TNotifyEvent; public property Caption: string read FCaption write SetCaption; property Enabled: Boolean read FEnabled write SetEnabled; property Focused: Boolean read FFocused write SetFocused; property OnClick: TNotifyEvent read FOnClick write FOnClick; end; ==== NON contiene ==== * Terminal I/O o sequenze ANSI * API DOM/Web * Chiamate specifiche della piattaforma ===== Unit TUI Renderer ===== ==== Interface ==== IWvdSTUIRenderer = interface (* Layout *) function Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; procedure Arrange(AControl: TWvdSControl; ARect: TRect); (* Rendering *) procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface); (* Input *) function HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; end; ==== Implementazione minima ==== OBBLIGATORIO per ogni TUI Renderer: - Rendering placeholder deterministico (prima della completezza feature) - Visualizzazione indicatore focus - Visualizzazione stato disabled - Navigazione Tab funzionante end-to-end - Opzionale: Gestione mouse (se TerminalCaps.SupportsMouse) ===== Stati visuali ===== ==== Gerarchia stati ==== Stati obbligatori: ├─ Base (* Visualizzazione default *) ├─ Focus (* Ha il focus tastiera *) ├─ Disabled (* Non interattivo *) └─ Error/Invalid (* Errore validazione *) Stati opzionali: ├─ Hover (* Mouse sopra - se mouse supportato *) └─ Pressed (* Premuto attivamente *) ==== Rendering per stato ==== procedure TWvdSButtonTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var Btn: TWvdSButton; Style: TStyle; begin Btn := TWvdSButton(AControl); (* Selezione stile basata su stato *) if not Btn.Enabled then Style := Theme.ButtonDisabled else if Btn.Focused then Style := Theme.ButtonFocused else Style := Theme.ButtonBase; (* Renderizzare bordo + caption *) ASurface.DrawBorder(Btn.Bounds, bsSingle); ASurface.DrawText(Btn.Bounds.Left + 1, Btn.Bounds.Top, Btn.Caption, Style); end; ===== Accessibilita (equivalente TUI) ===== OBBLIGATORIO: - Focus Ring / Highlight (* Chiaramente riconoscibile *) - Hint Hotkey/Acceleratore (* Opzionale: [A]nnulla *) - Indicatore stato errore (* Errori validazione visibili *) ===== Semantica input ===== ==== Navigazione focus ==== OBBLIGATORIO per ogni controllo focalizzabile: - Consumare Tab (FocusManager decide il movimento) - Elaborare correttamente Enter/Space - Input testo via eventi normalizzati (non raw keycode) ==== Pattern handler input ==== function TWvdSButtonTUIRenderer.HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; var Btn: TWvdSButton; begin Result := False; Btn := TWvdSButton(AControl); if not Btn.Enabled then Exit; if not Btn.Focused then Exit; case AEvent.Kind of iekKey: if AEvent.Key in [vkReturn, vkSpace] then begin if Assigned(Btn.OnClick) then Btn.OnClick(Btn); Result := True; (* Evento consumato *) end; iekMouse: if (AEvent.MouseButton = mbLeft) and (AEvent.MouseAction = maClick) then begin if Assigned(Btn.OnClick) then Btn.OnClick(Btn); Result := True; end; end; end; ===== Semantica layout ===== ==== Measure ==== function TWvdSButtonTUIRenderer.Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; var Btn: TWvdSButton; begin Btn := TWvdSButton(AControl); (* Dimensione minima ragionevole *) Result.Width := Length(Btn.Caption) + 4; (* Padding + bordo *) Result.Height := 3; (* Bordo sopra/sotto + testo *) (* Rispettare constraint dal parent *) if Result.Width > AAvailable.Width then Result.Width := AAvailable.Width; end; ==== Regole Paint ==== RIGOROSO: - Disegnare SOLO all'interno del rect assegnato - Clipping DEVE essere attivo - Nessuna operazione di rendering fuori bounds ===== Virtualizzazione ===== Per controlli con grandi quantità di dati (tabelle, liste, alberi, log): OBBLIGATORIO: - Renderizzare solo righe/elementi visibili - Nessuna allocazione buffer per riga per frame - Gestire correttamente posizione scroll ==== Esempio: Lista virtualizzata ==== procedure TWvdSListTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var List: TWvdSList; VisibleStart, VisibleEnd: Integer; I, Y: Integer; begin List := TWvdSList(AControl); (* Calcolare solo area visibile *) VisibleStart := List.ScrollOffset; VisibleEnd := VisibleStart + List.VisibleRowCount; if VisibleEnd > List.ItemCount then VisibleEnd := List.ItemCount; (* Renderizzare solo elementi visibili *) Y := 0; for I := VisibleStart to VisibleEnd - 1 do begin ASurface.DrawText(0, Y, List.Items[I], GetItemStyle(I)); Inc(Y); end; end; ===== Checklist controllo ===== ==== A) Stati visuali ==== [ ] Stato base renderizza correttamente [ ] Stato focus chiaramente riconoscibile [ ] Stato disabled distinguibile [ ] Stato errore/invalid visibile ==== B) Input ==== [ ] Navigazione Tab funziona [ ] Enter/Space attiva azione (per button) [ ] Input testo normalizzato (per TextEdit) [ ] Mouse supportato opzionalmente ==== C) Layout ==== [ ] Measure restituisce dimensione sensata [ ] Paint rispetta rect assegnato [ ] Nessun rendering fuori bounds [ ] Resize gestito correttamente ==== D) Performance ==== [ ] Liste grandi virtualizzate [ ] Nessun repaint O(N) per offscreen [ ] Nessuna allocazione inutile per frame ===== Documentazione per controllo ===== Documentare ogni controllo: WHY: Perché esiste questo controllo (casi d'uso) WHEN: Quando usarlo vs alternative più semplici Note TUI: - Requisiti capability (mouse, immagini, TrueColor) - Comportamento resize (anchoring/responsive) - Limitazioni note ===== Vedi anche ===== * [[.:tui-entwicklung|Panoramica sviluppo TUI]] * [[.:tui-engine|TUI Engine]] * [[.:tui-layout|Layout TUI]]