Inhaltsverzeichnis
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
Zuletzt geändert: 29.01.2026. u 22:40