Name the values layout carries, and say what a span's slot is

`along` said nothing about what it did. It is `Span::slot` now: the
stretch of the row between two distances from where the span starts
laying out, as a span of its own box, with the mirror for a negative
direction in one place. `far` is `row`, which is what the comment above
it already called it, and `shares` is `has_room` beside the
`any_leftover` it was folded into. `reached` now guards on the leftover
weight it divides by rather than on the numerator that happened to be
zero with it.

The pairs layout returns are named rather than positional: `Answer`
{size, holds} and `Drawn` {answer, drawing_holds} replace
`(Size, LayoutHolds)` and a three-tuple with two `LayoutHolds` in it,
which was the one shape the cold dump exists to catch. `try_reuse`
answers `bool` rather than `Option<()>`, and the four hand-written
copies of `move_idx != parent_move` are `ActiveData::is_region_node`.

`AXES` was declared in three modules; it is `Axis::BOTH`. `rel_min`,
`rel_max` and the unused `select_len` are gone -- `ZERO` and `FULL`
already said those. Three doc comments sat on `impl` blocks instead of
the single method inside them. `reposition` and `redepth` walked their
children by index, looking the parent up again per child; both take the
list and put it back. `Scroll`'s `fixed` and `fixed_len` are
`answer_px` and `answer_is_px`, which says which one is the length.

fmt, workspace clippy under `-D warnings` with and without
`layout-diagnostics`, and the workspace tests are clean. The cold dump
over 400 depth-5 trees is byte-identical to `6c84b6f`: 34,492 boxes,
no seed moved.
This commit is contained in:
iris-ai committed 2026-09-19 23:24:55 -04:00
1 parent 6c84b6f2cb
commit 3da1c71870
9 files changed
+167 -150

No files matched your search

+24 -25
View File
@@ -10,7 +10,6 @@ use crate::{
},
ui::render_state::{DrawInfo, Placing},
};
const AXES: [Axis; 2] = [Axis::X, Axis::Y];
/// makes your surfaces look pretty
pub struct Painter<'a> {
@@ -155,8 +154,8 @@ impl<'a> Painter<'a> {
/// where that is this widget's own narrowed the way the region is. An
/// axis the region leaves whole is not read at all, so a wrapper that
/// only moves its child does not pin its drawing to a rel base.
fn state_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
for axis in AXES {
fn resolve_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
for axis in Axis::BOTH {
if let Some(span) = place[axis].narrows_rel_base() {
let len = span.len();
let stated = (len != Len::FULL).then(|| len.within_len(self.rel_base(axis)));
@@ -181,7 +180,7 @@ impl<'a> Painter<'a> {
id: &'s StrongWidget<W>,
place: impl Into<PlaceDesc>,
) -> DrawResult<'s, 'a, W> {
let place = self.state_rel_base(place.into());
let place = self.resolve_rel_base(place.into());
let region_node = self.rsc.widgets().is_region_node(id.id());
let declared = self.declared_lens(id);
let align = self.rsc.widgets().alignment(id.id());
@@ -198,7 +197,7 @@ impl<'a> Painter<'a> {
self.children.push(id.id());
}
let px = rel_base.to_px(self.window);
let (size, answer_holds, holds) = self.state.draw_inner(
let drawn = self.state.draw_inner(
id.id(),
DrawInfo {
layer: self.layer,
@@ -217,8 +216,8 @@ impl<'a> Painter<'a> {
None,
self.rsc,
);
let holds = self.in_parent(holds, region, place, declared);
let answer_holds = self.in_parent(answer_holds, region, place, declared);
let holds = self.in_parent(drawn.drawing_holds, region, place, declared);
let answer_holds = self.in_parent(drawn.answer.holds, region, place, declared);
match self.under.iter_mut().find(|(child, _)| *child == id.id()) {
Some((_, kept)) => *kept = holds,
None => self.under.push((id.id(), holds)),
@@ -226,7 +225,7 @@ impl<'a> Painter<'a> {
DrawResult {
child: id,
painter: self,
size,
size: drawn.answer.size,
answer_holds,
}
}
@@ -255,8 +254,8 @@ impl<'a> Painter<'a> {
id: &'s StrongWidget<W>,
place: impl Into<PlaceDesc>,
) -> DrawResult<'s, 'a, W> {
let place = self.state_rel_base(place.into());
let states_rel_base = AXES
let place = self.resolve_rel_base(place.into());
let states_rel_base = Axis::BOTH
.iter()
.any(|&axis| place[axis].stated_rel_base().is_some());
if states_rel_base || !self.children.contains(&id.id()) {
@@ -579,10 +578,10 @@ impl PrimitiveLike for &TextureHandle {
}
}
/// Moves what a child depends on into this widget's own terms: this
/// method's `impl` block is where a `Painter`'s own boxes are, so it takes
/// only what the child was asked with.
impl Painter<'_> {
/// Moves what a child depends on into this widget's own terms, taking
/// only what the child was asked with.
///
/// Window ranges are already about the one unit and combine directly.
/// A rel base pin becomes this widget's own rel base wherever a length of it
/// is what reached the child; where only pixels did, no length of this
@@ -602,7 +601,7 @@ impl Painter<'_> {
declared: Declared,
) -> LayoutHolds {
let mut result = LayoutHolds::ANY;
for axis in AXES {
for axis in Axis::BOTH {
let declared = declared[axis];
let holds = holds[axis];
let result = &mut result[axis];
@@ -677,16 +676,16 @@ impl LayoutLen {
}
}
/// Where a widget's drawing goes inside the part its parent gave it: what
/// it reported, on the side of the part its alignment says, and the whole
/// part wherever the answer fills it.
///
/// The length it reported is a length of its rel base, and the part is one too,
/// so this takes one from the other rather than composing it into the part.
/// That is what makes a fraction the same fraction wherever the part it is
/// placed in sits and however long it is -- the fraction is resolved once,
/// here, against the rel base it was reported of.
impl PlaceDesc {
/// Where a widget's drawing goes inside the part its parent gave it: what
/// it reported, on the side of the part its alignment says, and the whole
/// part wherever the answer fills it.
///
/// The length it reported is a length of its rel base, and the part is one
/// too, so this takes one from the other rather than composing it into the
/// part. That is what makes a fraction the same fraction wherever the part
/// it is placed in sits and however long it is -- the fraction is resolved
/// once, here, against the rel base it was reported of.
pub(crate) fn placement(
self,
region: UiRegion,
@@ -695,7 +694,7 @@ impl PlaceDesc {
align: RegionAlign,
) -> UiRegion {
let mut placed = region;
for axis in AXES {
for axis in Axis::BOTH {
let reported = size[axis];
if reported.fills(declared[axis], self[axis].does_fill()) {
continue;
@@ -725,7 +724,7 @@ impl PlaceDesc {
let given = self.of(own, align);
let mut rel_base = parent_rel_base;
let mut region = given;
for axis in AXES {
for axis in Axis::BOTH {
let base = self[axis]
.stated_rel_base()
.unwrap_or_else(|| parent_rel_base[axis]);