====== TUI Layout ======
Anchoring-First Responsive Layout für TUI-Anwendungen.
Anchoring ist der **Default-Modus** - jedes Control verhält sich korrekt bei Terminal-Resize ohne spezielle Container.
===== Grundprinzip =====
Anchoring-First bedeutet:
- Terminal Resize darf Layout, Focus und Rendering nicht brechen
- Controls behalten stabile räumliche Beziehungen
- Vorhersagbare Expansion/Shrinking-Regeln
===== Anchor-Semantik =====
==== Verfügbare Anchors ====
| Anchor | Bedeutung |
^ Left | Abstand zum linken Rand bleibt konstant |
^ Top | Abstand zum oberen Rand bleibt konstant |
^ Right | Abstand zum rechten Rand bleibt konstant |
^ Bottom | Abstand zum unteren Rand bleibt konstant |
==== Kombinationen ====
Default: Left + Top
→ Position bleibt stabil, Größe konstant
Left + Right:
→ Breite dehnt/schrumpft mit Parent-Breite
Top + Bottom:
→ Höhe dehnt/schrumpft mit Parent-Höhe
Alle vier (Left + Top + Right + Bottom):
→ Rect dehnt sich in beide Richtungen
Keine Anchors:
→ Behandeln wie Left + Top (keine "floating" Ambiguität)
==== PXAML Beispiele ====
===== Resize-Verhalten =====
==== Ablauf bei Resize ====
1. Resize Event empfangen
└─ Root Available Rect aktualisieren
2. Layout invalidieren
└─ Measure/Arrange Pass durchführen
3. Focus erhalten
└─ Gleicher logischer Control behält Focus
4. Neu rendern
└─ Paint → DiffFlush
==== Deterministisch ====
PFLICHT:
- Gleicher Input → Gleiches Layout
- Kein Flicker bei schnellem Resize
- Kein Cursor-Corruption
- Focus bleibt auf logischem Control
===== Breakpoints =====
Optionale aber empfohlene Resize-Schwellwerte:
==== Standard-Breakpoints ====
| Breakpoint | Breite | Typisches Layout |
^ Narrow | < 80 | Single-Column, gestapelt |
^ Medium | 80-119 | Sidebar collapsed zu Tabs |
^ Wide | >= 120 | Sidebar + Content nebeneinander |
==== PXAML Konfiguration ====
==== Breakpoint-Regeln ====
PFLICHT:
- Breakpoints NICHT "magic" - in PXAML oder Theme Config definieren
- Breakpoints dokumentieren
- Verhalten bei jedem Breakpoint klar definieren
===== Layout-Container =====
==== Stack ====
Orientierung: Vertikal oder Horizontal
Kinder werden nacheinander angeordnet
==== Dock ====
Positionen: Left, Top, Right, Bottom, Fill
Kinder docken an Seiten, Rest füllt Mitte
==== Overlay ====
Für Popups, Modals, Tooltips
Überlagert andere Controls
Muss innerhalb Screen Bounds bleiben (clamped)
==== Grid (später) ====
Zeilen und Spalten definieren
Controls in Zellen platzieren
===== Anchoring-Precedence =====
Reihenfolge der Layout-Berechnung:
1. Container Layout (wenn explizit)
└─ Stack/Grid/Dock/Overlay berechnet Child-Rects
2. Anchors anwenden
└─ Innerhalb des Container-Rects verfeinern
└─ Min/Max beachten
└─ Margins/Padding erhalten
3. Clipping zuletzt
└─ Finale Bounds beschneiden
===== Scroll und Viewport =====
==== Wenn Content größer als Bereich ====
BEVORZUGT:
- ScrollViewer Container verwenden
- Content scrollbar machen
NICHT als Default:
- Text "shrink to fit"
PFLICHT:
- Controls können in kleinerem Rect rendern (Clip + Ellipsis)
- State darf nicht verloren gehen
==== ScrollViewer Beispiel ====
===== Focus unter Reflow =====
PFLICHT:
- Focus wird über Control-Identität getrackt (nicht Screen-Position)
- Nach Reflow:
- Wenn fokussiertes Control noch fokussierbar und sichtbar → behalten
- Sonst: Fallback auf nächstes fokussierbares Sibling in Focus-Order
==== Focus-Stabilität ====
procedure TLayoutEngine.ApplyReflow;
var
PreviousFocus: TWvdSControl;
begin
(* Focus merken *)
PreviousFocus := FocusManager.FocusedControl;
(* Layout neu berechnen *)
MeasureAndArrange(RootControl);
(* Focus wiederherstellen *)
if (PreviousFocus <> nil) and
PreviousFocus.CanFocus and
PreviousFocus.IsVisible then
FocusManager.SetFocus(PreviousFocus)
else
FocusManager.FocusNextAvailable;
end;
===== Verifikation =====
==== Resize-Tests ====
[ ] Narrow ↔ Wide wiederholt: kein Flicker
[ ] Cursor nicht korrupt nach Resize
[ ] Focus bleibt auf gleichem Control
[ ] Anchored Stretch Controls überlappen nicht
[ ] Popups/Overlays bleiben in Screen Bounds
==== Breakpoint-Tests ====
[ ] Layout wechselt korrekt bei Breakpoint-Überschreitung
[ ] Kein Flicker beim Breakpoint-Wechsel
[ ] Alle Breakpoints dokumentiert
==== Container-Tests ====
[ ] Stack ordnet Kinder korrekt an
[ ] Dock füllt korrekt (Left, Top, Right, Bottom, Fill)
[ ] Overlay bleibt in Bounds
[ ] Nested Containers funktionieren
===== PXAML Referenz =====
==== Control-Attribute ====
| Attribut | Werte | Bedeutung |
^ Anchors | Left,Top,Right,Bottom | Anchor-Kombinationen |
^ Margin | "l,t,r,b" oder "all" | Äußerer Abstand |
^ Padding | "l,t,r,b" oder "all" | Innerer Abstand |
^ MinWidth | Integer | Minimale Breite |
^ MaxWidth | Integer | Maximale Breite |
^ MinHeight | Integer | Minimale Höhe |
^ MaxHeight | Integer | Maximale Höhe |
==== Container-Attribute ====
| Attribut | Werte | Bedeutung |
^ ResponsiveMode | Auto, Manual | Automatisches Breakpoint-Handling |
^ Breakpoints | "w1,w2,..." | Breakpoint-Breiten |
===== Siehe auch =====
* [[.:tui-entwicklung|TUI-Entwicklung Übersicht]]
* [[.:tui-engine|TUI Engine]]
* [[.:tui-controls|TUI Controls]]