Repository navigation
Conversation
a flow is a frame laid out along x whose items wrap: one that would pass the right edge of a row already holding an item starts the next row a row gap below. a row is as tall as its tallest item and its items size and align across against the height it measured last frame. an item wider than a whole row takes it alone at the row's width. the natural width is the items in one row, so a flow fitted to its content with a largest size wraps there.
widget.flow gives the options at the layout style's gaps, margin.r between items and margin.b between rows. a flow is sized in its parent as a stack is and shares its open and close path. each row's natural height is kept in the state store under the flow's id and the row's index, so items align in rows whose height comes from later items. a flow that is not start-aligned, or that its parent aligns by its size, spends its first frame measuring.
octalide
force-pushed
the
feat/203
branch
2 times, most recently
from
October 1, 2026 20:01
fb69de1 to
302c70b
Compare
octalide
marked this pull request as ready for review
October 1, 2026 20:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #203
Plan
blit.layout: aFlowoptions record besideStack(align,gap,row_gap, the flow's ownw/h,item_w/item_h) andlayout.flow(gap, row_gap).layout.rows(...)builds a flow frame.resolveplaces an item at the pen. When the width is known, the row already holds an item, and the item would pass the right edge (1/64 px slack), it wraps to the next row one row gap below the row's bottom. An item wider than a whole row is clamped to the row width, so it takes the row alone and the widget cuts its own label (fit_box,fit_pair). Across, items size and align (start,center,end,stretch) against their row's height.committracks rows. A row's height is its tallest item,need_hstacks the rows, andneed_wis the one-row natural width.blit.widget:flow(ctx)gives the options at the style system's gaps: thelayoutstyle'smargin.rbetween items,margin.bbetween rows.begin_flow/end_flowopen a flow as the next item of the current frame, sized in its parent exactly asbegin_stackis. Both share one open and close path (enter,leave). Each row's natural height goes in the state store under an id derived from the flow's id and the row index, so items align in a row whose height depends on later items. It settles one frame late, like stacks. A flow that is not start-aligned, or that its parent aligns by its size, spends its first frame measuring, as stacks do.fit_pair.Decisions the issue left open:
limit(fit(), 0, max)) wraps atmaxand is as narrow as its items when they fit in less. That is how a flow inside an overlay (which fits its content) gets a wrap width. An open width with no max never wraps.same_linedoes.layout.Alignin the options, asStack.aligndoes. The style system has no alignment field, so the gaps come from the style and alignment from the options.cellar's readout becomes:
size_next(limit(fit(), 0, max)),begin_flow(ui, "readout", flow(ui)), then oneplaceand onefit_pairper pair, thenend_flow.Ran:
mach test . --filterforlayout__,flow__,space__,dock__,overlay__andwindow__, the gallery test (golden unchanged), andmach fmt --checkon the root anddemo/gallery.