diff --git a/src/widget/position/span.rs b/src/widget/position/span.rs index e96a919..dd1f2a6 100644 --- a/src/widget/position/span.rs +++ b/src/widget/position/span.rs @@ -60,10 +60,14 @@ impl Widget for Span { start.px += self.gap; } - let along = match total.rest == 0.0 && total.rel == 0.0 { - true => total, - false => Len::default(), - }; + // Carried whole rather than collapsed to one share: a span that sizes + // from its children does not resolve `rest`, it passes the weight up, + // so nesting spans divides the same space rather than re-dividing a + // share of it. Four `rest(1)` children under two spans under one span + // get a quarter each, which collapsing to `rest(1)` per level does + // not give. Resolution happens at the nearest ancestor with a length, + // and the root always has one. + let along = total; Size::from_axis(axis, along, ortho) } diff --git a/tests/layout.rs b/tests/layout.rs index 6e88906..008c735 100644 --- a/tests/layout.rs +++ b/tests/layout.rs @@ -186,3 +186,46 @@ fn only_a_container_that_places_its_children_lengthens_the_chain() { "the span above the leaf, and the root the window is held in" ); } + +/// A span that sizes from its children passes their `rest` weight up rather +/// than collapsing it to one share, so nesting divides the same space instead +/// of re-dividing a share of it. +#[test] +fn nested_spans_divide_the_space_once_however_deep_the_nesting_is() { + let mut h = Harness::new((400, 200)); + let (a, b, c, d) = ( + rect(Color::RED).add(&mut h.rsc), + rect(Color::BLUE).add(&mut h.rsc), + rect(Color::GREEN).add(&mut h.rsc), + rect(Color::WHITE).add(&mut h.rsc), + ); + let left = (a, b).span(Dir::RIGHT).add(&mut h.rsc); + let right = (c, d).span(Dir::RIGHT).add(&mut h.rsc); + h.set_root((left, right).span(Dir::RIGHT)); + + for (i, id) in [a, b, c, d].into_iter().enumerate() { + let x = i as f32 * 100.0; + assert_corners!(h, id, (x, 0), (x + 100.0, 200)); + } +} + +/// The same space, unevenly nested: weights carried up mean a share is a +/// share of the whole, not of whatever branch a widget happens to sit in. +#[test] +fn an_uneven_nesting_still_gives_every_share_the_same_length() { + let mut h = Harness::new((400, 200)); + let (a, b, c, d) = ( + rect(Color::RED).add(&mut h.rsc), + rect(Color::BLUE).add(&mut h.rsc), + rect(Color::GREEN).add(&mut h.rsc), + rect(Color::WHITE).add(&mut h.rsc), + ); + let one = (a,).span(Dir::RIGHT).add(&mut h.rsc); + let three = (b, c, d).span(Dir::RIGHT).add(&mut h.rsc); + h.set_root((one, three).span(Dir::RIGHT)); + + for (i, id) in [a, b, c, d].into_iter().enumerate() { + let x = i as f32 * 100.0; + assert_corners!(h, id, (x, 0), (x + 100.0, 200)); + } +}