====== TUI Controls ======
Smjernice implementacije za Controls/Widgets u TUI-Targetu.
Ovaj pattern proširuje postojeći "Model + Renderer" koncept s TUI-specifičnim zahtjevima.
===== Arhitektura =====
==== Model + Renderer Razdvajanje ====
Model (Target-neutralan) Renderer (Target-specifičan)
───────────────────── ─────────────────────────────
TWvdS* Pascal-klasa TUI: CellBuffer via RenderSurface
- Properties, State GUI: Canvas/GDI
- Events, Commands Web: DOM/HTML
- Bez I/O-ovisnosti
==== Deliverables po Controlu ====
| Komponenta | Sadržaj |
^ Model Unit | Properties, Events, State (target-neutralno) |
^ TUI Renderer Unit | Paint, Focus, Input Handling |
^ Pack Manifest | PXAML Tag → Units Mapping |
===== Model Unit (Target-neutralno) =====
==== Sadrži ====
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 sadrži ====
* Terminal I/O ili ANSI-sekvence
* DOM/Web APIs
* Platformno-specifične pozive
===== TUI Renderer Unit =====
==== Interface ====
IWvdSTUIRenderer = interface
(* Layout *)
function Measure(AControl: TWvdSControl; AAvailable: TSize): TSize;
procedure Arrange(AControl: TWvdSControl; ARect: TRect);
(* Rendering *)
procedure Paint(AControl: TWvdSControl; ASurface: TRenderSurface);
(* Input *)
function HandleInput(AControl: TWvdSControl; AEvent: TInputEvent): Boolean;
end;
==== Minimalna implementacija ====
OBAVEZNO za svaki TUI Renderer:
- Deterministički Placeholder-rendering (prije Feature-potpunosti)
- Prikaz Focus-Indikatora
- Prikaz Disabled-Statea
- Tab-Navigacija funkcionira End-to-End
- Opcionalno: Mouse Handling (ako TerminalCaps.SupportsMouse)
===== Visual States =====
==== State-Hijerarhija ====
Obavezni States:
├─ Base (* Default-prikaz *)
├─ Focus (* Ima tipkovnički fokus *)
├─ Disabled (* Nije interaktivan *)
└─ Error/Invalid (* Validacijska greška *)
Opcionalni States:
├─ Hover (* Miš iznad - ako Mouse podržan *)
└─ Pressed (* Aktivno pritisnut *)
==== Rendering po Stateu ====
procedure TWvdSButtonTUIRenderer.Paint(AControl: TWvdSControl;
ASurface: TRenderSurface);
var
Btn: TWvdSButton;
Style: TStyle;
begin
Btn := TWvdSButton(AControl);
(* State-bazirani odabir Stylea *)
if not Btn.Enabled then
Style := Theme.ButtonDisabled
else if Btn.Focused then
Style := Theme.ButtonFocused
else
Style := Theme.ButtonBase;
(* Renderiranje Bordera + Captiona *)
ASurface.DrawBorder(Btn.Bounds, bsSingle);
ASurface.DrawText(Btn.Bounds.Left + 1, Btn.Bounds.Top,
Btn.Caption, Style);
end;
===== Accessibility (TUI-Ekvivalent) =====
OBAVEZNO:
- Focus Ring / Highlight (* Jasno prepoznatljivo *)
- Hotkey/Accelerator Hint (* Opcionalno: [O]dustani *)
- Error State Indicator (* Validacijska greška vidljiva *)
===== Input Semantics =====
==== Focus Navigation ====
OBAVEZNO za svaki fokusirajući Control:
- Tab konzumirati (FocusManager odlučuje o pomicanju)
- Enter/Space ispravno obraditi
- Text Input preko normaliziranih Eventa (ne Raw Keycodes)
==== Input Handler Pattern ====
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; (* Event konzumiran *)
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;
===== Layout Semantics =====
==== Measure ====
function TWvdSButtonTUIRenderer.Measure(AControl: TWvdSControl;
AAvailable: TSize): TSize;
var
Btn: TWvdSButton;
begin
Btn := TWvdSButton(AControl);
(* Minimalna razumna veličina *)
Result.Width := Length(Btn.Caption) + 4; (* Padding + Border *)
Result.Height := 3; (* Border gore/dolje + Text *)
(* Poštivanje Constrainta od Parenta *)
if Result.Width > AAvailable.Width then
Result.Width := AAvailable.Width;
end;
==== Paint-Pravila ====
STRIKTNO:
- Crtati SAMO unutar dodijeljenog Recta
- Clipping MORA biti aktivan
- Nikakve Out-of-Bounds pisanja
===== Virtualizacija =====
Za Controls s velikim količinama podataka (Tables, Lists, Trees, Logs):
OBAVEZNO:
- Renderirati samo vidljive Rows/Items
- Nikakve Per-Row Buffer-alokacije po Frameu
- Ispravno upravljati Scroll-pozicijom
==== Primjer: Virtualizirana Lista ====
procedure TWvdSListTUIRenderer.Paint(AControl: TWvdSControl;
ASurface: TRenderSurface);
var
List: TWvdSList;
VisibleStart, VisibleEnd: Integer;
I, Y: Integer;
begin
List := TWvdSList(AControl);
(* Izračunati samo vidljivo područje *)
VisibleStart := List.ScrollOffset;
VisibleEnd := VisibleStart + List.VisibleRowCount;
if VisibleEnd > List.ItemCount then
VisibleEnd := List.ItemCount;
(* Renderirati samo vidljive iteme *)
Y := 0;
for I := VisibleStart to VisibleEnd - 1 do
begin
ASurface.DrawText(0, Y, List.Items[I], GetItemStyle(I));
Inc(Y);
end;
end;
===== Control Checklista =====
==== A) Visual States ====
[ ] Base State renderira ispravno
[ ] Focus State jasno prepoznatljiv
[ ] Disabled State razlikuje se
[ ] Error/Invalid State vidljiv
==== B) Input ====
[ ] Tab-Navigacija funkcionira
[ ] Enter/Space pokreće akciju (kod Buttona)
[ ] Text Input normaliziran (kod TextEdita)
[ ] Mouse opcionalno podržan
==== C) Layout ====
[ ] Measure vraća razumnu veličinu
[ ] Paint poštuje dodijeljeni Rect
[ ] Nema renderiranja izvan Boundsa
[ ] Resize se ispravno obrađuje
==== D) Performanse ====
[ ] Velike liste virtualizirane
[ ] Nema O(N) Repainta za Offscreen
[ ] Nema nepotrebnih alokacija po Frameu
===== Dokumentacija po Controlu =====
Svaki Control dokumentirati:
WHY: Zašto ovaj Control postoji (Use Cases)
WHEN: Kada koristiti vs. jednostavnije alternative
TUI Notes:
- Capability Requirements (Mouse, Images, TrueColor)
- Resize Behavior (Anchoring/Responsive)
- Known Limitations
===== Vidi također =====
* [[.:tui-entwicklung|TUI-Razvoj Pregled]]
* [[.:tui-engine|TUI Engine]]
* [[.:tui-layout|TUI Layout]]