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
@@ -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