Move the settled layout vocabulary into LAYOUT.md and prune the handoff
The handoff had grown a chronicle of what each commit renamed. What is durable about it -- the three names, and the one argument a container uses to say them -- is design, so it goes to `docs/LAYOUT.md` as its own section and the handoff keeps a pointer plus where the branch stands. `docs/PLAN.md`'s "frame/extent experiment" entry described a prototype in retired words; it becomes a pointer, and the one finding it held that was not recorded elsewhere -- why the extent-relative child-frame trial was removed -- joins the failed hypotheses in `docs/LAYOUT.md`.
This commit is contained in:
1 parent
265ce6f829
commit
61a2f601bb
4 files changed
+113
-98
No files matched your search
+60
-4
@@ -8,9 +8,9 @@ without reading that result does not make the parent's size depend on it.
|
||||
carries those commits whole plus the retained-layout repair built on them. §4 to §6 and the density section
|
||||
retain the rationale of the design but still name types that have since been
|
||||
replaced; they are not an API reference. `docs/HANDOFF.md` is where the work
|
||||
in flight stands. The sections from "Rel bases, decided boxes and padding"
|
||||
onwards are the settled design, the findings that outlived the working log,
|
||||
and the measurement method.
|
||||
in flight stands. The sections from "Three names, and the one argument that
|
||||
says them" onwards are the settled design, the findings that outlived the
|
||||
working log, and the measurement method.
|
||||
|
||||
## Design
|
||||
|
||||
@@ -319,6 +319,56 @@ fragment stage cannot make. Rendering and hit-testing both traverse the full
|
||||
mask chain and use the same rounded-rectangle coverage; `iris/tests/mask_sdf.rs`
|
||||
checks the WGSL implementation against the CPU SDF.
|
||||
|
||||
## Three names, and the one argument that says them
|
||||
|
||||
Settled with Bryan on 2026-09-17 and 2026-09-19. Layout has exactly three
|
||||
things, and only two of them are boxes:
|
||||
|
||||
- **region** — the box a parent asks a widget in. It draws there, and a text
|
||||
wraps at it. `ActiveData::region`, `Painter::region`.
|
||||
- **placement** — the box its drawing ends up in: a box the size it reported,
|
||||
positioned inside the region by its own alignment, and equal to the region
|
||||
wherever it fills one. It is computed after `draw` returns, is not on
|
||||
`Painter`, and no widget mentions it. `ActiveData::placement` is what
|
||||
`window_region` resolves for hit testing.
|
||||
- **rel_base** — not a box. The length a fraction the widget declares or
|
||||
reports is a fraction of, per axis, as a length of the window. It is the
|
||||
one value that never changes coordinate space: a region node re-expresses
|
||||
the region locally and takes the rel base untouched.
|
||||
|
||||
`frame` and `extent` are retired and must not come back in this sense; the
|
||||
word "frame" for one rendered frame is unaffected.
|
||||
|
||||
A container says all three in one argument. `Painter::widget_at(id, place)`
|
||||
and `place_at(id, place)` take `impl Into<PlaceDesc>`, so a wrapper that only
|
||||
hands over a box passes a `UiRegion` and says nothing else — which is all
|
||||
`Pad`, `Offset` and `Painter::widget` do.
|
||||
|
||||
`PlaceDescAxis` is one axis, and its three constructors are named after the
|
||||
operations the geometry already had, because two of them take the same span
|
||||
and differ only in how it is applied:
|
||||
|
||||
- `within(span)` — `UiSpan::within`: composed into the caller's box, so it
|
||||
moves and scales with it. What an inset speaks.
|
||||
- `shifted(span)` — `UiSpan::shift`: window lengths from where the caller's
|
||||
box starts. What a container dividing room speaks, and what makes a moved
|
||||
box re-place every child by addition, exactly. Not directional: `Dir::Neg`
|
||||
is handled by the span before the numbers get here.
|
||||
- `sized(len)` — the body of `placement` with the length given from above
|
||||
rather than reported. What a stack's sizing child decides for the rest.
|
||||
|
||||
What is optional is a builder, so a caller writes only what it decided:
|
||||
`.fills()` says the region is the placement, and `.rel_base(len)` names the
|
||||
child's rel base outright. **The rel base a caller does not name follows the
|
||||
constructor** — `within` narrows it the way the box is narrowed, `shifted`
|
||||
passes it through, `sized` is it. That rule is what makes the common case
|
||||
right by default; stating it by hand was the one thing a container could get
|
||||
wrong with nothing failing.
|
||||
|
||||
`PlaceDesc` is the pair, with `x` and `y` fields and the `axis`, `axis_mut`
|
||||
and `from_axis` of every other pair here, so the joint work — resolving a
|
||||
region, reading the fill flags — is written once rather than per axis.
|
||||
|
||||
## Rel bases, decided boxes and padding
|
||||
|
||||
Containers that only divide room are transparent to fractions. A child rel base
|
||||
@@ -381,7 +431,7 @@ composes a rel base back up a chain.
|
||||
|
||||
A rel base decided for a child is therefore a length of the window too: a row's
|
||||
slot, padding's rel base less its pixels, or the box a stack's sizing child
|
||||
decided (which arrives as `Part::Sized`). It is never a fraction of the
|
||||
decided (which arrives as `PlaceDescAxis::sized`). It is never a fraction of the
|
||||
parent's rel base, because a slot of a row is not a fraction of anything the row
|
||||
can name -- a division of two lengths, which a `rel + px` length cannot hold.
|
||||
A widget's own declaration *is* a fraction, of whichever of those reached it,
|
||||
@@ -587,6 +637,12 @@ must still agree exactly.
|
||||
- **Resolving a rule that is a fraction of the rel base from the record instead
|
||||
of redrawing** recovers nothing: `reuse outside: a rel base` is 3 of
|
||||
264 cold draws at seed 1 and 1 of 758 at seed 13.
|
||||
- **A child rel base expressed as a fraction of the parent's region** (the
|
||||
"extent-relative child frame" trial, 2026-09-17) was removed. The
|
||||
size/resize cost it was aimed at came from conflating answer and drawing
|
||||
dependencies, not from `Pad` and `Stack` reading their raw placement
|
||||
conservatively. A decided rel base is a length of the window, not a
|
||||
fraction of anything the parent can name.
|
||||
- **A `git bisect`** once named a commit that could not be the cause; read
|
||||
the tree rather than the bisect when that happens.
|
||||
|
||||
|
||||
Reference in new issue
Block a user