AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
Layout Managers

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

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 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

Common layout managers include:

Key concepts:

  1. Minimum Size - Layout managers calculate minimum size requirements by:
    • Considering minimum sizes of child views
    • Adding margins and spacing
    • Respecting fixed size constraints
  2. Expanding Views - Children can expand to fill available space of their parent:
  3. Spacing - Configurable gaps between views:
  4. Margins - Space around individual views:
    • Set per-view via ASS or margins property
    • Respected during layout
    • Part of minimum size calculations of the parent view
  5. Layout Direction - Overall flow direction:
    • Horizontal layouts flow left-to-right
    • Vertical layouts flow top-to-bottom
    • Grid layouts use both directions
  6. Relativeness - children position is relative to parent's position, not an absolute position within a window.
  7. 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"),
  }
);

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.

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") let { it->setExpanding(); },
           // alias to it->setExpanding(2) ^^^^^^
    },
    _new<AButton>("Down"),
  } with_style { MinSize { 300_dp, {} } },
);
#define let
Performs multiple operations on a single object without repeating its name (in place) This function c...
Definition kAUI.h:262
#define with_style
Allows to define a style to the view right in place.
Definition kAUI.h:287

Expanding views push remaining views in their container:

Code Result
setContents(
  Vertical {
    _new<AButton>("Up"),
    Horizontal {
        _new<AButton>("Left"),
        _new<AButton>("Center") let { it->setExpanding(); },
        _new<AButton>("Right"),
    },
    _new<AButton>("Down"),
  } 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") let { it->setExpanding(1); },
  _new<AButton>("Right") 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()
Base class for all layout managers.
Definition ALayout.h:308
A view that represents a set of views.
Definition AViewContainerBase.h:68
Base class of all UI objects.
Definition AView.h:78
Represents a window in the underlying windowing system.
Definition AWindow.h:45

Applying size#

Size calculation#

  • Layout manager queries Minimum size which is determined with AView::getMinimumSize and cached until the view or its children call AView::markMinContentSizeInvalid. It considers:
  • After minimum sizes of children are calculated, layout manager queries their expanding ratios, and gives such views a share of free space if available. Unlike minimum size, Expanding ratio does not depend on children's Expanding ratios.

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

Classes#

class  AAbsoluteLayout
 Absolute positioning layout. Allows to explicitly set your own coordinates. More...
 
class  AAdvancedGridLayout
 Grid layout. Unlike AGridLayout, cells may have different sizes. More...
 
class  AGridLayout
 Grid layout with fixed-size cells. More...
 
class  AHorizontalLayout
 Places views in a row. More...
 
class  ALayout
 Base class for all layout managers. More...
 
class  AStackedLayout
 Places views in a stack (along z axis). More...
 
class  AVerticalLayout
 Places views in a column. More...
 
class  AWordWrappingLayout
 Imitates behaviour of word wrapping, but uses views instead words. More...