diff --git a/src/widget/position/scroll.rs b/src/widget/position/scroll.rs index 6dba289..8458896 100644 --- a/src/widget/position/scroll.rs +++ b/src/widget/position/scroll.rs @@ -17,9 +17,9 @@ impl Widget for Scroll { let answer_len = painter .widget_at(&self.inner, whole, [Place::Fill(Part::All); 2]) .len(self.axis); - let content = answer_len.apply_leftover(); + let fixed = Len::from_parts(answer_len.rel, answer_len.px).to_px(container_len); self.container_len = container_len; - self.content_len = content.to_px(container_len); + self.content_len = fixed.max(container_len); if self.snap_end { self.amt = self.content_len - self.container_len; @@ -32,9 +32,9 @@ impl Widget for Scroll { // the drawing holds for that length alone. One scrolled part way sits // where it is until the box shrinks past what is left of it. Kept to // the end, it moves with every length. - let fixed_len = content.rel == Rel::ZERO; + let fixed_len = answer_len.rel == Rel::ZERO && answer_len.leftover == Weight::ZERO; if fixed_len && self.content_len <= self.container_len && align == AxisAlign::NEG { - painter.holds(self.axis, self.content_len..=Px::MAX); + painter.holds(self.axis, fixed..=Px::MAX); } else if fixed_len && !self.snap_end { let left = self.content_len - self.amt; painter.holds(self.axis, Px::MIN..=left); diff --git a/tests/cases/scroll.rs b/tests/cases/scroll.rs index cf5f6fe..2de8567 100644 --- a/tests/cases/scroll.rs +++ b/tests/cases/scroll.rs @@ -60,6 +60,69 @@ fn a_wheel_scrolls_the_content_and_stops_at_its_end() { assert_corners!(h, top, (0, 0), (400, 200)); } +#[test] +fn fixed_content_and_a_share_fill_one_viewport() { + let mut h = Harness::new((900, 100)); + let content = rect(Color::RED) + .width(LayoutLen { + px: Px::from_int(600), + rel: Rel::ZERO, + leftover: Weight::ONE, + }) + .add(&mut h.rsc); + let scroll = Scroll::new(content.add_strong(&mut h.rsc), Axis::X); + h.set_root(scroll); + + assert_corners!(h, content, (0, 0), (900, 100)); +} + +#[test] +fn fixed_content_wider_than_the_viewport_still_scrolls() { + let mut h = Harness::new((900, 100)); + let content = rect(Color::RED).width(1200).add(&mut h.rsc); + let scroll = Scroll::new(content.add_strong(&mut h.rsc), Axis::X); + h.set_root(scroll); + + assert_corners!(h, content, (-300, 0), (900, 100)); +} + +#[test] +fn a_lone_share_fills_without_scrolling() { + let mut h = Harness::new((900, 100)); + let content = rect(Color::RED).width(LayoutLen::LEFTOVER).add(&mut h.rsc); + let scroll = Scroll::new(content.add_strong(&mut h.rsc), Axis::X); + h.set_root(scroll); + + assert_corners!(h, content, (0, 0), (900, 100)); +} + +#[test] +fn wrapping_content_beside_a_fixed_length_is_stable_warm_and_cold() { + fn plant(h: &mut Harness) -> (WidgetId, WidgetId) { + let fixed = rect(Color::RED).width(600).add(&mut h.rsc); + let text = wtext("Wrapping shapes one source into as many lines as the box leaves room for, so a paragraph's height is an answer and not a setting.") + .size(16) + .wrap(true) + .width(LayoutLen::LEFTOVER) + .add(&mut h.rsc); + let content = (fixed, text).span(Dir::RIGHT).add(&mut h.rsc); + let scroll = Scroll::new(content.add_strong(&mut h.rsc), Axis::X); + h.set_root(scroll); + (text.id(), content.id()) + } + + let mut warm = Harness::new((900, 300)); + let (text, content) = plant(&mut warm); + warm.rsc.widgets_mut().get_dyn_mut(text); + warm.frame(); + + let mut cold = Harness::new((900, 300)); + let (cold_text, cold_content) = plant(&mut cold); + + assert_eq!(warm.region(&text), cold.region(&cold_text)); + assert_eq!(warm.region(&content), cold.region(&cold_content)); +} + /// A widget that clips to its box may not report more than the box: its /// parent would place the part it cut off, and the framework would put a /// drawing longer than its box somewhere. `Masked` is the second of these