iced_core/widget/operation/
scrollable.rs1use crate::widget::operation::Animation;
3use crate::widget::{Id, Operation};
4use crate::{Rectangle, Size, Vector};
5
6pub trait Scrollable {
8 fn snap_to(
10 &mut self,
11 offset: RelativeOffset<Option<f32>>,
12 animation: Animation,
13 bounds: Rectangle,
14 content: Size,
15 );
16
17 fn scroll_to(
19 &mut self,
20 offset: AbsoluteOffset<Option<f32>>,
21 animation: Animation,
22 bounds: Rectangle,
23 content: Size,
24 );
25
26 fn scroll_by(
28 &mut self,
29 offset: AbsoluteOffset,
30 animation: Animation,
31 bounds: Rectangle,
32 content: Size,
33 );
34}
35
36pub fn snap_to<T>(
39 target: Id,
40 offset: RelativeOffset<Option<f32>>,
41 animation: Animation,
42) -> impl Operation<T> {
43 struct SnapTo {
44 target: Id,
45 offset: RelativeOffset<Option<f32>>,
46 animation: Animation,
47 }
48
49 impl<T> Operation<T> for SnapTo {
50 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
51 operate(self);
52 }
53
54 fn scrollable(
55 &mut self,
56 id: Option<&Id>,
57 bounds: Rectangle,
58 content: Size,
59 _translation: Vector,
60 state: &mut dyn Scrollable,
61 ) {
62 if Some(&self.target) == id {
63 state.snap_to(self.offset, self.animation, bounds, content);
64 }
65 }
66 }
67
68 SnapTo {
69 target,
70 offset,
71 animation,
72 }
73}
74
75pub fn scroll_to<T>(
78 target: Id,
79 offset: AbsoluteOffset<Option<f32>>,
80 animation: Animation,
81) -> impl Operation<T> {
82 struct ScrollTo {
83 target: Id,
84 offset: AbsoluteOffset<Option<f32>>,
85 animation: Animation,
86 }
87
88 impl<T> Operation<T> for ScrollTo {
89 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
90 operate(self);
91 }
92
93 fn scrollable(
94 &mut self,
95 id: Option<&Id>,
96 bounds: Rectangle,
97 content: Size,
98 _translation: Vector,
99 state: &mut dyn Scrollable,
100 ) {
101 if Some(&self.target) == id {
102 state.scroll_to(self.offset, self.animation, bounds, content);
103 }
104 }
105 }
106
107 ScrollTo {
108 target,
109 offset,
110 animation,
111 }
112}
113
114pub fn scroll_by<T>(target: Id, offset: AbsoluteOffset, animation: Animation) -> impl Operation<T> {
117 struct ScrollBy {
118 target: Id,
119 offset: AbsoluteOffset,
120 animation: Animation,
121 }
122
123 impl<T> Operation<T> for ScrollBy {
124 fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
125 operate(self);
126 }
127
128 fn scrollable(
129 &mut self,
130 id: Option<&Id>,
131 bounds: Rectangle,
132 content: Size,
133 _translation: Vector,
134 state: &mut dyn Scrollable,
135 ) {
136 if Some(&self.target) == id {
137 state.scroll_by(self.offset, self.animation, bounds, content);
138 }
139 }
140 }
141
142 ScrollBy {
143 target,
144 offset,
145 animation,
146 }
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Default)]
151pub struct AbsoluteOffset<T = f32> {
152 pub x: T,
154 pub y: T,
156}
157
158impl From<AbsoluteOffset> for AbsoluteOffset<Option<f32>> {
159 fn from(offset: AbsoluteOffset) -> Self {
160 Self {
161 x: Some(offset.x),
162 y: Some(offset.y),
163 }
164 }
165}
166
167impl std::ops::Add<Vector> for AbsoluteOffset {
168 type Output = Self;
169
170 fn add(self, translation: Vector) -> Self::Output {
171 Self {
172 x: self.x + translation.x,
173 y: self.y + translation.y,
174 }
175 }
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Default)]
182pub struct RelativeOffset<T = f32> {
183 pub x: T,
185 pub y: T,
187}
188
189impl RelativeOffset {
190 pub const START: Self = Self { x: 0.0, y: 0.0 };
192
193 pub const END: Self = Self { x: 1.0, y: 1.0 };
195}
196
197impl From<RelativeOffset> for RelativeOffset<Option<f32>> {
198 fn from(offset: RelativeOffset) -> Self {
199 Self {
200 x: Some(offset.x),
201 y: Some(offset.y),
202 }
203 }
204}