Inhaltsverzeichnis
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
Zuletzt geändert: den 29.01.2026 um 15:13