====== TUI Controls ====== Implementierungsrichtlinien für Controls/Widgets im TUI-Target. Dieses Pattern erweitert das bestehende "Model + Renderer" Konzept um TUI-spezifische Anforderungen. ===== Architektur ===== ==== Model + Renderer Trennung ==== Model (Target-neutral) Renderer (Target-spezifisch) ───────────────────── ───────────────────────────── TWvdS* Pascal-Klasse TUI: CellBuffer via RenderSurface - Properties, State GUI: Canvas/GDI - Events, Commands Web: DOM/HTML - Keine I/O-Abhängigkeit ==== Deliverables pro Control ==== | Komponente | Inhalt | ^ Model Unit | Properties, Events, State (target-neutral) | ^ TUI Renderer Unit | Paint, Focus, Input Handling | ^ Pack Manifest | PXAML Tag → Units Mapping | ===== Model Unit (Target-neutral) ===== ==== Enthält ==== 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; ==== Enthält NICHT ==== * Terminal I/O oder ANSI-Sequenzen * DOM/Web APIs * Plattform-spezifische Aufrufe ===== TUI Renderer Unit ===== ==== 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; ==== Minimum-Implementierung ==== PFLICHT für jeden TUI Renderer: - Deterministisches Placeholder-Rendering (vor Feature-Vollständigkeit) - Focus-Indikator Darstellung - Disabled-State Darstellung - Tab-Navigation funktioniert End-to-End - Optional: Mouse Handling (wenn TerminalCaps.SupportsMouse) ===== Visual States ===== ==== State-Hierarchie ==== Pflicht-States: ├─ Base (* Default-Darstellung *) ├─ Focus (* Hat Tastatur-Fokus *) ├─ Disabled (* Nicht interaktiv *) └─ Error/Invalid (* Validierungsfehler *) Optional-States: ├─ Hover (* Maus darüber - wenn Mouse supported *) └─ Pressed (* Aktiv gedrückt *) ==== Rendering pro State ==== procedure TWvdSButtonTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var Btn: TWvdSButton; Style: TStyle; begin Btn := TWvdSButton(AControl); (* State-basierte Style-Auswahl *) if not Btn.Enabled then Style := Theme.ButtonDisabled else if Btn.Focused then Style := Theme.ButtonFocused else Style := Theme.ButtonBase; (* Border + Caption rendern *) ASurface.DrawBorder(Btn.Bounds, bsSingle); ASurface.DrawText(Btn.Bounds.Left + 1, Btn.Bounds.Top, Btn.Caption, Style); end; ===== Accessibility (TUI-Äquivalent) ===== PFLICHT: - Focus Ring / Highlight (* Klar erkennbar *) - Hotkey/Accelerator Hint (* Optional: [A]bbrechen *) - Error State Indicator (* Validierungsfehler sichtbar *) ===== Input Semantics ===== ==== Focus Navigation ==== PFLICHT für jedes fokussierbare Control: - Tab konsumieren (FocusManager entscheidet Bewegung) - Enter/Space korrekt verarbeiten - Text Input über normalisierte Events (nicht Raw Keycodes) ==== Input Handler Pattern ==== 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; (* Event konsumiert *) 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; ===== Layout Semantics ===== ==== Measure ==== function TWvdSButtonTUIRenderer.Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; var Btn: TWvdSButton; begin Btn := TWvdSButton(AControl); (* Minimale vernünftige Größe *) Result.Width := Length(Btn.Caption) + 4; (* Padding + Border *) Result.Height := 3; (* Border oben/unten + Text *) (* Constraints vom Parent respektieren *) if Result.Width > AAvailable.Width then Result.Width := AAvailable.Width; end; ==== Paint-Regeln ==== STRENG: - NUR innerhalb des zugewiesenen Rect zeichnen - Clipping MUSS aktiv sein - Keine Out-of-Bounds Schreiboperationen ===== Virtualisierung ===== Für Controls mit großen Datenmengen (Tables, Lists, Trees, Logs): PFLICHT: - Nur sichtbare Rows/Items rendern - Keine Per-Row Buffer-Allokation pro Frame - Scroll-Position korrekt verwalten ==== Beispiel: Virtualisierte Liste ==== procedure TWvdSListTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var List: TWvdSList; VisibleStart, VisibleEnd: Integer; I, Y: Integer; begin List := TWvdSList(AControl); (* Nur sichtbaren Bereich berechnen *) VisibleStart := List.ScrollOffset; VisibleEnd := VisibleStart + List.VisibleRowCount; if VisibleEnd > List.ItemCount then VisibleEnd := List.ItemCount; (* Nur sichtbare Items rendern *) Y := 0; for I := VisibleStart to VisibleEnd - 1 do begin ASurface.DrawText(0, Y, List.Items[I], GetItemStyle(I)); Inc(Y); end; end; ===== Control Checkliste ===== ==== A) Visual States ==== [ ] Base State rendert korrekt [ ] Focus State klar erkennbar [ ] Disabled State unterscheidbar [ ] Error/Invalid State sichtbar ==== B) Input ==== [ ] Tab-Navigation funktioniert [ ] Enter/Space löst Aktion aus (bei Buttons) [ ] Text Input normalisiert (bei TextEdit) [ ] Mouse optional unterstützt ==== C) Layout ==== [ ] Measure gibt sinnvolle Größe zurück [ ] Paint respektiert zugewiesenes Rect [ ] Kein Rendering außerhalb Bounds [ ] Resize wird korrekt behandelt ==== D) Performance ==== [ ] Große Listen virtualisiert [ ] Kein O(N) Repaint für Offscreen [ ] Keine unnötigen Allokationen pro Frame ===== Dokumentation pro Control ===== Jedes Control dokumentieren: WHY: Warum existiert dieses Control (Use Cases) WHEN: Wann verwenden vs. einfachere Alternativen TUI Notes: - Capability Requirements (Mouse, Images, TrueColor) - Resize Behavior (Anchoring/Responsive) - Known Limitations ===== Siehe auch ===== * [[.:tui-entwicklung|TUI-Entwicklung Übersicht]] * [[.:tui-engine|TUI Engine]] * [[.:tui-layout|TUI Layout]]