Inhaltsverzeichnis
TUI Controls
Smernice za implementacijo kontrol/gradnikov v TUI cilju.
Ta vzorec razširja obstoječi koncept „Model + Renderer“ s TUI specifičnimi zahtevami.
Arhitektura
Ločitev modela in izrisovalnika
Model (Ciljno neodvisen) Renderer (Ciljno specifičen) ───────────────────── ───────────────────────────── TWvdS* Pascal razred TUI: CellBuffer preko RenderSurface - Lastnosti, stanje GUI: Canvas/GDI - Dogodki, ukazi Web: DOM/HTML - Brez I/O odvisnosti
Izdelki za vsako kontrolo
| Komponenta | Vsebina |
| Model enota | Lastnosti, dogodki, stanje (ciljno neodvisno) |
|---|---|
| TUI Renderer enota | Paint, Focus, obravnava vnosa |
| Manifest paketa | PXAML oznaka → preslikava enot |
Model enota (ciljno neodvisna)
Vsebuje
TWvdSButton = class(TWvdSControl) private FCaption: string; FEnabled: Boolean; FFocused: Boolean; FPressed: Boolean; FOnClick: TNotifyEvent; public property Caption: string read FCaption write SetCaption; property Enabled: Boolean read FEnabled write SetEnabled; property Focused: Boolean read FFocused write SetFocused; property OnClick: TNotifyEvent read FOnClick write FOnClick; end;
NE vsebuje
- Terminal I/O ali ANSI zaporedij
- DOM/Web API-jev
- Platformno specifičnih klicev
TUI Renderer enota
Vmesnik
IWvdsTUIRenderer = interface (* Razporeditev *) function Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; procedure Arrange(AControl: TWvdSControl; ARect: TRect); (* Izrisovanje *) procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface); (* Vnos *) function HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; end;
Minimalna implementacija
OBVEZNO za vsak TUI Renderer: - Deterministično izrisovanje nadomestka (pred popolnostjo funkcij) - Prikaz indikatorja fokusa - Prikaz stanja onemogočeno - Navigacija s Tab deluje od konca do konca - Opcijsko: obravnava miške (če TerminalCaps.SupportsMouse)
Vizualna stanja
Hierarhija stanj
Obvezna stanja: ├─ Base (* Privzeti prikaz *) ├─ Focus (* Ima tipkovnični fokus *) ├─ Disabled (* Ni interaktivno *) └─ Error/Invalid (* Napaka pri preverjanju *) Opcijska stanja: ├─ Hover (* Miška nad - če miška podprta *) └─ Pressed (* Aktivno pritisnjen *)
Izrisovanje glede na stanje
procedure TWvdSButtonTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var Btn: TWvdSButton; Style: TStyle; begin Btn := TWvdSButton(AControl); (* Izbira sloga na podlagi stanja *) if not Btn.Enabled then Style := Theme.ButtonDisabled else if Btn.Focused then Style := Theme.ButtonFocused else Style := Theme.ButtonBase; (* Izriši rob + napis *) ASurface.DrawBorder(Btn.Bounds, bsSingle); ASurface.DrawText(Btn.Bounds.Left + 1, Btn.Bounds.Top, Btn.Caption, Style); end;
Dostopnost (TUI ekvivalent)
OBVEZNO: - Obroč fokusa / poudarek (* Jasno prepoznaven *) - Namig za bližnjico (* Opcijsko: [P]rekliči *) - Indikator stanja napake (* Napaka pri preverjanju vidna *)
Semantika vnosa
Navigacija s fokusom
OBVEZNO za vsako fokusabilno kontrolo: - Tab porabi (FocusManager odloča o premiku) - Enter/Space pravilno obdela - Vnos besedila prek normaliziranih dogodkov (ne surovih kod tipk)
Vzorec obravnave vnosa
function TWvdSButtonTUIRenderer.HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean; var Btn: TWvdSButton; begin Result := False; Btn := TWvdSButton(AControl); if not Btn.Enabled then Exit; if not Btn.Focused then Exit; case AEvent.Kind of iekKey: if AEvent.Key in [vkReturn, vkSpace] then begin if Assigned(Btn.OnClick) then Btn.OnClick(Btn); Result := True; (* Dogodek porabljen *) end; iekMouse: if (AEvent.MouseButton = mbLeft) and (AEvent.MouseAction = maClick) then begin if Assigned(Btn.OnClick) then Btn.OnClick(Btn); Result := True; end; end; end;
Semantika razporeditve
Measure
function TWvdSButtonTUIRenderer.Measure(AControl: TWvdSControl; AAvailable: TSize): TSize; var Btn: TWvdSButton; begin Btn := TWvdSButton(AControl); (* Minimalna razumna velikost *) Result.Width := Length(Btn.Caption) + 4; (* Odmik + rob *) Result.Height := 3; (* Rob zgoraj/spodaj + besedilo *) (* Upoštevaj omejitve starša *) if Result.Width > AAvailable.Width then Result.Width := AAvailable.Width; end;
Pravila za Paint
STROGO: - SAMO znotraj dodeljenega Rect risati - Obrezovanje MORA biti aktivno - Brez pisanja izven meja
Virtualizacija
Za kontrole z velikimi količinami podatkov (tabele, seznami, drevesa, dnevniki):
OBVEZNO: - Izrisuj samo vidne vrstice/elemente - Brez dodeljevanja medpomnilnika za vsako vrstico v vsakem okvirju - Pravilno upravljanje položaja drsenja
Primer: Virtualiziran seznam
procedure TWvdSListTUIRenderer.Paint(AControl: TWvdSControl; ASurface: TRenderSurface); var List: TWvdSList; VisibleStart, VisibleEnd: Integer; I, Y: Integer; begin List := TWvdSList(AControl); (* Izračunaj samo vidno območje *) VisibleStart := List.ScrollOffset; VisibleEnd := VisibleStart + List.VisibleRowCount; if VisibleEnd > List.ItemCount then VisibleEnd := List.ItemCount; (* Izriši samo vidne elemente *) Y := 0; for I := VisibleStart to VisibleEnd - 1 do begin ASurface.DrawText(0, Y, List.Items[I], GetItemStyle(I)); Inc(Y); end; end;
Kontrolni seznam za kontrole
A) Vizualna stanja
[ ] Osnovno stanje se pravilno izrisuje [ ] Stanje fokusa jasno prepoznavno [ ] Stanje onemogočeno razločljivo [ ] Stanje napake/neveljavnosti vidno
B) Vnos
[ ] Navigacija s Tab deluje [ ] Enter/Space sproži akcijo (pri gumbih) [ ] Vnos besedila normaliziran (pri TextEdit) [ ] Miška opcijsko podprta
C) Razporeditev
[ ] Measure vrne smiselno velikost [ ] Paint upošteva dodeljen Rect [ ] Brez izrisovanja izven meja [ ] Sprememba velikosti pravilno obdelana
D) Zmogljivost
[ ] Veliki seznami virtualizirani [ ] Brez O(N) ponovnega izrisovanja za izven zaslona [ ] Brez nepotrebnih dodeljevanj na okvir
Dokumentacija za vsako kontrolo
Dokumentiraj vsako kontrolo: WHY: Zakaj ta kontrola obstaja (primeri uporabe) WHEN: Kdaj uporabiti vs. enostavnejše alternative TUI opombe: - Zahteve zmogljivosti (Mouse, Images, TrueColor) - Obnašanje ob spremembi velikosti (Sidranje/Odzivnost) - Znane omejitve
Glejte tudi
Zuletzt geändert: dne 29.01.2026 ob 22:25