diff --git a/src/widget/position/pad.rs b/src/widget/position/pad.rs index 82d1ba3..7141a4d 100644 --- a/src/widget/position/pad.rs +++ b/src/widget/position/pad.rs @@ -7,8 +7,14 @@ pub struct Pad { impl Widget for Pad { fn draw(&mut self, painter: &mut Painter) -> Size { + // The inner's own alignment, not the near edge. This reports the + // inner's size plus the padding, so where the box is that answer the + // inset box is exactly the inner and alignment has no room to move + // it; where the box is bigger -- a share of a row, a rule over this + // widget -- the slack is the inner's to sit in, and forcing the near + // edge pinned it to a corner it had not asked for. let inner = painter - .widget_aligned(&self.inner, self.padding.region(), RegionAlign::NEAR) + .widget_within(&self.inner, self.padding.region()) .size(); Size { x: LayoutLen { diff --git a/src/widget/position/stack.rs b/src/widget/position/stack.rs index f4c5ca7..8bc3a1c 100644 --- a/src/widget/position/stack.rs +++ b/src/widget/position/stack.rs @@ -29,7 +29,15 @@ impl Widget for Stack { let region = painter.box_of(size); for (i, child) in self.children.iter().enumerate() { painter.child_layer_at(i); - painter.widget_aligned(child, region, RegionAlign::NEAR); + // The sizing child placed its own content in the box its answer + // decided, and this box was derived from that answer, so applying + // its alignment again here would place it twice. Every other + // child is handed a box that owes nothing to its own answer, and + // where it sits in one bigger than itself is its own business. + match sizing == Some(i) { + true => painter.widget_aligned(child, region, RegionAlign::NEAR), + false => painter.widget_within(child, region), + }; } size } diff --git a/tests/cases/layout.rs b/tests/cases/layout.rs index 5b972cf..43a683c 100644 --- a/tests/cases/layout.rs +++ b/tests/cases/layout.rs @@ -499,3 +499,32 @@ fn leftover_children_disappear_at_the_exact_fixed_content_boundary() { assert!(h.region(&a).is_none()); assert!(h.region(&b).is_none()); } + +/// **A stack child smaller than the stack sits where its own alignment +/// says.** `Stack` gives every child the box its sizing child defines and +/// used to force the near edge on all of them; that override is owed only to +/// the sizing child, which has already placed its own content in the box the +/// stack derived from its answer. Every other child is handed a box that owes +/// nothing to it, so where it sits in one bigger than itself is its own +/// business -- and with the override it could not be aligned at all, which is +/// what moved the `tabs` example's counters to the wrong corner. +#[test] +fn a_stack_child_smaller_than_the_stack_keeps_its_own_alignment() { + let mut h = Harness::new((400, 200)); + let big = rect(Color::BLUE).add(&mut h.rsc); + let small = rect(Color::RED).sized((50, 50)).add(&mut h.rsc); + h.rsc + .widgets_mut() + .set_alignment(small.id(), Axis::X, AxisAlign::POS); + let (a, b) = (big.add_strong(&mut h.rsc), small.add_strong(&mut h.rsc)); + let children: Vec = vec![a, b]; + h.set_root(Stack { + children, + size: StackSize::Default, + }); + + assert_corners!(h, big, (0, 0), (400, 200)); + // The far edge on X because it asked for it, the middle on Y because + // that is the default. + assert_corners!(h, small, (350, 75), (400, 125)); +}