Standard UI Layout
Introduction
UI elements in a window are arranged in a hierarchy (a rooted tree). Each element is responsible for the positioning and sizing of its child elements.
By default elements use the standard UI layout algorithm, which is implemented by the system. If an element has the PBElement_CUSTOM_LAYOUT flag, then it will be sent various messages allowing to implement a custom layout algorithm.
For example, window elements (the roots of their respective hierarchies) have a custom algorithm that positions the first child element to match the size of the window, excluding the space taken by decorations like the titlebar.
This document describes the standard layout algorithm.
Properties Affecting Layout
Each element has a set of flags (see PBElementFlags) and some layout metrics (see PBLayoutMetrics).
Some of these properties affect how the element lays out its children. For example, the PBElement_LAYOUT_HORIZONTAL flag instructs an element using the standard layout algorithm to lay out its children in a horizontal row.
Some of these properties affect the layout of the element's parent. For example, the PBElement_ALIGN_RIGHT flag instructs the parent element to align this specific child on the right side.
The algorithm obtains the preferred size of each child element using the PBElementMeasure function. See its documentation for details.
Columns
By default, the algorithm lays out the child elements in a column, one after another from top to bottom. The algorithm determines the height of each element with PBElementMeasure, and accumulates these values to obtain the y-offset of each successive child. The algorithm obtains the width of each element with PBElementMeasure, and then horizontally centers each element within its bounds.

If a child element has the PBElement_ALIGN_LEFT flag, then that element will be left aligned instead of centered. If a child element has the PBElement_ALIGN_RIGHT flag, then that element will be right aligned instead of centered. If a child element has both these flags specified, then its preferred width (from PBElementMeasure) is ignored and it is resized to precisely match the width of the parent, even if this means truncating the contents of the child.

PBElement_H_FILL is an alias for PBElement_ALIGN_LEFT|PBElement_ALIGN_RIGHT. Note that this mode only causes the child element to take up the exact width of its container. It does not force the container take up the full width of its container; you may need to also set this flag on the container and some of its ancestors to get the desired layout.
Each child element can have different alignment flags.
Setting the PBElement_ALIGN_TOP or PBElement_ALIGN_BOTTOM flags on the child elements has no effect.
Rows
When the PBElement_LAYOUT_HORIZONTAL flag is set on an element, the standard layout algorithm will instead lay out the child elements in a horizontal row, one after another going left to right.
Here, setting the the PBElement_ALIGN_TOP or PBElement_ALIGN_BOTTOM flags on the child elements will change their respective alignments. The PBElement_ALIGN_LEFT and PBElement_ALIGN_RIGHT flags will have no effect.

PBElement_V_FILL is an alias for PBElement_ALIGN_TOP|PBElement_ALIGN_BOTTOM.
For a vertical column, the primary axis is the vertical axis. For a horizontal row, the primary axis is the horizontal axis.
Insets and Gaps
The insets of an element give the amount of space between its borders and where the child elements should be placed. There is a measurement in dps for each side: left, right, top and bottom.
The gap gives the amount of space in dps left between each child element on the primary axis.

If the size of the container element has already been determined, then the following apply:
- for columns, if all child elements are horizontally centered, then the left and right insets are not used;
- for rows, if all child elements are vertically centered, then the top and bottom insets are not used;
- for columns, if no child element has a primary axis fill, then the bottom inset is not used;
- for rows, if no child element has a primary axis fill, then the right inset is not used.
Primary Axis Fills
After positioning its children, an element using the standard layout algorithm will then calculate the amount of remaining space on its primary axis. It then evenly distributes this space between all its child elements that have the corresponding fill flag for the primary axis.

Setting the primary axis fill flag on a child does not cause the parent to also fill the remaining space of its parent. If setting this flag on an element has no effect, that likely means the parent's size on the primary axis is set to perfectly match the size needed for its child elements. Thus, there will be no leftover space.
Reverse Layout
Setting the PBElement_LAYOUT_REVERSE flag on an element causes it to reverse its layout. That is, for a column, the elements are placed from right to left instead of left to right, and for a row, the elements are placed from bottom to top instead of top to bottom.
Porting from Flexbox
The standard layout algorithm is simpler than CSS "flexbox" to make it easy to construct the most common layouts in GUI applications. However, many of the features of "flexbox" have some equivalent.
flex-direction: row: Set thePBElement_LAYOUT_HORIZONTALflag on the container.flex-direction: column: The default.flex-direction: row-reverse: SetPBElement_LAYOUT_HORIZONTAL|PBElement_LAYOUT_REVERSEon the container and add a child element at the end with the flagPBElement_FILL.flex-direction: column-reverse: SetPBElement_LAYOUT_REVERSEon the container and add a child element at the end with the flagPBElement_FILL.flex-wrap: nowrap: The default.flex-wrap: wrap: No equivalent. UsePBWrapPanelinstead.flex-wrap: wrap-reverse: No equivalent. UsePBWrapPanelinstead.justify-content: flex-start: The default.justify-content: flex-end: Add a child element at the start with the flagPBElement_FILL.justify-content: center: Add a child element at the start with the flagPBElement_FILLand similarly another at the end.justify-content: space-between: Add a child element between each pair of children with the flagPBElement_FILL.justify-content: space-around: No direct equivalent.justify-content: space-evenly: Add a child element between each pair of children with the flagPBElement_FILLand similarly one at the start and one at the end.align-items: flex-start: No direct equivalent. But seealign-self: flex-start.align-items: flex-end: No direct equivalent. But seealign-self: flex-end.align-items: center: No direct equivalent. But seealign-self: flex-center.align-items: stretch: No direct equivalent. But seealign-self: flex-stretch.align-items: baseline: No equivalent. The standard layout algorithm is not designed for complex text layout.gap: <N>px: Set thegapvalue in the container'sPBLayoutMetricsstructure.padding: ...: Set theinsetsvalue in the container'sPBLayoutMetricsstructure.order: <N>: No direct equivalent. UsePBElementChangeOrderingto manually get the desired order.flex-grow: <N>: No direct equivalent. But see the "Primary Axis Fills" section for a discussion on how an element can fill up the remaining space of a container.flex-shrink: <N>: No direct equivalent. But see the "Primary Axis Fills" section.flex-basis: <N>px: Set the fixed width or height in the child'sPBLayoutMetricsstructure.flex-basis: auto: The default.align-self: flex-start: Set thePBElement_ALIGN_LEFT(for a column) orPBElement_ALIGN_TOP(for a row) flag on the child.align-self: flex-end: Set thePBElement_ALIGN_RIGHT(for a column) orPBElement_ALIGN_BOTTOM(for a row) flag on the child.align-self: center: The default.align-self: stretch: Set thePBElement_H_FILL(for a column) orPBElement_V_FILL(for a row) flags on the child.align-self: baseline: No equivalent. The standard layout algorithm is not designed for complex text layout.