Layout & containers
Two-phase layout
Every widget participates in the same two-phase pass: measure asks each widget how tall it wants to be for a given width, then arrange hands each a final rectangle. Containers implement layout by measuring their children and placing them; leaves just report a size and draw. Because layout is deterministic and top-down, there is no constraint solver to reason about — a container's rule is plain code.
The containers
Column— stacks children vertically with padding and spacing; the default panel container.Row— lays children horizontally, withflexweights distributing leftover width.Grid— row-major, N equal columns, uniform row height.Field— a labelled control row (label on the left, control filling the rest) — the inspector idiom.Spacer— fixed empty space.
auto form = column(
field("Name", textField("ball")),
field("Radius", numberField(1.5f)),
row(flex(button("Cancel"), 1), flex(button("Apply"), 2))); // 1:2 width split
flex(child, weight) marks a row child as stretchy; fixed children take their measured width and the remainder is split by weight. Nesting columns and rows builds any form layout without absolute coordinates.
Scrolling, sections, tabs
Three containers handle overflow and grouping:
ScrollViewwraps a taller child, clips and scrolls it (wheel or thumb-drag), and shows a gutter only when the content overflows. It bubbles an unconsumed wheel up the ancestor chain and re-measures each frame, so content that grows is scrollable without an explicit invalidation call.CollapsiblePanelis a titled disclosure section — collapsed, it is just its header and its content takes no space or events.TabWidgetis a tab strip over a content stack; only the active page is laid out (inactive pages take zero space).
Working in points
All layout is in logical points, with the DPI scale folded in by the canvas. A single uiScale factor scales every metric and font size together (the way a desktop "UI scale" setting does), and text stays crisp because the FontBook rasterizes at the target size rather than scaling a bitmap. The result: the same layout code produces a pixel-perfect interface at any density or scale.
For arranging whole panels — resizable, tabbable, tear-off regions — rather than widgets within a panel, see docking.