====== TUI Engine ====== Architecture and quality requirements for the TUI rendering engine. These requirements are **non-negotiable** - they define the minimum standard for GUI-like TUI quality. ===== Quality Requirements ===== ==== 1. Flicker-free Rendering ==== REQUIRED: - Double-buffering with diff-based flush - Dirty-rect or run-length optimization - No full-screen redraw loops **Why:** Flicker destroys user experience and makes TUI unusable for professional applications. ==== 2. Deterministic Layout + Clipping ==== REQUIRED: - Implement Measure/Arrange/Paint lifecycle - Clip drawing to assigned rectangles - No out-of-bounds write operations ==== 3. Unicode Correctness ==== REQUIRED: - Handle wide characters (East Asian Width) correctly - Handle combining marks correctly - Calculate emoji width correctly - Cursor positioning must be grapheme-aware **Problem:** "Drifting caret" - cursor wanders with wide chars. **Solution:** Use grapheme clusters for cursor calculation. ==== 4. Theme + State Layering ==== REQUIRED: - Support style tokens - Implement layered states: Base → Hover (if mouse) → Focus → Pressed → Disabled → Error/Validation - Consistent focus indicators across all controls ==== 5. Input + Focus as First-Class ==== REQUIRED: - Focus navigation (Tab/Shift+Tab) - Deterministic focus ordering - Normalized input event model: Keys, text input, resize, optional mouse ==== 6. Performance and Scaling ==== REQUIRED: - Virtualization for large surfaces (tables/logs/trees) - Avoid O(N) repaint of offscreen rows/columns - Efficient memory usage ==== 7. Image Support (SCADA/MES) ==== REQUIRED: - Implement capability detection - Fallback chain: 1. Kitty Graphics (preferred) 2. Sixel 3. Placeholder (frame + caption + "image unavailable") ===== Engine Building Blocks ===== ==== 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; (* Target frame *) FFrontBuffer: TCellBuffer; (* Last flushed frame *) public procedure ComputeDiff(out ADirtyRects: TRectArray); procedure Flush(ATerminal: TTerminalIO); end; **DiffEngine Requirements:** * Minimal cursor movements * Minimal style switches * Stable during rapid 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; **Important:** Surface writes only to BackBuffer, not directly to TerminalIO. ==== D) Layout Engine ==== Controls are arranged into rects. Minimum Containers: - Stack (vertical/horizontal) - Dock (Left, Top, Right, Bottom, Fill) - Grid (later) - Overlay (for 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 ==== REQUIRED: - Dump BackBuffer to stable text representation - Compare with expected output ==== Unicode Fixtures ==== REQUIRED: - Tests with wide characters (Chinese, Japanese) - Tests with combining marks (e + accent) - Tests with emoji ==== Image Fallback Tests ==== REQUIRED: - Test Kitty → Sixel → Placeholder fallback - Verify capability detection ===== Verification Checklist ===== TUI Engine Verification: Rendering: - [ ] No flicker during repeated repaint - [ ] Resize produces stable layout - [ ] No stuck cursor - [ ] No broken clipping Unicode: - [ ] Wide characters positioned correctly - [ ] Combining marks displayed correctly - [ ] Emoji width correct Performance: - [ ] Table/List renders 10k rows with scroll - [ ] No O(N) repaint for offscreen Images: - [ ] Kitty Graphics works (if supported) - [ ] Sixel fallback works - [ ] Placeholder when no support ===== See also ===== * [[.:tui-entwicklung|TUI Development Overview]] * [[.:tui-controls|TUI Controls]] * [[.:tui-layout|TUI Layout]]