Record the root unification, and where bounds stand
`0d03267` in iris unifies the root's layout path with every other widget's:
`Placing::WINDOW` is the box nobody drew and `Placing::ask` the one place a
box is decided. The leftover-as-a-minimum gap the log recorded for
`root_layout` is closed by it rather than left.
`SizeRule::{Min, Max, Clamp}` is on `layout/bounds` and not in #19. Every
hand-written test passes and the 400-seed scan does not, for a reason that is
a design question: a bound is the first rule whose effect depends on the box
its parent gives it, and the retained machinery hands a widget a box by paths
that never ask it again. The log records the four readings measured and what
each one's seeds were, so none of them is tried twice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6a92857079
commit
149a6838af
2 files changed
+91
-15
No files matched your search
+27
-15
@@ -55,6 +55,12 @@ and past the reviewed `cadfba0` it is twelve rounds, each described in
|
||||
overflow its pixels asked for, said as the place the parent gives and
|
||||
sharing one comparison with the span; and `Image` grown in the generated
|
||||
trees, which is the only widget here whose hint is a length in pixels.
|
||||
- **One ask, the root's included**, `0d03267` -- the root had a layout path
|
||||
of its own, so a rule that reads the box it is offered reached every widget
|
||||
but that one. `Placing::WINDOW` is the box nobody drew and `Placing::ask`
|
||||
the one place a box is decided; the root's own path is now the bookkeeping
|
||||
a widget with no parent keeps. Bryan asked for this rather than a widget
|
||||
above the root, which would pin the tree to pixels.
|
||||
|
||||
The settled design of the vocabulary rounds is in `docs/LAYOUT.md` under
|
||||
"Three names, and the one argument that says them". Bryan settled the API
|
||||
@@ -110,14 +116,15 @@ the name it is reachable by.
|
||||
|
||||
**Always**, because they cost nothing: format, workspace clippy under
|
||||
`-D warnings` with and without `layout-diagnostics`, the workspace tests, and
|
||||
the **cold dump**. `layout_dump` over 400 depth-5 trees is **34,488** boxes
|
||||
-- **34,571 since `2dba90b` grew images in the trees**; counted again on
|
||||
2026-09-20, the fourth through eighth sweeps having all repeated 34,492, which
|
||||
is a `wc -l` of the whole run rather than of its box lines -- and it is the only thing that catches two same-typed values being
|
||||
swapped, which is the failure mode of a rename or a move. Count the lines
|
||||
that are a box (`grep -cE '^[0-9]+ [0-9]+ '`), not the output. The repair moved 650 of those
|
||||
boxes, all from the collapsed-share correction; every commit since has been
|
||||
byte-identical to `84dad21`.
|
||||
the **cold dump**. `layout_dump` over 400 depth-5 trees is **34,571** boxes
|
||||
since `2dba90b` grew images in the trees, and `0d03267` left every one of them
|
||||
byte-identical. It was 34,488 before the images; the fourth through eighth
|
||||
sweeps all repeated 34,492, which is a `wc -l` of the whole run rather than of
|
||||
its box lines, so count the lines that are a box
|
||||
(`grep -cE '^[0-9]+ [0-9]+ '`). It is the only thing that catches two
|
||||
same-typed values being swapped, which is the failure mode of a rename or a
|
||||
move. The repair moved 650 of those boxes, all from the collapsed-share
|
||||
correction; every commit since has been byte-identical to `84dad21`.
|
||||
|
||||
**Only when the change can alter what layout computes**: the three seed scans
|
||||
-- 400 at depth 5, 1,000 at depth 6, 2,000 at depth 4. They cost about a
|
||||
@@ -185,19 +192,24 @@ glyphs do not follow a shortened entry.
|
||||
- A `leftover` under a parent that does not divide is a minimum size --
|
||||
`max(box, px + rel*box)` (Bryan, 2026-09-20), which is a `SizeRule::Min` of
|
||||
`rel(1.0)` and shares `Painter::longer_than` with the span. Done in
|
||||
`b295c8b` for a widget its parent asks; `root_layout` still reads the old
|
||||
way, for which see `docs/LAYOUT_LOG.md`.
|
||||
`b295c8b`, and in `0d03267` for the root as well, which used to read it the
|
||||
old way.
|
||||
- `Fixed::div` by zero answers `MIN`/`MAX` while `ratio` answers `ZERO`; both
|
||||
are caller bugs under `debug_assert`, but the fallbacks differ.
|
||||
- `docs/LAYOUT.md` §4, §5 and the density section name `Painter::place`,
|
||||
`Painter::region()`, `SetSize`, `desired_width`, `apply_rest`, `Len::dp`,
|
||||
`Aligned` and `MaxSize`, none of which exist. Do not restore
|
||||
`OnResize::Translate` or `OrthoSize`.
|
||||
- `LazySpan`, then `SizeRule::{Min, Max, Clamp}`. A cap may not contain
|
||||
`leftover`; whether `Max` narrows the child's drawing box is a product
|
||||
decision. `Min` is `Painter::longer_than` again -- a `leftover` where
|
||||
nothing divides it is already a `Min` of `rel(1.0)` -- so it belongs on
|
||||
that path rather than beside it.
|
||||
- `SizeRule::{Min, Max, Clamp}` is written and pushed as `layout/bounds`
|
||||
(`76aaf06`), and **is not ready to land**: every hand-written test passes,
|
||||
including a capped scroll taking its viewport from the cap, but the
|
||||
400-seed scan does not, and the reason is a design question Bryan has to
|
||||
settle -- see `docs/LAYOUT_LOG.md` under "Bounds are a rule that reads its
|
||||
box". Bryan settled two things already: `Max` narrows the child's drawing
|
||||
box (2026-09-20), and a rule gives a length or bounds one but never both,
|
||||
since a capped share is said with two widgets. A cap may not contain
|
||||
`leftover`.
|
||||
- `LazySpan`.
|
||||
- `Scroll` taking a direction rather than one axis.
|
||||
|
||||
Other product work is in `docs/PLAN.md` and the focused documents it links.
|
||||
|
||||
@@ -6,6 +6,70 @@ nothing here is rediscovered. Each entry says who found it and when.
|
||||
it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and
|
||||
the current plan is in `docs/HANDOFF.md`.
|
||||
|
||||
## One ask, the root's included (2026-09-20)
|
||||
|
||||
`0d03267`. `root_layout` read the root's declared lengths against the window
|
||||
while every other widget's box came of `Painter::widget_at`, where a rule of
|
||||
the widget's own can take the box past what its parent offered. Bryan asked
|
||||
for the two paths unified, and ruled out doing it by putting a widget above
|
||||
the root: a root sized in pixels would make every fraction under it a fraction
|
||||
of a px length, which pins the whole tree to those pixels and re-asks it on
|
||||
every resize.
|
||||
|
||||
`Placing::WINDOW` is the unification -- the full output, fractions of the full
|
||||
output, no move entry and no mask -- and `Placing::ask` is the one place a box
|
||||
is decided, called by the painter, by a local redraw, and by the root's first
|
||||
draw. What is left of the root's own path is the bookkeeping a widget with no
|
||||
parent keeps.
|
||||
|
||||
Two things fell out. `DrawInfo::asked` is now the place the parent offered
|
||||
rather than the place the ask came to, so a local redraw re-decides a rule
|
||||
instead of re-reading its decision; the two were the same until a rule could
|
||||
move the box. And the root's `is_region_node` is read, where the old path
|
||||
passed `false`.
|
||||
|
||||
The comparison a rule makes is kept on the widget asked about rather than on
|
||||
the asker. A window range means the same thing at either end of an ask and
|
||||
`in_parent` passes one up unchanged, so the asker still ends up holding it
|
||||
through the child's drawing -- and the root, which has no asker, needs nothing
|
||||
of its own, since `resize` already checks its record.
|
||||
|
||||
## Bounds are a rule that reads its box, and the oracle refuses one (2026-09-20)
|
||||
|
||||
On the branch `layout/bounds` (`76aaf06`), not in #19. `SizeRule::{Min, Max,
|
||||
Clamp}` is the capability `MaxSize` had on the app's pin and nothing on this
|
||||
branch has. Every hand-written test passes, including a capped scroll taking
|
||||
its viewport from the cap; the 400-seed depth-5 scan does not.
|
||||
|
||||
The finding is general and worth keeping whatever is decided. A bound is the
|
||||
first rule whose effect depends on the box its parent gives it, and the
|
||||
retained machinery hands a widget a box by paths that never ask it again
|
||||
(`place_in` from a re-placing parent, `reposition` after a parent's box moved).
|
||||
A decision made when the box was one length survives into a box of another, so
|
||||
warm and cold disagree about a tree they agree on structurally. Four readings
|
||||
measured over 400 seeds at depth 5:
|
||||
|
||||
- decided at every ask and kept: seeds 291, 1, 120, 178, 64 differ.
|
||||
- re-decided at `place_in` as well: seeds 1, 362, 188, 254, 156, because that
|
||||
path's box is the one the answer chose, not the one the widget was asked in.
|
||||
- skipping a place the parent decided outright, which is the rule the share
|
||||
follows: worse, since the same widget then gets two decisions by two paths.
|
||||
- the bound as an answer rule only, leaving the box alone: seeds 4 and 196 --
|
||||
much the closest.
|
||||
|
||||
The share is the one existing rule of this kind, and it is stable for two
|
||||
reasons that do not generalise: `place_at` re-asks a child whose rel base it
|
||||
narrows, and a share that binds is baked into the retained place as a `Sized`
|
||||
length. A bound that binds is a length of the rel base, and `Sized` cannot say
|
||||
"this slot, narrowed" for a `Within` place.
|
||||
|
||||
Neutering the bounds in the generator while leaving its random draws in place
|
||||
puts the same shapes back to green, so the divergence is the bounds and not
|
||||
the new trees. Two findings from the branch are worth having whatever happens
|
||||
to it: a rule that is a fraction must pin its rel base, which `Exact` was
|
||||
already missing for bounds-shaped reasons; and `widget_trait!` dropped
|
||||
attributes, so no method it defines could carry a doc comment.
|
||||
|
||||
## Images in the generated trees (2026-09-20)
|
||||
|
||||
`Image` is the only widget here whose size hint is a length in pixels, so it is
|
||||
|
||||
Reference in new issue
Block a user