One argument says where a child goes and what its fractions are of

`Place` was a product written as a sum -- a `Part` and a fill flag -- and
`Part` named three operations the geometry already had, under words that did
not match them. `Of` was `UiSpan::within`, `From` was `UiSpan::shift`, and
`Sized` was `placement`'s own body with the length given rather than
reported. Both enums are gone.

`PlaceDescAxis` says one axis, named after the operation it performs:
`within`, `shifted`, `sized`, and `WHOLE`. What is optional is a builder --
`fills` and `rel_base` -- so a caller writes only what it decided, and the
rel base it does not write follows the constructor: a span composed into the
caller's box narrows it, a span along a cursor does not, a decided length is
it. That was the one rule a caller could get wrong with nothing failing.

`PlaceDesc` says both axes with named fields, so `axis`, `axis_mut` and
`from_axis` work the way they do on every other pair here, and the joint
work -- resolving a region, reading the fill flags -- is written once rather
than per axis. `widget_at` and `place_at` take `impl Into<PlaceDesc>`, so a
wrapper passes a `UiRegion` and says nothing else. `widget_within` and
`ActiveData::narrow_rel_base` are deleted; `asked` and `placed` carry the
rel base their ask stated.

Cold layout is byte-identical to `84dad21`.
This commit is contained in:
iris-ai committed 2026-09-19 17:59:26 -04:00
1 parent c55be21761
commit 58ce74dd7d
12 files changed
+367 -271

No files matched your search

+4 -6
View File
@@ -14,7 +14,7 @@ impl Widget for Scroll {
let container_len = painter.px_len(self.axis);
// Asked in the whole viewport, then put at the scrolled offset.
let answer_len = painter
.widget_at(&self.inner, [Place::Fill(Part::WHOLE); 2], None)
.widget_at(&self.inner, PlaceDesc::WHOLE.fills())
.len(self.axis);
let fixed = painter.to_px(Len::from_parts(answer_len.rel, answer_len.px), self.axis);
self.container_len = container_len;
@@ -54,9 +54,9 @@ impl Widget for Scroll {
let content = match moved || self.content_len != self.container_len {
true => {
let start = Len::from_parts(Rel::ZERO, anchor - self.amt);
Part::From(UiSpan::new(start, start.offset(self.content_len)))
PlaceDescAxis::shifted(UiSpan::new(start, start.offset(self.content_len)))
}
false => Part::WHOLE,
false => PlaceDescAxis::WHOLE,
};
// The viewport is the inner's rel base, so a fraction it declares or
// reports is a fraction of what is on screen rather than of the
@@ -64,9 +64,7 @@ impl Widget for Scroll {
// box, scrolled: its drawing moved there, not made again there.
painter.place_at(
&self.inner,
self.axis
.pair(Place::Fill(content), Place::Fill(Part::WHOLE)),
None,
PlaceDesc::from_axis(self.axis, content.fills(), PlaceDescAxis::WHOLE.fills()),
);
// What it occupies is its box, on both axes: it clips its content to
// that box, so it can neither take less of one nor honestly ask for