Merge pull request #2994 from rizzen-yazston/scrollable
[Scrollable] Added the ability to change a specific direction offset when updating the scrollable's offsets.
This commit is contained in:
commit
10b4e6d688
3 changed files with 67 additions and 27 deletions
|
|
@ -5,10 +5,10 @@ use crate::{Rectangle, Vector};
|
||||||
/// The internal state of a widget that can be scrolled.
|
/// The internal state of a widget that can be scrolled.
|
||||||
pub trait Scrollable {
|
pub trait Scrollable {
|
||||||
/// Snaps the scroll of the widget to the given `percentage` along the horizontal & vertical axis.
|
/// Snaps the scroll of the widget to the given `percentage` along the horizontal & vertical axis.
|
||||||
fn snap_to(&mut self, offset: RelativeOffset);
|
fn snap_to(&mut self, offset: RelativeOffset<Option<f32>>);
|
||||||
|
|
||||||
/// Scroll the widget to the given [`AbsoluteOffset`] along the horizontal & vertical axis.
|
/// Scroll the widget to the given [`AbsoluteOffset`] along the horizontal & vertical axis.
|
||||||
fn scroll_to(&mut self, offset: AbsoluteOffset);
|
fn scroll_to(&mut self, offset: AbsoluteOffset<Option<f32>>);
|
||||||
|
|
||||||
/// Scroll the widget by the given [`AbsoluteOffset`] along the horizontal & vertical axis.
|
/// Scroll the widget by the given [`AbsoluteOffset`] along the horizontal & vertical axis.
|
||||||
fn scroll_by(
|
fn scroll_by(
|
||||||
|
|
@ -21,10 +21,13 @@ pub trait Scrollable {
|
||||||
|
|
||||||
/// Produces an [`Operation`] that snaps the widget with the given [`Id`] to
|
/// Produces an [`Operation`] that snaps the widget with the given [`Id`] to
|
||||||
/// the provided `percentage`.
|
/// the provided `percentage`.
|
||||||
pub fn snap_to<T>(target: Id, offset: RelativeOffset) -> impl Operation<T> {
|
pub fn snap_to<T>(
|
||||||
|
target: Id,
|
||||||
|
offset: RelativeOffset<Option<f32>>,
|
||||||
|
) -> impl Operation<T> {
|
||||||
struct SnapTo {
|
struct SnapTo {
|
||||||
target: Id,
|
target: Id,
|
||||||
offset: RelativeOffset,
|
offset: RelativeOffset<Option<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Operation<T> for SnapTo {
|
impl<T> Operation<T> for SnapTo {
|
||||||
|
|
@ -51,10 +54,13 @@ pub fn snap_to<T>(target: Id, offset: RelativeOffset) -> impl Operation<T> {
|
||||||
|
|
||||||
/// Produces an [`Operation`] that scrolls the widget with the given [`Id`] to
|
/// Produces an [`Operation`] that scrolls the widget with the given [`Id`] to
|
||||||
/// the provided [`AbsoluteOffset`].
|
/// the provided [`AbsoluteOffset`].
|
||||||
pub fn scroll_to<T>(target: Id, offset: AbsoluteOffset) -> impl Operation<T> {
|
pub fn scroll_to<T>(
|
||||||
|
target: Id,
|
||||||
|
offset: AbsoluteOffset<Option<f32>>,
|
||||||
|
) -> impl Operation<T> {
|
||||||
struct ScrollTo {
|
struct ScrollTo {
|
||||||
target: Id,
|
target: Id,
|
||||||
offset: AbsoluteOffset,
|
offset: AbsoluteOffset<Option<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Operation<T> for ScrollTo {
|
impl<T> Operation<T> for ScrollTo {
|
||||||
|
|
@ -111,22 +117,31 @@ pub fn scroll_by<T>(target: Id, offset: AbsoluteOffset) -> impl Operation<T> {
|
||||||
|
|
||||||
/// The amount of absolute offset in each direction of a [`Scrollable`].
|
/// The amount of absolute offset in each direction of a [`Scrollable`].
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct AbsoluteOffset {
|
pub struct AbsoluteOffset<T = f32> {
|
||||||
/// The amount of horizontal offset
|
/// The amount of horizontal offset
|
||||||
pub x: f32,
|
pub x: T,
|
||||||
/// The amount of vertical offset
|
/// The amount of vertical offset
|
||||||
pub y: f32,
|
pub y: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AbsoluteOffset> for AbsoluteOffset<Option<f32>> {
|
||||||
|
fn from(offset: AbsoluteOffset) -> Self {
|
||||||
|
Self {
|
||||||
|
x: Some(offset.x),
|
||||||
|
y: Some(offset.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The amount of relative offset in each direction of a [`Scrollable`].
|
/// The amount of relative offset in each direction of a [`Scrollable`].
|
||||||
///
|
///
|
||||||
/// A value of `0.0` means start, while `1.0` means end.
|
/// A value of `0.0` means start, while `1.0` means end.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct RelativeOffset {
|
pub struct RelativeOffset<T = f32> {
|
||||||
/// The amount of horizontal offset
|
/// The amount of horizontal offset
|
||||||
pub x: f32,
|
pub x: T,
|
||||||
/// The amount of vertical offset
|
/// The amount of vertical offset
|
||||||
pub y: f32,
|
pub y: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelativeOffset {
|
impl RelativeOffset {
|
||||||
|
|
@ -136,3 +151,12 @@ impl RelativeOffset {
|
||||||
/// A relative offset that points to the bottom-right of a [`Scrollable`].
|
/// A relative offset that points to the bottom-right of a [`Scrollable`].
|
||||||
pub const END: Self = Self { x: 1.0, y: 1.0 };
|
pub const END: Self = Self { x: 1.0, y: 1.0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RelativeOffset> for RelativeOffset<Option<f32>> {
|
||||||
|
fn from(offset: RelativeOffset) -> Self {
|
||||||
|
Self {
|
||||||
|
x: Some(offset.x),
|
||||||
|
y: Some(offset.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,13 @@ pub use crate::core::widget::operation::scrollable::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Snaps the scrollable with the given [`Id`] to the provided [`RelativeOffset`].
|
/// Snaps the scrollable with the given [`Id`] to the provided [`RelativeOffset`].
|
||||||
pub fn snap_to<T>(id: impl Into<Id>, offset: RelativeOffset) -> Task<T> {
|
pub fn snap_to<T>(
|
||||||
|
id: impl Into<Id>,
|
||||||
|
offset: impl Into<RelativeOffset<Option<f32>>>,
|
||||||
|
) -> Task<T> {
|
||||||
task::effect(Action::widget(operation::scrollable::snap_to(
|
task::effect(Action::widget(operation::scrollable::snap_to(
|
||||||
id.into(),
|
id.into(),
|
||||||
offset,
|
offset.into(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,15 +23,18 @@ pub fn snap_to<T>(id: impl Into<Id>, offset: RelativeOffset) -> Task<T> {
|
||||||
pub fn snap_to_end<T>(id: impl Into<Id>) -> Task<T> {
|
pub fn snap_to_end<T>(id: impl Into<Id>) -> Task<T> {
|
||||||
task::effect(Action::widget(operation::scrollable::snap_to(
|
task::effect(Action::widget(operation::scrollable::snap_to(
|
||||||
id.into(),
|
id.into(),
|
||||||
RelativeOffset::END,
|
RelativeOffset::END.into(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scrolls the scrollable with the given [`Id`] to the provided [`AbsoluteOffset`].
|
/// Scrolls the scrollable with the given [`Id`] to the provided [`AbsoluteOffset`].
|
||||||
pub fn scroll_to<T>(id: impl Into<Id>, offset: AbsoluteOffset) -> Task<T> {
|
pub fn scroll_to<T>(
|
||||||
|
id: impl Into<Id>,
|
||||||
|
offset: impl Into<AbsoluteOffset<Option<f32>>>,
|
||||||
|
) -> Task<T> {
|
||||||
task::effect(Action::widget(operation::scrollable::scroll_to(
|
task::effect(Action::widget(operation::scrollable::scroll_to(
|
||||||
id.into(),
|
id.into(),
|
||||||
offset,
|
offset.into(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1673,11 +1673,11 @@ impl Default for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl operation::Scrollable for State {
|
impl operation::Scrollable for State {
|
||||||
fn snap_to(&mut self, offset: RelativeOffset) {
|
fn snap_to(&mut self, offset: RelativeOffset<Option<f32>>) {
|
||||||
State::snap_to(self, offset);
|
State::snap_to(self, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to(&mut self, offset: AbsoluteOffset) {
|
fn scroll_to(&mut self, offset: AbsoluteOffset<Option<f32>>) {
|
||||||
State::scroll_to(self, offset);
|
State::scroll_to(self, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1829,18 +1829,28 @@ impl State {
|
||||||
self.unsnap(bounds, content_bounds);
|
self.unsnap(bounds, content_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snap_to(&mut self, offset: RelativeOffset) {
|
fn snap_to(&mut self, offset: RelativeOffset<Option<f32>>) {
|
||||||
self.offset_x = Offset::Relative(offset.x.clamp(0.0, 1.0));
|
if let Some(x) = offset.x {
|
||||||
self.offset_y = Offset::Relative(offset.y.clamp(0.0, 1.0));
|
self.offset_x = Offset::Relative(x.clamp(0.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(y) = offset.y {
|
||||||
|
self.offset_y = Offset::Relative(y.clamp(0.0, 1.0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to(&mut self, offset: AbsoluteOffset) {
|
fn scroll_to(&mut self, offset: AbsoluteOffset<Option<f32>>) {
|
||||||
self.offset_x = Offset::Absolute(offset.x.max(0.0));
|
if let Some(x) = offset.x {
|
||||||
self.offset_y = Offset::Absolute(offset.y.max(0.0));
|
self.offset_x = Offset::Absolute(x.max(0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(y) = offset.y {
|
||||||
|
self.offset_y = Offset::Absolute(y.max(0.0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll by the provided [`AbsoluteOffset`].
|
/// Scroll by the provided [`AbsoluteOffset`].
|
||||||
pub fn scroll_by(
|
fn scroll_by(
|
||||||
&mut self,
|
&mut self,
|
||||||
offset: AbsoluteOffset,
|
offset: AbsoluteOffset,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
|
|
@ -1851,7 +1861,7 @@ impl State {
|
||||||
|
|
||||||
/// Unsnaps the current scroll position, if snapped, given the bounds of the
|
/// Unsnaps the current scroll position, if snapped, given the bounds of the
|
||||||
/// [`Scrollable`] and its contents.
|
/// [`Scrollable`] and its contents.
|
||||||
pub fn unsnap(&mut self, bounds: Rectangle, content_bounds: Rectangle) {
|
fn unsnap(&mut self, bounds: Rectangle, content_bounds: Rectangle) {
|
||||||
self.offset_x = Offset::Absolute(
|
self.offset_x = Offset::Absolute(
|
||||||
self.offset_x.absolute(bounds.width, content_bounds.width),
|
self.offset_x.absolute(bounds.width, content_bounds.width),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue