iced_core/widget/operation/
scrollable.rs1use crate::widget::{Id, Operation};
3use crate::{Rectangle, Vector};
4
5pub trait Scrollable {
7 fn snap_to(&mut self, offset: RelativeOffset<Option<f32>>);
9
10 fn scroll_to(&mut self, offset: AbsoluteOffset<Option<f32>>);
12
13 fn scroll_by(&mut self, offset: AbsoluteOffset, bounds: Rectangle, content_bounds: Rectangle);
15}
16
17pub fn snap_to<T>(target: Id, offset: RelativeOffset<Option<f32>>) -> impl Operation<T> {
20 struct SnapTo {
21 target: Id,
22 offset: RelativeOffset<Option<f32>>,
23 }
24
25 impl<T> Operation<T> for SnapTo {
26 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
27 operate(self);
28 }
29
30 fn scrollable(
31 &mut self,
32 id: Option<&Id>,
33 _bounds: Rectangle,
34 _content_bounds: Rectangle,
35 _translation: Vector,
36 state: &mut dyn Scrollable,
37 ) {
38 if Some(&self.target) == id {
39 state.snap_to(self.offset);
40 }
41 }
42 }
43
44 SnapTo { target, offset }
45}
46
47pub fn scroll_to<T>(target: Id, offset: AbsoluteOffset<Option<f32>>) -> impl Operation<T> {
50 struct ScrollTo {
51 target: Id,
52 offset: AbsoluteOffset<Option<f32>>,
53 }
54
55 impl<T> Operation<T> for ScrollTo {
56 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
57 operate(self);
58 }
59
60 fn scrollable(
61 &mut self,
62 id: Option<&Id>,
63 _bounds: Rectangle,
64 _content_bounds: Rectangle,
65 _translation: Vector,
66 state: &mut dyn Scrollable,
67 ) {
68 if Some(&self.target) == id {
69 state.scroll_to(self.offset);
70 }
71 }
72 }
73
74 ScrollTo { target, offset }
75}
76
77pub fn scroll_by<T>(target: Id, offset: AbsoluteOffset) -> impl Operation<T> {
80 struct ScrollBy {
81 target: Id,
82 offset: AbsoluteOffset,
83 }
84
85 impl<T> Operation<T> for ScrollBy {
86 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
87 operate(self);
88 }
89
90 fn scrollable(
91 &mut self,
92 id: Option<&Id>,
93 bounds: Rectangle,
94 content_bounds: Rectangle,
95 _translation: Vector,
96 state: &mut dyn Scrollable,
97 ) {
98 if Some(&self.target) == id {
99 state.scroll_by(self.offset, bounds, content_bounds);
100 }
101 }
102 }
103
104 ScrollBy { target, offset }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Default)]
109pub struct AbsoluteOffset<T = f32> {
110 pub x: T,
112 pub y: T,
114}
115
116impl From<AbsoluteOffset> for AbsoluteOffset<Option<f32>> {
117 fn from(offset: AbsoluteOffset) -> Self {
118 Self {
119 x: Some(offset.x),
120 y: Some(offset.y),
121 }
122 }
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Default)]
129pub struct RelativeOffset<T = f32> {
130 pub x: T,
132 pub y: T,
134}
135
136impl RelativeOffset {
137 pub const START: Self = Self { x: 0.0, y: 0.0 };
139
140 pub const END: Self = Self { x: 1.0, y: 1.0 };
142}
143
144impl From<RelativeOffset> for RelativeOffset<Option<f32>> {
145 fn from(offset: RelativeOffset) -> Self {
146 Self {
147 x: Some(offset.x),
148 y: Some(offset.y),
149 }
150 }
151}