Skip to content

Layout Managers#

Layout manager is an object that manages placement and size of views inside containers.

Detailed Description#

In AUI, layout building consists of layout managers. Layout manager determines position and size of container's children views. A container is a AView "view" that consists of other views, called children. In general, layout manager does not allow going beyond the border of the container. A container can be a child of an another container i.e., nesting is allowed.

The ALayout is the base class for all layout managers in AUI. Layout managers are responsible for:

  • Positioning child views within their container
  • Calculating minimum sizes
  • Handling view additions and removals
  • Managing spacing between views
  • Respecting view margins and alignment
  • Supporting expanding/stretching of views

Note

You can use AUI Devtools to play around with layouts, especially with Expanding property, to get better understanding on how does layout work in AUI.

Common layout managers include:

Key concepts:

  1. Minimum Size - Layout managers calculate minimum size requirements by:
  2. Considering minimum sizes of child views
  3. Adding margins and spacing
  4. Respecting fixed size constraints
  5. Following AUI Box Model.

  6. Expanding Views - Children can expand to fill available space of their parent:

  7. Set via AView::setExpanding() or ass::Expanding on a child
  8. Requires parent to have ass::FixedSize or ass::MinSize or Expanding set to take effect
  9. Independent for horizontal/vertical directions
  10. Ignored if ass::FixedSize is set

  11. Spacing - Configurable gaps between views:

  12. Set via ALayout::setSpacing() or ass::LayoutSpacing of the parent view
  13. Part of minimum size calculations of the parent view
  14. Applied uniformly between its child views

  15. Margins - Space around individual views:

  16. Set per-view via ASS or margins property
  17. Respected during layout
  18. Part of minimum size calculations of the parent view

  19. Layout Direction - Overall flow direction:

  20. Horizontal layouts flow left-to-right
  21. Vertical layouts flow top-to-bottom
  22. Grid layouts use both directions

  23. Relativeness - children position is relative to parent's position, not an absolute position within a window.

  24. Nesting - you can nest containers into containers, and so on. When we say "container", it means a AViewContainer. When we say "Vertical", we imply a AViewContainer with AVerticalLayout as the layout manager.

Layout Examples#

Horizontal layout:

Code Result
setContents(
  Horizontal {
    _new<AButton>("1"),
    _new<AButton>("2"),
    _new<AButton>("3"),
  }
);

Vertical layout:

Code Result
setContents(
  Vertical {
    _new<AButton>("1"),
    _new<AButton>("2"),
    _new<AButton>("3"),
  }
);

Since container can be child of other container, we can create complex UIs using basic layout managers:

Code Result
setContents(
  Vertical {
    _new<AButton>("Up"),
    Horizontal {
        _new<AButton>("Left"),
        _new<AButton>("Right"),
    },
    _new<AButton>("Down"),
  }
);

Stacked layout:

Code Result
setContents(
  Stacked {
    _new<AView>() AUI_WITH_STYLE { BackgroundSolid(0xff0000_rgb), Expanding() },
    Label { "Test" },
  }
);
![](imgs/Screenshot_20250625_011101.png)

Expanding#

Expanding (often referred as stretch factor) is a property of any AView. Expanding is an expansion coefficient set on per-axis basic (i.e, one value along x axis, another value along y axis), however it's convenient to set both values. Hints layout manager how much this AView should be extended relative to other AViews in the same container.

Note

You can use AUI Devtools to play around with layouts, especially with Expanding property, to get better understanding on how does layout work in AUI.

Horizontal layouts ignore y expanding of their children, Vertical layouts ignore x expanding of their children.

Views are normally created without any expanding set. When Expanding views appear in a layout they are given a share of space in accordance with their expanding or their minimum size whichever gives more space to them. Expanding is used to change how much space views are given in proportion to one another.

Expanding view does not affect parent's size or parent's expanding property. Use AView::setExpanding() on parent, or Expanding variant of declarative container notation (Vertical::Expanding, Horizontal::Expanding, Stacked::Expanding) for such case.

Expanding views use free space of their container to grow.

Free space of a container is determined by its size subtracted by sum of minimum sizes of its children. Please note that your container would probably occupy minimum possible size (determined by minimum sizes of its children). It order to make container larger than minimum possible size, you can specify FixedSize or MinSize or Expanding to the container.

You can use ass::Expanding ASS property, or AView::setExpanding method to specify Expanding:

Code Result
setContents(
  Vertical {
    _new<AButton>("Up"),
    Horizontal {
      _new<AButton>("Left"),
      _new<AButton>("Center"),
      _new<AButton>("Right") AUI_LET { it->setExpanding(); },
           // alias to it->setExpanding(2) ^^^^^^
    },
    _new<AButton>("Down"),
  } AUI_WITH_STYLE { MinSize { 300_dp, {} } },
);

Expanding views push remaining views in their container:

Code Result
setContents(
  Vertical {
    _new<AButton>("Up"),
    Horizontal {
        _new<AButton>("Left"),
        _new<AButton>("Center") AUI_LET { it->setExpanding(); },
        _new<AButton>("Right"),
    },
    _new<AButton>("Down"),
  } AUI_WITH_STYLE { MinSize { 300_dp, {} } },
);

Expanding view does affect expanding environment inside a single container. If there's one view with expanding set to any positive value it would occupy all free space in the container. If there is a view with expanding equal to 1 and another view with expanding equal to 2 the first view would occupy one third of free space, the second view would occupy two thirds of free space:

Vertical {
  _new<AButton>("Left") AUI_LET { it->setExpanding(1); },
  _new<AButton>("Right") AUI_LET { it->setExpanding(2); }, // will be twice as big as "Left"
}

You can use ASpacerExpanding as blank expanding view:

Vertical {
  _new<AButton>("Left"),
  SpacerExpanding(),
  _new<AButton>("Right"),
}

Note

FixedSize nullifies Expanding's action (on per axis basic).

Implementation details#

The process of applying position and size involves several key functions:

AWindow::redraw()
└─> AWindow::applyGeometryToChildrenIfNecessary()
    └─> AWindow::applyGeometryToChildren()
        └─> ALayout::onResize()            └─> AViewContainerBase::getMinimumSize()              ┐              │
                └─> AViewContainerBase::getContentMinimumWidth()  │              │
                    └─> ALayout::getMinimumWidth()                │              │
                        └─> AView::getMinimumWidth()              │ cached       │
                └─> AViewContainerBase::getContentMinimumHeight() │              │ potentially
                    └─> ALayout::getMinimumHeight()               │              │ recursive
                        └─> AView::getMinimumHeight()             ┘              │
            └─> AViewContainerBase::setGeometry()                                │
                └─> AViewContainerBase::setSize()                                │
                    └─> AViewContainerBase::applyGeometryToChildrenIfNecessary()                        └─> AViewContainerBase::applyGeometryToChildren()        │
                            └─> ALayout::onResize()                                └─> AView::setGeometry()

Applying size#

Size calculation#

Special cases#

  • AScrollArea: requires special handling for viewport positioning and size compensation
  • AForEachUI: manages view inflation/deflation based on visibility
  • Performance Optimizations: Views outside viewport may be left unupdated to improve performance

Grid layout. Unlike AGridLayout, cells may have different sizes.


Base class for all layout managers.


Places views in a stack (along z axis).


Places views in a row.


Absolute positioning layout. Allows to explicitly set your own coordinates.


Places views in a column.


Grid layout with fixed-size cells.


Imitates behaviour of word wrapping, but uses views instead words