From e102e89c6ade6fa5bb9a716a1d836a636dcf2918 Mon Sep 17 00:00:00 2001 From: lufte Date: Fri, 10 May 2024 18:50:10 -0300 Subject: Implement `scroll_by` operation for `scrollable` `scroll_by` allows scrolling an absolute offset that is applied to the current scrolling position. --- core/src/widget/operation.rs | 46 +++++++++++++++++++++++++++++---- core/src/widget/operation/scrollable.rs | 45 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) (limited to 'core/src/widget') diff --git a/core/src/widget/operation.rs b/core/src/widget/operation.rs index 4ee4b4a7..097c3601 100644 --- a/core/src/widget/operation.rs +++ b/core/src/widget/operation.rs @@ -38,6 +38,7 @@ pub trait Operation: Send { _state: &mut dyn Scrollable, _id: Option<&Id>, _bounds: Rectangle, + _content_bounds: Rectangle, _translation: Vector, ) { } @@ -76,9 +77,16 @@ where state: &mut dyn Scrollable, id: Option<&Id>, bounds: Rectangle, + content_bounds: Rectangle, translation: Vector, ) { - self.as_mut().scrollable(state, id, bounds, translation); + self.as_mut().scrollable( + state, + id, + bounds, + content_bounds, + translation, + ); } fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { @@ -151,9 +159,16 @@ where state: &mut dyn Scrollable, id: Option<&Id>, bounds: Rectangle, + content_bounds: Rectangle, translation: Vector, ) { - self.operation.scrollable(state, id, bounds, translation); + self.operation.scrollable( + state, + id, + bounds, + content_bounds, + translation, + ); } fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { @@ -222,9 +237,16 @@ where state: &mut dyn Scrollable, id: Option<&Id>, bounds: Rectangle, + content_bounds: Rectangle, translation: Vector, ) { - self.operation.scrollable(state, id, bounds, translation); + self.operation.scrollable( + state, + id, + bounds, + content_bounds, + translation, + ); } fn focusable( @@ -262,9 +284,16 @@ where state: &mut dyn Scrollable, id: Option<&Id>, bounds: Rectangle, + content_bounds: Rectangle, translation: Vector, ) { - self.operation.scrollable(state, id, bounds, translation); + self.operation.scrollable( + state, + id, + bounds, + content_bounds, + translation, + ); } fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { @@ -341,9 +370,16 @@ where state: &mut dyn Scrollable, id: Option<&Id>, bounds: Rectangle, + content_bounds: Rectangle, translation: crate::Vector, ) { - self.operation.scrollable(state, id, bounds, translation); + self.operation.scrollable( + state, + id, + bounds, + content_bounds, + translation, + ); } fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { diff --git a/core/src/widget/operation/scrollable.rs b/core/src/widget/operation/scrollable.rs index 12161255..c2fecf56 100644 --- a/core/src/widget/operation/scrollable.rs +++ b/core/src/widget/operation/scrollable.rs @@ -9,6 +9,14 @@ pub trait Scrollable { /// Scroll the widget to the given [`AbsoluteOffset`] along the horizontal & vertical axis. fn scroll_to(&mut self, offset: AbsoluteOffset); + + /// Scroll the widget by the given [`AbsoluteOffset`] along the horizontal & vertical axis. + fn scroll_by( + &mut self, + offset: AbsoluteOffset, + bounds: Rectangle, + content_bounds: Rectangle, + ); } /// Produces an [`Operation`] that snaps the widget with the given [`Id`] to @@ -34,6 +42,7 @@ pub fn snap_to(target: Id, offset: RelativeOffset) -> impl Operation { state: &mut dyn Scrollable, id: Option<&Id>, _bounds: Rectangle, + _content_bounds: Rectangle, _translation: Vector, ) { if Some(&self.target) == id { @@ -68,6 +77,7 @@ pub fn scroll_to(target: Id, offset: AbsoluteOffset) -> impl Operation { state: &mut dyn Scrollable, id: Option<&Id>, _bounds: Rectangle, + _content_bounds: Rectangle, _translation: Vector, ) { if Some(&self.target) == id { @@ -79,6 +89,41 @@ pub fn scroll_to(target: Id, offset: AbsoluteOffset) -> impl Operation { ScrollTo { target, offset } } +/// Produces an [`Operation`] that scrolls the widget with the given [`Id`] by +/// the provided [`AbsoluteOffset`]. +pub fn scroll_by(target: Id, offset: AbsoluteOffset) -> impl Operation { + struct ScrollBy { + target: Id, + offset: AbsoluteOffset, + } + + impl Operation for ScrollBy { + fn container( + &mut self, + _id: Option<&Id>, + _bounds: Rectangle, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self); + } + + fn scrollable( + &mut self, + state: &mut dyn Scrollable, + id: Option<&Id>, + bounds: Rectangle, + content_bounds: Rectangle, + _translation: Vector, + ) { + if Some(&self.target) == id { + state.scroll_by(self.offset, bounds, content_bounds); + } + } + } + + ScrollBy { target, offset } +} + /// The amount of absolute offset in each direction of a [`Scrollable`]. #[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct AbsoluteOffset { -- cgit