TUI Engine

Arhitektura in zahteve kakovosti TUI izrisovalnega motorja.

Te zahteve so neizpogajljive - določajo minimalni standard za kakovost TUI podobno GUI.

Zahteve kakovosti

1. Izrisovanje brez utripanja

OBVEZNO:
- Dvojno medpomnenje z diferenčnim izpiranjem
- Optimizacija umazanih pravokotnikov ali stiskanja zaporedij
- Brez popolnih ponovnih izrisov zaslona v zanki

Zakaj: Utripanje uničuje uporabniško izkušnjo in naredi TUI neuporaben za profesionalne aplikacije.

2. Deterministična razporeditev + obrezovanje

OBVEZNO:
- Implementiran življenjski cikel Measure/Arrange/Paint
- Risanje obrezano na dodeljene pravokotnike
- Brez pisanja izven meja

3. Pravilnost Unicode

OBVEZNO:
- Pravilno ravnanje s širokimi znaki (East Asian Width)
- Pravilno ravnanje s kombinirnimi oznakami
- Pravilno izračunavanje širine emojijev
- Pozicioniranje kurzorja mora upoštevati grafeme

Problem: „Plavajoči kazalec“ - kurzor drsi pri širokih znakih.

Rešitev: Uporaba grafemskih grozdov za izračun kurzorja.

4. Tema + plastenje stanj

OBVEZNO:
- Podpora žetonom slogov
- Implementirana plast stanj:
  Base → Hover (če miška) → Focus → Pressed → Disabled → Error/Validation
- Indikatorji fokusa konsistentni čez vse kontrole

5. Vnos + fokus kot prvovrstna

OBVEZNO:
- Navigacija s fokusom (Tab/Shift+Tab)
- Deterministično urejanje fokusa
- Normaliziran model vnosnih dogodkov:
  Tipke, vnos besedila, sprememba velikosti, opcijska miška

6. Zmogljivost in skaliranje

OBVEZNO:
- Virtualizacija za velike površine (tabele/dnevniki/drevesa)
- Izogibanje O(N) ponovnemu izrisovanju vrstic/stolpcev izven zaslona
- Učinkovita poraba pomnilnika

7. Podpora slik (SCADA/MES)

OBVEZNO:
- Implementirano zaznavanje zmogljivosti
- Nadomestna veriga:
  1. Kitty Graphics (prednostno)
  2. Sixel
  3. Nadomestek (okvir + napis + "slika ni na voljo")

Gradniki motorja

A) Plast zmogljivosti terminala

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) Model izrisovanja: CellBuffer + DiffEngine

TCell = record
  Grapheme: string;      (* Unicode grafemski grozd *)
  Fg: TColor;            (* Barva ospredja *)
  Bg: TColor;            (* Barva ozadja *)
  Attrs: TAttributes;    (* Krepko, ležeče, podčrtano, itd. *)
  Link: string;          (* Opcijsko: hiperpovezava *)
  ImageRef: Integer;     (* Opcijsko: referenca slike *)
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;   (* Ciljni okvir *)
  FFrontBuffer: TCellBuffer;  (* Zadnji izpran okvir *)
public
  procedure ComputeDiff(out ADirtyRects: TRectArray);
  procedure Flush(ATerminal: TTerminalIO);
end;

Zahteve za DiffEngine:

  • Minimalni premiki kurzorja
  • Minimalne menjave slogov
  • Stabilnost pri hitri spremembi velikosti

C) Izrisovalna površina (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;

Pomembno: Surface piše samo v BackBuffer, ne neposredno v TerminalIO.

D) Motor razporeditve

Kontrole se razporedijo v pravokotnike.

Minimalni vsebniki:
- Stack (navpično/vodoravno)
- Dock (Left, Top, Right, Bottom, Fill)
- Grid (kasneje)
- Overlay (za pojavna okna/modalna okna)

E) Pogodba za izrisovanje gradnikov/kontrol

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;

Testiranje

Testi posnetkov

OBVEZNO:
- Izpis BackBuffer v stabilno tekstovno predstavitev
- Primerjava s pričakovanim izhodom

Unicode testni primeri

OBVEZNO:
- Testi s širokimi znaki (中文, 日本語)
- Testi s kombinirnimi oznakami (é = e + ´)
- Testi z emojiji (👍, 🎉)

Testi nadomestkov za slike

OBVEZNO:
- Testiranje nadomestne verige Kitty → Sixel → Placeholder
- Preverjanje zaznavanja zmogljivosti

Kontrolni seznam preverjanja

Preverjanje TUI Engine:

Izrisovanje:
- [ ] Brez utripanja pri ponavljajočem se ponovnem izrisovanju
- [ ] Sprememba velikosti proizvede stabilen razpored
- [ ] Brez obtičanega kurzorja
- [ ] Brez prekinjenega obrezovanja

Unicode:
- [ ] Široki znaki pravilno pozicionirani
- [ ] Kombinirne oznake pravilno prikazane
- [ ] Širina emojijev pravilna

Zmogljivost:
- [ ] Table/List izrisuje 10k vrstic z drsenjem
- [ ] Brez O(N) ponovnega izrisovanja za izven zaslona

Slike:
- [ ] Kitty Graphics deluje (če podprto)
- [ ] Sixel nadomestek deluje
- [ ] Nadomestek pri manjkajoči podpori

Glejte tudi

Zuletzt geändert: dne 29.01.2026 ob 22:25