====== 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 =====
* [[.:tui-entwicklung|Pregled TUI razvoja]]
* [[.:tui-engine|TUI Engine]]
* [[.:tui-layout|TUI Layout]]