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

Scroll i Viewport

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 Primjer

<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

Zuletzt geändert: 29.01.2026. u 22:41