TUI Layout
Anchoring-First Responsive Layout za TUI-aplikacije.
Anchoring je Default-Mode - svaki Control se ponaša ispravno pri Terminal-Resizeu bez posebnih Containera.
Temeljno načelo
Anchoring-First znači:
- Terminal Resize ne smije pokvariti Layout, Focus i Rendering
- Controls zadržavaju stabilne prostorne odnose
- Predvidljiva pravila Expansion/Shrinking
Anchor-Semantika
Dostupni Anchori
| Anchor | Značenje |
| Left | Udaljenost od lijevog ruba ostaje konstantna |
| Top | Udaljenost od gornjeg ruba ostaje konstantna |
| Right | Udaljenost od desnog ruba ostaje konstantna |
| Bottom | Udaljenost od donjeg ruba ostaje konstantna |
Kombinacije
Default: Left + Top
→ Pozicija ostaje stabilna, veličina konstantna
Left + Right:
→ Širina se rasteže/skuplja sa širinom Parenta
Top + Bottom:
→ Visina se rasteže/skuplja s visinom Parenta
Sva četiri (Left + Top + Right + Bottom):
→ Rect se rasteže u oba smjera
Bez Anchora:
→ Tretirati kao Left + Top (bez "floating" nejasnoće)
PXAML Primjeri
<!-- Fiksna pozicija gore lijevo -->
<Button Anchors="Left,Top" Text="OK" />
<!-- Puna širina, fiksna visina -->
<TextEdit Anchors="Left,Top,Right" Height="3" />
<!-- Ispunjava cijelo dostupno područje -->
<ListView Anchors="Left,Top,Right,Bottom" />
<!-- Statusna traka dolje -->
<StatusBar Anchors="Left,Right,Bottom" Height="1" />
Resize-Ponašanje
Tok pri Resizeu
1. Primiti Resize Event
└─ Ažurirati Root Available Rect
2. Invalidirati Layout
└─ Izvršiti Measure/Arrange Pass
3. Zadržati Focus
└─ Isti logički Control zadržava Focus
4. Ponovno renderirati
└─ Paint → DiffFlush
Deterministički
OBAVEZNO:
- Isti Input → Isti Layout
- Nema flickera kod brzog Resizea
- Nema Cursor-Corruptiona
- Focus ostaje na logičkom Controlu
Breakpoints
Opcionalni ali preporučeni Resize-pragovi:
Standardni Breakpoints
| Breakpoint | Širina | Tipični Layout |
| Narrow | < 80 | Single-Column, složeno |
| Medium | 80-119 | Sidebar kolabiran u Tabove |
| Wide | >= 120 | Sidebar + Content jedan pored drugog |
PXAML Konfiguracija
<Panel ResponsiveMode="Auto" Breakpoints="80,120">
<!-- Automatski Reflow pri prijelazu Breakpointa -->
</Panel>
Breakpoint-Pravila
OBAVEZNO:
- Breakpoints NISU "magic" - definirati u PXAML ili Theme Config
- Breakpoints dokumentirati
- Ponašanje za svaki Breakpoint jasno definirati
Layout-Containeri
Stack
Orijentacija: Vertikalno ili Horizontalno
Djeca se aranžiraju jedno za drugim
<Stack Orientation="Vertical">
<Label Text="Ime:" />
<TextEdit />
<Label Text="Email:" />
<TextEdit />
</Stack>
Dock
Pozicije: Left, Top, Right, Bottom, Fill
Djeca se pričvršćuju na strane, ostatak ispunjava sredinu
<Dock>
<MenuBar Dock="Top" />
<StatusBar Dock="Bottom" />
<Sidebar Dock="Left" Width="20" />
<Content Dock="Fill" />
</Dock>
Overlay
Za Popupe, Modale, Tooltipe
Prekriva druge Controls
Mora ostati unutar Screen Boundsa (clamped)
<Overlay>
<Dialog X="10" Y="5" Width="40" Height="10">
<!-- Modal Content -->
</Dialog>
</Overlay>
Grid (kasnije)
Definiranje Redaka i Stupaca
Postavljanje Controls u ćelije
Anchoring-Precedence
Redoslijed izračuna Layouta:
1. Container Layout (ako eksplicitno)
└─ Stack/Grid/Dock/Overlay izračunava Child-Rectove
2. Primjena Anchora
└─ Unutar Container-Recta rafinirati
└─ Poštivati Min/Max
└─ Zadržati Margins/Padding
3. Clipping na kraju
└─ Rezanje finalnih Boundsa
Kada je Content veći od područja
PREFERIRANO:
- Koristiti ScrollViewer Container
- Content učiniti scrollabilnim
NIJE Default:
- Text "shrink to fit"
OBAVEZNO:
- Controls mogu renderirati u manjem Rectu (Clip + Ellipsis)
- State se ne smije izgubiti
<ScrollViewer Anchors="Left,Top,Right,Bottom">
<Stack Orientation="Vertical">
<!-- Dugačka lista Controls -->
</Stack>
</ScrollViewer>
Focus pod Reflow
OBAVEZNO:
- Focus se prati preko Control-Identiteta (ne Screen-pozicije)
- Nakon Reflowa:
- Ako fokusirani Control još može imati fokus i vidljiv je → zadržati
- Inače: Fallback na sljedeći fokusirajući Sibling u Focus-Orderu
Focus-Stabilnost
procedure TLayoutEngine.ApplyReflow;
var
PreviousFocus: TWvdSControl;
begin
(* Zapamtiti Focus *)
PreviousFocus := FocusManager.FocusedControl;
(* Ponovno izračunati Layout *)
MeasureAndArrange(RootControl);
(* Vratiti Focus *)
if (PreviousFocus <> nil) and
PreviousFocus.CanFocus and
PreviousFocus.IsVisible then
FocusManager.SetFocus(PreviousFocus)
else
FocusManager.FocusNextAvailable;
end;
Verifikacija
Resize-Testovi
[ ] Narrow ↔ Wide ponovljeno: nema flickera
[ ] Cursor nije korumpiran nakon Resizea
[ ] Focus ostaje na istom Controlu
[ ] Anchored Stretch Controls se ne preklapaju
[ ] Popupi/Overlayi ostaju u Screen Boundsima
Breakpoint-Testovi
[ ] Layout se ispravno mijenja pri prijelazu Breakpointa
[ ] Nema flickera pri promjeni Breakpointa
[ ] Svi Breakpointi dokumentirani
Container-Testovi
[ ] Stack ispravno aranžira djecu
[ ] Dock ispravno ispunjava (Left, Top, Right, Bottom, Fill)
[ ] Overlay ostaje u Boundsima
[ ] Ugniježdeni Containeri funkcioniraju
PXAML Referenca
Control-Atributi
| Atribut | Vrijednosti | Značenje |
| Anchors | Left,Top,Right,Bottom | Anchor-kombinacije |
| Margin | „l,t,r,b“ ili „all“ | Vanjski razmak |
| Padding | „l,t,r,b“ ili „all“ | Unutarnji razmak |
| MinWidth | Integer | Minimalna širina |
| MaxWidth | Integer | Maksimalna širina |
| MinHeight | Integer | Minimalna visina |
| MaxHeight | Integer | Maksimalna visina |
Container-Atributi
| Atribut | Vrijednosti | Značenje |
| ResponsiveMode | Auto, Manual | Automatsko Breakpoint-Handling |
| Breakpoints | „w1,w2,…“ | Breakpoint-širine |
Vidi također