Skip to main content

Module layout

Module layout 

Source
Expand description

The flex solver: clay-style layout over the flat tree, run by compute once per frame.

Each node declares a Sizing per axis (Fit, Grow, Fixed, Percent or a size expression), optional clamps, a direction, padding, gap and alignment; see LayoutSpec. The solver resolves them in five passes over the preorder tree:

  1. fit widths (reverse: children before parents)
  2. grow widths (forward: parents before children)
  3. fit heights (reverse; text wraps at its final width here)
  4. grow heights (forward)
  5. positions (forward)

A wrapping row breaks its children into lines in pass 2 and every later pass reads that grouping, which is why wrapping is rows-only: a row’s width is final before its height is measured, where a column would need its height first. A sixth pass runs only on a frame with a float anchored to a node by key (FloatAnchor::Node), since such a float’s anchor may come later in preorder; its subtree is laid out again from the anchor’s final rect.

A table (LayoutSpec::table) is a column whose rows’ cells line up: pass 1 reaches the table after its rows and cells and sets every fit cell to its column’s widest and every row to the columns’ width, so the table’s own fit width is the aligned columns; pass 2 reaches it before its rows, resolves the columns against the widest row once and writes each column’s width into its cells, and a row of a table then leaves its children alone. A column, a table or a leaf straight under the table has no cells.

Text measurement goes through TextMeasure, so the solver is testable with a deterministic stub and never depends on system fonts.

Traits§

TextMeasure
What the solver asks about text, editors, images and cell grids: the sizes it cannot compute from specs alone. The core implements it over its text system; a test may implement it with fixed numbers.

Functions§

compute
Lays tree out into viewport logical px: sizes and positions every node, breaks wrapping rows into lines, resolves tables and floats, and clamps the scroll offsets in scroll. Core::finish_frame calls it once per frame; it is public for a custom runner or a test that drives the solver directly.