diff --git a/src/widget/position/scroll.rs b/src/widget/position/scroll.rs index 8a29257..9771df1 100644 --- a/src/widget/position/scroll.rs +++ b/src/widget/position/scroll.rs @@ -44,7 +44,6 @@ impl Widget for Scroll { // have placed the whole scroll in a box longer than it. let slack = (self.container_len - self.content_len).max(Px::ZERO); let anchor = slack.mul(align.rel()); - let mut content = UiSpan::FULL; // Content that fills the viewport and has not been scrolled is the // viewport, and is handed back as it came. Writing the same box as // its own length in pixels is the same box in another form, and the @@ -52,18 +51,20 @@ impl Widget for Scroll { // one centred in `px 900`, since halving a difference is not halving // each part of it. let moved = anchor != Px::ZERO || self.amt != Px::ZERO; - if moved || self.content_len != self.container_len { - let start = Len::from_parts(Rel::ZERO, anchor - self.amt); - content = UiSpan::new(start, start.offset(self.content_len)); - } + 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))) + } + false => Part::All, + }; // The viewport is the inner's frame, so a fraction it declares or // reports is a fraction of what is on screen rather than of the // content box its own answer decided. Where it goes is the content // box, scrolled: its drawing moved there, not made again there. painter.place_at( &self.inner, - self.axis - .pair(Place::Fill(Part::From(content)), Place::Fill(Part::All)), + self.axis.pair(Place::Fill(content), Place::Fill(Part::All)), ); // 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 diff --git a/tests/cases/scroll.rs b/tests/cases/scroll.rs index 2de8567..e7094c9 100644 --- a/tests/cases/scroll.rs +++ b/tests/cases/scroll.rs @@ -145,3 +145,19 @@ fn a_clipping_widget_reporting_more_than_its_box_is_caught() { h.set_root(clipper); h.frame(); } + +/// Content that fits sits in the viewport, not in a box of the window's +/// length anchored at the viewport's start. `Part::From` takes window +/// lengths, so a `rel(1.0)` span in one is the window, and only a scroll +/// filling the window would land right. +#[test] +fn content_that_fits_is_placed_in_the_viewport_and_not_in_the_window() { + let mut h = Harness::new((400, 400)); + let head = rect(Color::RED).height(100).add(&mut h.rsc); + let inner = rect(Color::BLUE).height(50).add(&mut h.rsc); + let scroll = Scroll::new(inner.add_strong(&mut h.rsc), Axis::Y).add(&mut h.rsc); + h.set_root((head, scroll).span(Dir::DOWN)); + + assert_corners!(h, scroll, (0, 100), (400, 400)); + assert_corners!(h, inner, (0, 225), (400, 275)); +}