====== 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]]