Inhaltsverzeichnis

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

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