.. _ref-layout:
###############################################################################
Layout
###############################################################################
Mit der Property ``Layout`` wird die Art beeinflusst, wie ein Widget seine Children layoutet.
Diese Property ist auf dem Widget implementiert und steht allen Widget-Typen zur Verfügung.
Das Setzen dieser Property auf einem Widget bewirkt, dass auf diesem Widget ein
Layoutmanager installiert wird, der alle direkten Child-Widgets in spezifischer
Art layoutet; dabei werden u.U. Position und Shape der Child-Widgets verändert.
Es gibt verschiedene Arten von Layouts in Maongo. Dies sind
* Fill-Layout (die enthaltenen Children werden so positioniert das sie das Widget ausfüllen)
* Flow-Layout (die enthaltenen Children werden zeilenweise angeordnet)
* Box-Layout (die enthaltenen Children werden neben- bzw. übereinander angeordnet)
* Border-Layout (die enthaltenen Children werden auf die angegebenen Layoutpositionen platziert)
Syntax::
Allgemeines
================================================================================
Der verfügbare Raum für alle Layouts ist per Default der rechteckige Bereich der ``Bounds`` (das umschließende Rechteck
des auf einem Widget gesetzten Shapes) abzüglich eines evtl. ``Padding``.
Die Abstände, die mittels des Parameters ``gap`` für die einzelnen Layouts definiert werden, wirken stets nur zwischen den
gefüllten Bereichen eines Layouts, nie nach außen.
Widgets, deren Property ``Visible`` auf ``false`` steht, werden nicht dargestellt und auch im Layout nicht beachtet.
**"PreferredBounds"**
Zu jedem Layouttyp ist angegeben, welche ``PreferredBounds`` dieses Layout zurück liefert, wenn es danach gefragt wird.
Hintergrund: Neben der Größenangabe, die mit ``Shape`` auf einem Widget gesetzt wird, kann ein Widget auch selbst bestimmen,
welchen Platz es gerne hätte. Dies sind die ``PreferredBounds``. Widgets mit Layouts fragen ihre Children nach ``PreferredBounds``,
um ein optimales Layout zu erzielen. Dieser Mechanismus funktioniert über mehrere Ebenen im Widget-Tree.
``PreferredBounds`` sind eine Widget-Property und können auch explizit gesetzt werden. Siehe :ref:`ref-possize`.
Werden ``PreferredBounds`` vom MAD-Autor gesetzt, so hat dies Vorrang gegenüber dem Widget-eigenen Mechanismus, sie zu bestimmen.
Die meisten Widget-Typen bestimmen ihre ``PreferredBounds`` mit der Größenangabe in ``Shape`` (oder dem Default-Shape, falls ``Shape``
nicht gesetzt ist). Ausnahme: Das Text-Widget ist in der Lage, seine ``PreferredBounds`` anhand der Textmenge zu bestimmen.
**"LayoutConstraints"**
Im Borderlayout müssen die ChildWidgets eines Widgets mit Layout mit der Property ``LayoutConstraints`` versehen werden,
die dem Layout die spezifischen Positionen der einzelnen Child-Widgets mitteilt.
Auch im Filllayout kann die Property ``LayoutConstraints`` angegeben werden, um für einzelne Children ein spezifisches
Layoutverhalten zu erreichen. Bei den anderen Layouts wird eine evtl. vorhandene Property ``LayoutConstraints`` auf den Children ignoriert.
FillLayout
================================================================================
::
Enthält ein Widget, dessen Layout-Property auf ``fill`` gesetzt ist, weitere Widgets,
so werden die Child-Widgets so positioniert, dass sie das Parent-Widget abzüglich eines
eventuellen Paddings ausfüllen. Die Positions- und Shape-Angaben der Child-Widgets werden
also ignoriert.
Dieses Default-Verhalten kann durch LayoutConstraints auf den Child-Widgets verändert werden (s.u.)
**Parameter**
keine
**PreferredBounds**
Die PreferredBounds eines Widgets mit FillLayout werden berechnet, indem die größte Höhe und die größte Breite seiner Children g
enutzt werden; gibt es Children mit ``LayoutConstraints=preserve``, so wird auch die Location des betreffenden Childs mit eingerechnet.
Children mit ``LayoutConstraints=ignore`` werden ignoriert
.. image:: images/mp_layout_bounds1.png
**LayoutConstraints**
Das Verhalten des FillLayouts kann durch die Angabe von LayoutConstraints auf den Childwidgets modifiziert werden.
Bei Child-Widgets ohne LayoutConstraints wird der Default (``padding``) angenommen::
Das FillLayout nutzt je nach eingestellten LayoutConstraints unterschiedliche Modi, um die Größe eines Kindes anzupassen:
Bei ``resize`` wird das Child-Shape vergrößert oder verkleinert (ein Kreis bleibt ein Kreis),
bei ``reshape`` wird das Child-Shape vom Layout neu gesetzt, vom ursprünglichen Shape des Kindes bleibt nichts erhalten.
Mögliche Werte für LayoutConstraints sind:
* ``padding``: das Shape des Child-Widgets wird so verändert (resize), dass es die Bounds des Parents-Shapes minus Padding ausfüllt (Default).
* ``bounds``: das Shape des Child-Widgets wird so verändert (resize), dass es die Bounds das Parent-Shapes ausfüllt.
* ``preserve``: keine Veränderung von Child-Shape und -Location.
* ``ignore``: keine Veränderung von Child-Shape und -Location, widget wird bei der Berechnung der PreferredBounds ignoriert.
* ``preferred``: keine Veränderung der Location, das Child-Shape wird auf seine PreferredBounds gesetzt (resize).
**Beispiel**
Ein Beispiel MAD mit verschiedenen LayoutConstraints: :download:`MAD <../reference/layout/fill.mad>`.
FlowLayout
================================================================================
::
Enthält ein Widget, dessen Layout-Property auf ``flow`` gesetzt ist, weitere Widgets, so werden diese in horizontaler Richtung zeilenweise
angeordnet. Evtl. Positionsangaben im Child-Widget (x, y, Location) werden ignoriert.
Das FlowLayout fragt seine Elemente nach ihren ``PreferredBounds`` und nutzt diese. Das hat zur Folge, dass beispielsweise Textwidgets
den für die Darstellung des enthaltenen Textes nötigen Platz zurückmelden.
**Parameter**
::
gap: Abstand zwischen Children: derselbe Wert für horizontal und vertikal
gap: , Abstand zwischen Children: zwei Werte für horizontal und vertikal
gap: 0.0,0.0 (Default)
**PreferredBounds**
Die PreferredBounds eines Widgets mit FlowLayout werden zurückgeliefert als Breite der Original-Bounds und Höhe des für das Layout der
Children inklusive der Gaps benötigten Bereichs.
.. image:: images/mp_layout_bounds2.png
**LayoutConstraints**
keine
**Beispiel**
Ein Beispiel :download:`MAD <../reference/layout/flow.mad>`.
BoxLayout
================================================================================
::
Enthält ein Widget, dessen Layout-Property auf ``box`` gesetzt ist, weitere Widgets, so werden diese nebeneinander
oder übereinander angeordnet. Evtl. Positionsangaben im Child-Widget werden ignoriert. Für die Behandlung der
Children-Shapes sind die Einstellungen in ``stackmode`` und ``fillmode`` ausschlaggebend.
**Parameter**
::
direction: Richtung, in der das Layout gefüllt wird.
direction: down (Default) von oben nach unten
stackmode: Wie soll das Child-Widget gestapelt werden?
Betrifft die Höhe bei direction=up/down und die Breite bei direction=right/left
stackmode: preferred (Default) die entsprechende Dimension der PreferredBounds nutzen.
stackmode: fill Die Children so skalieren, dass sie den zur Verfügung stehenden Platz
in dieser Dimension ausnutzen.
stackmode: equal Die Children so skalieren, dass sie in dieser Dimension so groß sind wie das
größte Child-Widget.
fillmode: Wie soll das Childwidget den zur Verfügung stehenden Platz ausfüllen?
Betrifft die Breite bei direction=up/down und die Höhe bei direction=right/left
fillmode: fill (Default) Die Children so skalieren, dass sie den zur Verfügung stehenden Platz
in dieser Dimension ausnutzen.
fillmode: preferred Die entsprechende Dimension der PreferredBounds nutzen.
gap: Abstand zwischen Children
gap: 0.0 (Default)
**PreferredBounds**
Die PreferredBounds eines Widgets mit BoxLayout werden zurückgeliefert als (bei direction=up/down) die Breite der
Bounds/PreferredBounds des breitesten Elements und die Summe der Höhen der Bounds/PreferredBounds (zzgl. gaps) der Children,
(bei direction=right/left) die Höhe der Bounds/PreferredBounds des höchsten Elements und die Summe der Breiten der
Bounds/PreferredBounds (zzgl. gaps) der Children.
.. image:: images/mp_layout_bounds3.png
**LayoutConstraints**
keine
**Beispiel**
Ein Beispiel :download:`MAD <../reference/layout/box.mad>`.
BorderLayout
================================================================================
::
Ein Widget, dessen Layout-Property auf ``border`` gesetzt ist, kann bis zu fünf Child-Widgets auf die Layout-Positionen North, West, South, East und Center platzieren. Positions- und Shape-Angaben der Child-Widgets werden dabei u.U. modifiziert::
|north |
- - - - - - - - - - -
west |center| east
- - - - - - - - - - -
|south |
Die fünf Layout-Positionen konkurrieren um den zur Verfügung stehenden Platz. Das Layout fragt stets die PreferredBounds der Children ab und versucht diesen Platzbedarf zu erfüllen. Ist ``mode: wide`` oder ``mode:portrait``, so erhält die Layoutposition ``center`` den Platz, der nach Platzierung der anderen Laypoutpositionen übrig bleibt.
Ist das Attribut ``mode:center``, so erhält die Layoutposition ``center`` den benötigten Platz, und die anderen Layoutpositionen werden entsprechend angepasst.
Außerdem bestimmen die ``mode``-Angaben darüber, wie die Bereiche in den "Ecken" des Layouts benutzt werden.
wide::
north
- - - - - - - - - - -
west |center| east
- - - - - - - - - - -
south
portrait::
|north |
| - - -|
west |center| east
| - - -|
|south |
**Parameter**
::
mode:
mode: wide (Default)
gap: (alle Richtungen)
gap: , (senkrechte Achsen, waagrechte Achsen)
gap: , , , (obere, rechte, untere, linke Achse)
gap: 0 (Default)
**PreferredBounds**
Die ``PreferredBounds`` eines Widgets mit BorderLayout ist die Addition der Breiten und Höhen (zzgl. ``gap``) aller ``PreferredBounds`` der Child-Widgets, nachdem sie entsprechend ihrer ``LayoutConstraints`` in das Layout platziert wurden.
**LayoutConstraints**
Innerhalb eines Widgets mit ``Layout=border`` müssen alle Children eine eindeutige Angabe in ihrer Property ``LayoutConstraints`` haben. Layoutpositionen können also nicht mehrfach belegt werden::
Für die Angabe der Himmelsrichtungen ist sowohl die Lang- als auch die Kurzschreibweise (``n, w, s, e, c``) möglich.
**Beispiel**
Ein Beispiel :download:`MAD <../reference/layout/border_preferred.mad>`.