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