1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//! Helps manage animating values for widgets, such as animating a button's style. This can be used
//! to manage animations within a widget for anything, but is particularly useful for animating
//! style changes based on widget status.
//!
//! The [`AnimatedState`] can internally keep track of a widget's status and style, and then allow
//! updates to the animated style based on these values. This struct can be built into a widget's
//! internal state and used to manage style animations. It uses interior mutability to lazily
//! update the animated style when the widget is drawn, and requests redraws when the widget status
//! changes in response to some event.
//!
//! This requires that that your animated `Value` implement [`Animate`] - you can normally derive
//! this for simple structs.
//!
//! There are a few steps to using this struct if you want to animate a widget's style:
//!
//! 1. Implement `get_initial_status` and `get_status` functions for your widget. You'll use these
//! to give the initial and current status to the [`AnimatedState`] so it can properly update
//! the animated style. You don't _technically_ need dedicated functions for these, but it can
//! help keep your Widget implementations cleaner. For example, a button might have an initial
//! status fn look like this:
//! ```no_run
//! # struct Button { on_press: Option<fn()> }
//! # enum Status { Active, Disabled }
//! # impl Button {
//!
//! fn get_initial_status(&self) -> Status {
//! if self.on_press.is_some() {
//! Status::Active
//! } else {
//! Status::Disabled
//! }
//! }
//! # }
//! ```
//! For the current status, you can include any other fields that may be useful for determining
//! the current status. For a button, this would be something like the internal widget state
//! for tracking whether the button is pressed, and the cursor + layout for hover states.
//! 2. Add an [`Mode`] to the widget so users can change how the animation behaves.
//! Then, add a builder function for updating it, e.g.
//! ```no_run
//! # use iced_anim::animated::Mode;
//! # struct Button { mode: Mode }
//! # impl Button {
//! /// Sets the animation mode for this widget.
//! pub fn animation(mut self, mode: impl Into<Mode>) -> Self {
//! self.mode = mode.into();
//! self
//! }
//! # }
//! ```
//! 3. Add an `AnimatedState<Status, Style>` field to your widget's state. For example,
//! a button state might look like this:
//! ```no_run
//! # use iced_anim::AnimatedState;
//! # type Status = iced_widget::button::Status;
//! # type Style = iced_widget::button::Style;
//! #[derive(Debug)]
//! struct State {
//! is_pressed: bool,
//! animated_state: AnimatedState<Status, Style>,
//! }
//! ```
//! 4. Update [`iced::advanced::Widget::state`] to get the initial status, then pass that status
//! and animation mode into [`AnimatedState::new`] to create the animated state.
//! 5. Update [`iced::advanced::Widget::diff`] to call call [`AnimatedState::diff`] if the mode
//! has changed externally.
//! ```ignore
//! fn diff(&self, tree: &mut Tree) {
//! // Diff the animated state with a potentially new animation mode.
//! let state = tree.state.downcast_mut::<State>();
//! state.animated_state.diff(self.animation);
//! // Diff the rest of your widget state as necessary, e.g.
//! tree.diff_children(std::slice::from_ref(&self.content));
//! }
//! ```
//! 6. Update [`iced::advanced::Widget::draw`] to get the current style from the animated state
//! instead of manually calculating the style on each draw. Use [`AnimatedState::current_style`]
//! and pass in a callback to generate the style based on the theme and status, and it'll return
//! a reference to the latest animated style. The inner animated style will be updated if the
//! closure produces a style different from the current target.
//! 7. Update [`iced::advanced::Widget::on_event`] to call [`AnimatedState::needs_redraw`] to
//! determine if the widget needs to redraw. If a redraw is needed, then use the shell to
//! request a redraw on the next frame. This may vary based on how your widget, but it will
//! generally look like this:
//! ```ignore
//! # use iced::window;
//! // Redraw anytime the status changes and would trigger a style change.
//! let state = tree.state.downcast_mut::<State>();
//! let status = self.get_status(&state, cursor, layout);
//! let needs_redraw = state.animated_state.needs_redraw(status);
//!
//! if needs_redraw {
//! shell.request_redraw(window::RedrawRequest::NextFrame);
//! }
//! ```
//! 8. Finally, ensure your widget handles [`iced::window::Event::RedrawRequested`] events by
//! calling [`AnimatedState::tick`] to update the animated value with the current time. This
//! is how the animated state can update the value over time.
use ;
use crate::;
/// Helps manage animating values for widgets.
///
/// This maintains the current animated value for a widget, which depends on the `status`.
/// - `Status`: The status of the widget which affects some `Value`, e.g. `button::Status`.
/// - `Value`: The value that will be animated, e.g. `button::Style`.