====== Layout TUI ======
Layout responsive anchoring-first per applicazioni TUI.
L'anchoring e la **modalita default** - ogni controllo si comporta correttamente al resize del terminale senza container speciali.
===== Principio fondamentale =====
Anchoring-First significa:
- Il resize del terminale non deve rompere layout, focus e rendering
- I controlli mantengono relazioni spaziali stabili
- Regole prevedibili di espansione/contrazione
===== Semantica anchor =====
==== Anchor disponibili ====
| Anchor | Significato |
^ Left | Distanza dal bordo sinistro rimane costante |
^ Top | Distanza dal bordo superiore rimane costante |
^ Right | Distanza dal bordo destro rimane costante |
^ Bottom | Distanza dal bordo inferiore rimane costante |
==== Combinazioni ====
Default: Left + Top
→ Posizione rimane stabile, dimensione costante
Left + Right:
→ Larghezza si espande/contrae con larghezza parent
Top + Bottom:
→ Altezza si espande/contrae con altezza parent
Tutti e quattro (Left + Top + Right + Bottom):
→ Rect si espande in entrambe le direzioni
Nessun anchor:
→ Trattare come Left + Top (nessuna ambiguita "floating")
==== Esempi PXAML ====
===== Comportamento resize =====
==== Flusso al resize ====
1. Evento resize ricevuto
└─ Aggiornare rect disponibile root
2. Invalidare layout
└─ Eseguire passaggio Measure/Arrange
3. Mantenere focus
└─ Stesso controllo logico mantiene il focus
4. Re-renderizzare
└─ Paint → DiffFlush
==== Deterministico ====
OBBLIGATORIO:
- Stesso input → stesso layout
- Nessun flicker con resize veloce
- Nessuna corruzione cursore
- Focus rimane sul controllo logico
===== Breakpoint =====
Soglie di resize opzionali ma raccomandate:
==== Breakpoint standard ====
| Breakpoint | Larghezza | Layout tipico |
^ Narrow | < 80 | Colonna singola, impilato |
^ Medium | 80-119 | Sidebar collassata in tab |
^ Wide | >= 120 | Sidebar + contenuto affiancati |
==== Configurazione PXAML ====
==== Regole breakpoint ====
OBBLIGATORIO:
- I breakpoint NON sono "magici" - definire in PXAML o config tema
- Documentare i breakpoint
- Definire chiaramente il comportamento per ogni breakpoint
===== Container layout =====
==== Stack ====
Orientamento: Verticale o orizzontale
I figli vengono disposti in sequenza
==== Dock ====
Posizioni: Left, Top, Right, Bottom, Fill
I figli si agganciano ai lati, il resto riempie il centro
==== Overlay ====
Per popup, modali, tooltip
Si sovrappone ad altri controlli
Deve rimanere entro i bounds dello schermo (clamped)
==== Grid (futuro) ====
Definire righe e colonne
Posizionare controlli nelle celle
===== Precedenza anchoring =====
Ordine di calcolo del layout:
1. Layout container (se esplicito)
└─ Stack/Grid/Dock/Overlay calcola rect figli
2. Applicare anchor
└─ Raffinare all'interno del rect container
└─ Rispettare Min/Max
└─ Preservare margin/padding
3. Clipping per ultimo
└─ Ritagliare bounds finali
===== Scroll e viewport =====
==== Quando il contenuto e piu grande dell'area ====
PREFERITO:
- Usare container ScrollViewer
- Rendere il contenuto scrollabile
NON come default:
- Testo "shrink to fit"
OBBLIGATORIO:
- I controlli possono renderizzare in rect piu piccolo (clip + ellipsis)
- Lo stato non deve andare perso
==== Esempio ScrollViewer ====
===== Focus durante reflow =====
OBBLIGATORIO:
- Il focus viene tracciato tramite identita del controllo (non posizione schermo)
- Dopo il reflow:
- Se il controllo focalizzato e ancora focalizzabile e visibile → mantenere
- Altrimenti: fallback al prossimo sibling focalizzabile nell'ordine focus
==== Stabilita focus ====
procedure TLayoutEngine.ApplyReflow;
var
PreviousFocus: TWvdSControl;
begin
(* Memorizzare focus *)
PreviousFocus := FocusManager.FocusedControl;
(* Ricalcolare layout *)
MeasureAndArrange(RootControl);
(* Ripristinare focus *)
if (PreviousFocus <> nil) and
PreviousFocus.CanFocus and
PreviousFocus.IsVisible then
FocusManager.SetFocus(PreviousFocus)
else
FocusManager.FocusNextAvailable;
end;
===== Verifica =====
==== Test resize ====
[ ] Narrow ↔ Wide ripetuto: nessun flicker
[ ] Cursore non corrotto dopo resize
[ ] Focus rimane sullo stesso controllo
[ ] Controlli anchored stretch non si sovrappongono
[ ] Popup/overlay rimangono nei bounds schermo
==== Test breakpoint ====
[ ] Layout cambia correttamente al superamento breakpoint
[ ] Nessun flicker al cambio breakpoint
[ ] Tutti i breakpoint documentati
==== Test container ====
[ ] Stack dispone i figli correttamente
[ ] Dock riempie correttamente (Left, Top, Right, Bottom, Fill)
[ ] Overlay rimane nei bounds
[ ] Container annidati funzionano
===== Riferimento PXAML =====
==== Attributi controllo ====
| Attributo | Valori | Significato |
^ Anchors | Left,Top,Right,Bottom | Combinazioni anchor |
^ Margin | "l,t,r,b" o "all" | Distanza esterna |
^ Padding | "l,t,r,b" o "all" | Distanza interna |
^ MinWidth | Integer | Larghezza minima |
^ MaxWidth | Integer | Larghezza massima |
^ MinHeight | Integer | Altezza minima |
^ MaxHeight | Integer | Altezza massima |
==== Attributi container ====
| Attributo | Valori | Significato |
^ ResponsiveMode | Auto, Manual | Gestione automatica breakpoint |
^ Breakpoints | "w1,w2,..." | Larghezze breakpoint |
===== Vedi anche =====
* [[.:tui-entwicklung|Panoramica sviluppo TUI]]
* [[.:tui-engine|TUI Engine]]
* [[.:tui-controls|Controlli TUI]]