TUI Development

Overview of Terminal UI (TUI) development for WvdS FPC RAD Studio.

TUI rendering in WvdS achieves GUI-like quality: flicker-free, Unicode-correct, themeable, virtualized.

What is TUI?

Terminal User Interface (TUI) enables graphical interfaces in the terminal:

  • Text-based display - Characters instead of pixels
  • Cross-platform - Runs on Windows Terminal, WezTerm, iTerm2, Linux Console
  • Resource-efficient - Ideal for servers, SSH, containers
  • Accessible - Screen reader compatible

When to Use TUI

Use Case Recommended
Server administration TUI
SSH-based tools TUI
Containers/Docker TUI
CI/CD pipelines TUI
Desktop application with GUI Desktop (LCL)
Web application Web (pas2js)
Both (Server + Desktop) TUI + Desktop

WvdS TUI Standard

The WvdS TUI standard targets Ratatui-level quality or better:

Quality Characteristics

Characteristic Description
Flicker-free Double-buffering, diff-based flush
Unicode-correct Wide chars, emoji, grapheme-aware cursor
Themeable Style tokens, state layering
Virtualized Efficiently render large data sets
Responsive Anchoring-first layout, resize-stable
Image-capable Kitty/Sixel with fallback

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│  PXAML (Markup)                                             │
├─────────────────────────────────────────────────────────────┤
│  Control Model (TWvdS*) - Target-neutral                    │
├─────────────────────────────────────────────────────────────┤
│  TUI Renderer - Target-specific                             │
├─────────────────────────────────────────────────────────────┤
│  Render Surface → CellBuffer → DiffEngine                   │
├─────────────────────────────────────────────────────────────┤
│  Terminal IO (ANSI Escape Sequences)                        │
└─────────────────────────────────────────────────────────────┘

Core Concepts

Target-Neutral Models

Control models contain no terminal-specific logic:

(* CORRECT - Target-neutral *)
TWvdSButton = class(TWvdSControl)
private
  FCaption: string;
  FOnClick: TNotifyEvent;
public
  property Caption: string read FCaption write SetCaption;
  property OnClick: TNotifyEvent read FOnClick write FOnClick;
end;
 
(* FORBIDDEN - Terminal-specific in model *)
TWvdSButton = class(TWvdSControl)
  procedure WriteAnsiSequence;  (* FORBIDDEN! *)
end;

Target-Specific Renderers

Renderers draw the model to the CellBuffer:

TWvdSTUIButtonRenderer = class(TWvdSTUIRenderer)
public
  procedure Measure(AControl: TWvdSControl; AAvail: TSize): TSize; override;
  procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface); override;
  function HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; override;
end;

Anchoring as Default

Every control has anchoring enabled by default:

Anchors: Left, Top, Right, Bottom

Default: Left+Top (stable position)
Left+Right: Width stretches with parent
Top+Bottom: Height stretches with parent
All four: Rect stretches in both directions

TUI Documentation

Document Content
TUI Engine CellBuffer, DiffEngine, Terminal Capabilities
TUI Controls Control implementation, focus, input
TUI Layout Anchoring, responsive, breakpoints

Quick Start: Creating a TUI Control

1. Model Unit (target-neutral)

unit WvdS.UI.Controls.MyControl;
 
type
  TWvdSMyControl = class(TWvdSControl)
  private
    FValue: string;
  public
    property Value: string read FValue write SetValue;
  end;

2. TUI Renderer Unit

unit WvdS.UI.TUI.Renderers.MyControl;
 
type
  TWvdSTUIMyControlRenderer = class(TWvdSTUIRenderer)
  public
    procedure Measure(AControl: TWvdSControl; AAvail: TSize): TSize; override;
    procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface); override;
  end;

3. Pack Manifest

{
  "id": "mycontrol",
  "renderers": {
    "tui": {
      "unit": "WvdS.UI.TUI.Renderers.MyControl",
      "class": "TWvdSTUIMyControlRenderer"
    }
  },
  "targetCaps": {
    "requires": ["keyboard"],
    "optional": ["mouse"]
  }
}

Verification

Every TUI implementation must be verified:

[ ] No flicker during repeated repaint
[ ] Resize produces stable layout
[ ] TextEdit caret is stable with wide/combining chars
[ ] Table/List renders 10k rows with smooth scroll
[ ] Images behave correctly per TerminalCaps
[ ] Focus remains stable through reflow

See also

Zuletzt geändert: on 2026/01/29 at 10:27 PM