summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/scrollable/src/main.rs6
-rw-r--r--native/src/widget/operation/scrollable.rs9
-rw-r--r--native/src/widget/scrollable.rs94
-rw-r--r--src/widget.rs4
4 files changed, 61 insertions, 52 deletions
diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs
index be8d0f52..97344c94 100644
--- a/examples/scrollable/src/main.rs
+++ b/examples/scrollable/src/main.rs
@@ -36,7 +36,7 @@ enum Message {
ScrollerWidthChanged(u16),
ScrollToBeginning,
ScrollToEnd,
- Scrolled(scrollable::CurrentOffset),
+ Scrolled(scrollable::Viewport),
}
impl Application for ScrollableDemo {
@@ -104,8 +104,8 @@ impl Application for ScrollableDemo {
self.current_scroll_offset,
)
}
- Message::Scrolled(offset) => {
- self.current_scroll_offset = offset.relative;
+ Message::Scrolled(viewport) => {
+ self.current_scroll_offset = viewport.relative_offset();
Command::none()
}
diff --git a/native/src/widget/operation/scrollable.rs b/native/src/widget/operation/scrollable.rs
index 62f4c91e..f947344d 100644
--- a/native/src/widget/operation/scrollable.rs
+++ b/native/src/widget/operation/scrollable.rs
@@ -64,15 +64,6 @@ pub fn scroll_to<T>(target: Id, offset: AbsoluteOffset) -> impl Operation<T> {
ScrollTo { target, offset }
}
-/// The current absolute & relative offset of a [`Scrollable`]
-#[derive(Debug, Clone, Copy, PartialEq, Default)]
-pub struct CurrentOffset {
- /// The [`AbsoluteOffset`] of a [`Scrollable`]
- pub absolute: AbsoluteOffset,
- /// The [`RelativeOffset`] of a [`Scrollable`]
- pub relative: RelativeOffset,
-}
-
/// The amount of absolute offset in each direction of a [`Scrollable`].
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct AbsoluteOffset {
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index eedddfd0..c66a166b 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -15,9 +15,7 @@ use crate::{
};
pub use iced_style::scrollable::StyleSheet;
-pub use operation::scrollable::{
- AbsoluteOffset, CurrentOffset, RelativeOffset,
-};
+pub use operation::scrollable::{AbsoluteOffset, RelativeOffset};
pub mod style {
//! The styles of a [`Scrollable`].
@@ -40,7 +38,7 @@ where
vertical: Properties,
horizontal: Option<Properties>,
content: Element<'a, Message, Renderer>,
- on_scroll: Option<Box<dyn Fn(CurrentOffset) -> Message + 'a>>,
+ on_scroll: Option<Box<dyn Fn(Viewport) -> Message + 'a>>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -95,11 +93,8 @@ where
/// Sets a function to call when the [`Scrollable`] is scrolled.
///
- /// The function takes the [`CurrentOffset`] of the [`Scrollable`]
- pub fn on_scroll(
- mut self,
- f: impl Fn(CurrentOffset) -> Message + 'a,
- ) -> Self {
+ /// The function takes the [`Viewport`] of the [`Scrollable`]
+ pub fn on_scroll(mut self, f: impl Fn(Viewport) -> Message + 'a) -> Self {
self.on_scroll = Some(Box::new(f));
self
}
@@ -437,7 +432,7 @@ pub fn update<Message>(
shell: &mut Shell<'_, Message>,
vertical: &Properties,
horizontal: Option<&Properties>,
- on_scroll: &Option<Box<dyn Fn(CurrentOffset) -> Message + '_>>,
+ on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>,
update_content: impl FnOnce(
Event,
Layout<'_>,
@@ -897,7 +892,7 @@ pub fn draw<Renderer>(
fn notify_on_scroll<Message>(
state: &mut State,
- on_scroll: &Option<Box<dyn Fn(CurrentOffset) -> Message + '_>>,
+ on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>,
bounds: Rectangle,
content_bounds: Rectangle,
shell: &mut Shell<'_, Message>,
@@ -909,39 +904,29 @@ fn notify_on_scroll<Message>(
return;
}
- let absolute_x =
- state.offset_x.absolute(bounds.width, content_bounds.width);
- let relative_x = absolute_x / (content_bounds.width - bounds.width);
-
- let absolute_y = state
- .offset_y
- .absolute(bounds.height, content_bounds.height);
- let relative_y = absolute_y / (content_bounds.height - bounds.height);
-
- let absolute = AbsoluteOffset {
- x: absolute_x,
- y: absolute_y,
- };
- let relative = RelativeOffset {
- x: relative_x,
- y: relative_y,
+ let viewport = Viewport {
+ offset_x: state.offset_x,
+ offset_y: state.offset_y,
+ bounds,
+ content_bounds,
};
- // Don't publish redundant offsets to shell
- if let Some(prev_relative) = state.last_notified {
+ // Don't publish redundant viewports to shell
+ if let Some(last_notified) = state.last_notified {
+ let prev = last_notified.relative_offset();
+ let curr = viewport.relative_offset();
+
let unchanged = |a: f32, b: f32| {
(a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan())
};
- if unchanged(prev_relative.x, relative.x)
- && unchanged(prev_relative.y, relative.y)
- {
+ if unchanged(prev.x, curr.x) && unchanged(prev.y, curr.y) {
return;
}
}
- shell.publish(on_scroll(CurrentOffset { absolute, relative }));
- state.last_notified = Some(relative);
+ shell.publish(on_scroll(viewport));
+ state.last_notified = Some(viewport);
}
}
@@ -954,7 +939,7 @@ pub struct State {
offset_x: Offset,
x_scroller_grabbed_at: Option<f32>,
keyboard_modifiers: keyboard::Modifiers,
- last_notified: Option<RelativeOffset>,
+ last_notified: Option<Viewport>,
}
impl Default for State {
@@ -988,18 +973,51 @@ enum Offset {
}
impl Offset {
- fn absolute(self, window: f32, content: f32) -> f32 {
+ fn absolute(self, viewport: f32, content: f32) -> f32 {
match self {
Offset::Absolute(absolute) => {
- absolute.min((content - window).max(0.0))
+ absolute.min((content - viewport).max(0.0))
}
Offset::Relative(percentage) => {
- ((content - window) * percentage).max(0.0)
+ ((content - viewport) * percentage).max(0.0)
}
}
}
}
+/// The current [`Viewport`] of the [`Scrollable`].
+#[derive(Debug, Clone, Copy)]
+pub struct Viewport {
+ offset_x: Offset,
+ offset_y: Offset,
+ bounds: Rectangle,
+ content_bounds: Rectangle,
+}
+
+impl Viewport {
+ /// Returns the [`AbsoluteOffset`] of the current [`Viewport`].
+ pub fn absolute_offset(&self) -> AbsoluteOffset {
+ let x = self
+ .offset_x
+ .absolute(self.bounds.width, self.content_bounds.width);
+ let y = self
+ .offset_y
+ .absolute(self.bounds.height, self.content_bounds.height);
+
+ AbsoluteOffset { x, y }
+ }
+
+ /// Returns the [`RelativeOffset`] of the current [`Viewport`].
+ pub fn relative_offset(&self) -> RelativeOffset {
+ let AbsoluteOffset { x, y } = self.absolute_offset();
+
+ let x = x / (self.content_bounds.width - self.bounds.width);
+ let y = y / (self.content_bounds.height - self.bounds.height);
+
+ RelativeOffset { x, y }
+ }
+}
+
impl State {
/// Creates a new [`State`] with the scrollbar(s) at the beginning.
pub fn new() -> Self {
diff --git a/src/widget.rs b/src/widget.rs
index 87e82f47..38995a45 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -109,8 +109,8 @@ pub mod radio {
pub mod scrollable {
//! Navigate an endless amount of content with a scrollbar.
pub use iced_native::widget::scrollable::{
- snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset,
- CurrentOffset, Id, Properties, RelativeOffset, StyleSheet,
+ snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, Id,
+ Properties, RelativeOffset, StyleSheet, Viewport,
};
/// A widget that can vertically display an infinite amount of content