summaryrefslogtreecommitdiffstats
path: root/widget
diff options
context:
space:
mode:
Diffstat (limited to 'widget')
-rw-r--r--widget/src/container.rs1
-rw-r--r--widget/src/scrollable.rs90
2 files changed, 60 insertions, 31 deletions
diff --git a/widget/src/container.rs b/widget/src/container.rs
index c3a66360..3b794099 100644
--- a/widget/src/container.rs
+++ b/widget/src/container.rs
@@ -459,6 +459,7 @@ pub fn visible_bounds(id: Id) -> Task<Option<Rectangle>> {
_state: &mut dyn widget::operation::Scrollable,
_id: Option<&widget::Id>,
bounds: Rectangle,
+ _content_bounds: Rectangle,
translation: Vector,
) {
match self.scrollables.last() {
diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs
index c2089340..f8455392 100644
--- a/widget/src/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -243,6 +243,24 @@ impl Direction {
Self::Horizontal(_) => None,
}
}
+
+ fn align(&self, delta: Vector) -> Vector {
+ let horizontal_alignment =
+ self.horizontal().map(|p| p.alignment).unwrap_or_default();
+
+ let vertical_alignment =
+ self.vertical().map(|p| p.alignment).unwrap_or_default();
+
+ let align = |alignment: Anchor, delta: f32| match alignment {
+ Anchor::Start => delta,
+ Anchor::End => -delta,
+ };
+
+ Vector::new(
+ align(horizontal_alignment, delta.x),
+ align(vertical_alignment, delta.y),
+ )
+ }
}
impl Default for Direction {
@@ -430,6 +448,7 @@ where
state,
self.id.as_ref().map(|id| &id.0),
bounds,
+ content_bounds,
translation,
);
@@ -729,12 +748,16 @@ where
};
// TODO: Configurable speed/friction (?)
- movement * 60.0
+ -movement * 60.0
}
mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y),
};
- state.scroll(delta, self.direction, bounds, content_bounds);
+ state.scroll(
+ self.direction.align(delta),
+ bounds,
+ content_bounds,
+ );
if notify_on_scroll(
state,
@@ -770,13 +793,12 @@ where
};
let delta = Vector::new(
- cursor_position.x - scroll_box_touched_at.x,
- cursor_position.y - scroll_box_touched_at.y,
+ scroll_box_touched_at.x - cursor_position.x,
+ scroll_box_touched_at.y - cursor_position.y,
);
state.scroll(
- delta,
- self.direction,
+ self.direction.align(delta),
bounds,
content_bounds,
);
@@ -1110,19 +1132,27 @@ impl From<Id> for widget::Id {
}
/// Produces a [`Task`] that snaps the [`Scrollable`] with the given [`Id`]
-/// to the provided `percentage` along the x & y axis.
+/// to the provided [`RelativeOffset`].
pub fn snap_to<T>(id: Id, offset: RelativeOffset) -> Task<T> {
task::effect(Action::widget(operation::scrollable::snap_to(id.0, offset)))
}
/// Produces a [`Task`] that scrolls the [`Scrollable`] with the given [`Id`]
-/// to the provided [`AbsoluteOffset`] along the x & y axis.
+/// to the provided [`AbsoluteOffset`].
pub fn scroll_to<T>(id: Id, offset: AbsoluteOffset) -> Task<T> {
task::effect(Action::widget(operation::scrollable::scroll_to(
id.0, offset,
)))
}
+/// Produces a [`Task`] that scrolls the [`Scrollable`] with the given [`Id`]
+/// by the provided [`AbsoluteOffset`].
+pub fn scroll_by<T>(id: Id, offset: AbsoluteOffset) -> Task<T> {
+ task::effect(Action::widget(operation::scrollable::scroll_by(
+ id.0, offset,
+ )))
+}
+
/// Returns [`true`] if the viewport actually changed.
fn notify_on_scroll<Message>(
state: &mut State,
@@ -1210,6 +1240,15 @@ impl operation::Scrollable for State {
fn scroll_to(&mut self, offset: AbsoluteOffset) {
State::scroll_to(self, offset);
}
+
+ fn scroll_by(
+ &mut self,
+ offset: AbsoluteOffset,
+ bounds: Rectangle,
+ content_bounds: Rectangle,
+ ) {
+ State::scroll_by(self, offset, bounds, content_bounds);
+ }
}
#[derive(Debug, Clone, Copy)]
@@ -1313,34 +1352,13 @@ impl State {
pub fn scroll(
&mut self,
delta: Vector<f32>,
- direction: Direction,
bounds: Rectangle,
content_bounds: Rectangle,
) {
- let horizontal_alignment = direction
- .horizontal()
- .map(|p| p.alignment)
- .unwrap_or_default();
-
- let vertical_alignment = direction
- .vertical()
- .map(|p| p.alignment)
- .unwrap_or_default();
-
- let align = |alignment: Anchor, delta: f32| match alignment {
- Anchor::Start => delta,
- Anchor::End => -delta,
- };
-
- let delta = Vector::new(
- align(horizontal_alignment, delta.x),
- align(vertical_alignment, delta.y),
- );
-
if bounds.height < content_bounds.height {
self.offset_y = Offset::Absolute(
(self.offset_y.absolute(bounds.height, content_bounds.height)
- - delta.y)
+ + delta.y)
.clamp(0.0, content_bounds.height - bounds.height),
);
}
@@ -1348,7 +1366,7 @@ impl State {
if bounds.width < content_bounds.width {
self.offset_x = Offset::Absolute(
(self.offset_x.absolute(bounds.width, content_bounds.width)
- - delta.x)
+ + delta.x)
.clamp(0.0, content_bounds.width - bounds.width),
);
}
@@ -1394,6 +1412,16 @@ impl State {
self.offset_y = Offset::Absolute(offset.y.max(0.0));
}
+ /// Scroll by the provided [`AbsoluteOffset`].
+ pub fn scroll_by(
+ &mut self,
+ offset: AbsoluteOffset,
+ bounds: Rectangle,
+ content_bounds: Rectangle,
+ ) {
+ self.scroll(Vector::new(offset.x, offset.y), bounds, content_bounds);
+ }
+
/// Unsnaps the current scroll position, if snapped, given the bounds of the
/// [`Scrollable`] and its contents.
pub fn unsnap(&mut self, bounds: Rectangle, content_bounds: Rectangle) {