@@ -3193,7 +3193,11 @@ impl ScrollHandle {
match active_item.strategy {
ScrollStrategy::FirstVisible => {
if state.overflow.y == Overflow::Scroll {
- if bounds.top() + scroll_offset.y < state.bounds.top() {
+ let child_height = bounds.size.height;
+ let viewport_height = state.bounds.size.height;
+ if child_height > viewport_height {
+ scroll_offset.y = state.bounds.top() - bounds.top();
+ } else if bounds.top() + scroll_offset.y < state.bounds.top() {
scroll_offset.y = state.bounds.top() - bounds.top();
} else if bounds.bottom() + scroll_offset.y > state.bounds.bottom() {
scroll_offset.y = state.bounds.bottom() - bounds.bottom();
@@ -3206,7 +3210,11 @@ impl ScrollHandle {
}
if state.overflow.x == Overflow::Scroll {
- if bounds.left() + scroll_offset.x < state.bounds.left() {
+ let child_width = bounds.size.width;
+ let viewport_width = state.bounds.size.width;
+ if child_width > viewport_width {
+ scroll_offset.x = state.bounds.left() - bounds.left();
+ } else if bounds.left() + scroll_offset.x < state.bounds.left() {
scroll_offset.x = state.bounds.left() - bounds.left();
} else if bounds.right() + scroll_offset.x > state.bounds.right() {
scroll_offset.x = state.bounds.right() - bounds.right();
@@ -3268,3 +3276,46 @@ impl ScrollHandle {
self.0.borrow().child_bounds.len()
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn scroll_handle_aligns_wide_children_to_left_edge() {
+ let handle = ScrollHandle::new();
+ {
+ let mut state = handle.0.borrow_mut();
+ state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(80.), px(20.)));
+ state.child_bounds = vec![Bounds::new(point(px(25.), px(0.)), size(px(200.), px(20.)))];
+ state.overflow.x = Overflow::Scroll;
+ state.active_item = Some(ScrollActiveItem {
+ index: 0,
+ strategy: ScrollStrategy::default(),
+ });
+ }
+
+ handle.scroll_to_active_item();
+
+ assert_eq!(handle.offset().x, px(-25.));
+ }
+
+ #[test]
+ fn scroll_handle_aligns_tall_children_to_top_edge() {
+ let handle = ScrollHandle::new();
+ {
+ let mut state = handle.0.borrow_mut();
+ state.bounds = Bounds::new(point(px(0.), px(0.)), size(px(20.), px(80.)));
+ state.child_bounds = vec![Bounds::new(point(px(0.), px(25.)), size(px(20.), px(200.)))];
+ state.overflow.y = Overflow::Scroll;
+ state.active_item = Some(ScrollActiveItem {
+ index: 0,
+ strategy: ScrollStrategy::default(),
+ });
+ }
+
+ handle.scroll_to_active_item();
+
+ assert_eq!(handle.offset().y, px(-25.));
+ }
+}