====== TUI Engine ======
Architektur und Qualitätsanforderungen der TUI Rendering Engine.
Diese Anforderungen sind **nicht verhandelbar** - sie definieren den Mindeststandard für GUI-ähnliche TUI-Qualität.
===== Qualitätsanforderungen =====
==== 1. Flicker-free Rendering ====
PFLICHT:
- Double-Buffering mit Diff-based Flush
- Dirty-Rect oder Run-Length Optimierung
- Keine Full-Screen Redraw Loops
**Warum:** Flicker zerstört die User Experience und macht TUI unbrauchbar für professionelle Anwendungen.
==== 2. Deterministisches Layout + Clipping ====
PFLICHT:
- Measure/Arrange/Paint Lifecycle implementieren
- Drawing auf zugewiesene Rectangles clippen
- Keine Out-of-Bounds Schreiboperationen
==== 3. Unicode-Korrektheit ====
PFLICHT:
- Wide Characters (East Asian Width) korrekt behandeln
- Combining Marks korrekt behandeln
- Emoji-Breite korrekt berechnen
- Cursor-Positionierung muss Grapheme-aware sein
**Problem:** "Drifting Caret" - Cursor wandert bei Wide Chars.
**Lösung:** Grapheme-Cluster für Cursor-Berechnung verwenden.
==== 4. Theme + State Layering ====
PFLICHT:
- Style Tokens unterstützen
- Layered States implementieren:
Base → Hover (falls Mouse) → Focus → Pressed → Disabled → Error/Validation
- Focus-Indikatoren konsistent über alle Controls
==== 5. Input + Focus als First-Class ====
PFLICHT:
- Focus Navigation (Tab/Shift+Tab)
- Deterministisches Focus Ordering
- Normalisiertes Input Event Model:
Keys, Text Input, Resize, optionale Mouse
==== 6. Performance und Skalierung ====
PFLICHT:
- Virtualisierung für große Surfaces (Tables/Logs/Trees)
- O(N) Repaint von Offscreen Rows/Columns vermeiden
- Effiziente Speichernutzung
==== 7. Image-Support (SCADA/MES) ====
PFLICHT:
- Capability Detection implementieren
- Fallback-Kette:
1. Kitty Graphics (bevorzugt)
2. Sixel
3. Placeholder (Frame + Caption + "image unavailable")
===== Engine-Bausteine =====
==== A) Terminal Capability Layer ====
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) Render Model: CellBuffer + DiffEngine ====
TCell = record
Grapheme: string; (* Unicode Grapheme Cluster *)
Fg: TColor; (* Foreground Color *)
Bg: TColor; (* Background Color *)
Attrs: TAttributes; (* Bold, Italic, Underline, etc. *)
Link: string; (* Optional: Hyperlink *)
ImageRef: Integer; (* Optional: Image Reference *)
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; (* Ziel-Frame *)
FFrontBuffer: TCellBuffer; (* Letzter geflushter Frame *)
public
procedure ComputeDiff(out ADirtyRects: TRectArray);
procedure Flush(ATerminal: TTerminalIO);
end;
**Anforderungen an DiffEngine:**
* Minimale Cursor-Bewegungen
* Minimale Style-Wechsel
* Stabil bei schnellem Resize
==== C) Render Surface (Drawing API) ====
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;
**Wichtig:** Surface schreibt nur in BackBuffer, nicht direkt in TerminalIO.
==== D) Layout Engine ====
Controls werden in Rects arrangiert.
Minimum Containers:
- Stack (vertikal/horizontal)
- Dock (Left, Top, Right, Bottom, Fill)
- Grid (später)
- Overlay (für Popups/Modals)
==== E) Widget/Control Rendering Contract ====
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 =====
==== Snapshot Tests ====
PFLICHT:
- BackBuffer in stabile Textdarstellung dumpen
- Vergleich mit erwarteter Ausgabe
==== Unicode-Fixtures ====
PFLICHT:
- Tests mit Wide Characters (中文, 日本語)
- Tests mit Combining Marks (é = e + ´)
- Tests mit Emoji (👍, 🎉)
==== Image-Fallback Tests ====
PFLICHT:
- Kitty → Sixel → Placeholder Fallback testen
- Capability Detection verifizieren
===== Verifikations-Checkliste =====
TUI Engine Verification:
Rendering:
- [ ] Kein Flicker bei wiederholtem Repaint
- [ ] Resize produziert stabiles Layout
- [ ] Kein hängengebliebener Cursor
- [ ] Kein gebrochenes Clipping
Unicode:
- [ ] Wide Characters korrekt positioniert
- [ ] Combining Marks korrekt dargestellt
- [ ] Emoji-Breite korrekt
Performance:
- [ ] Table/List rendert 10k Rows mit Scroll
- [ ] Kein O(N) Repaint für Offscreen
Images:
- [ ] Kitty Graphics funktioniert (wenn supported)
- [ ] Sixel Fallback funktioniert
- [ ] Placeholder bei fehlender Unterstützung
===== Siehe auch =====
* [[.:tui-entwicklung|TUI-Entwicklung Übersicht]]
* [[.:tui-controls|TUI Controls]]
* [[.:tui-layout|TUI Layout]]