1use iced_native::{widget, Element, Length, Padding};
2
3use crate::keyframes::{as_f32, get_length, Repeat};
4use crate::timeline::Frame;
5use crate::{Ease, Linear, MovementType};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct Id(iced_native::widget::Id);
10
11impl Id {
12 pub fn new(id: impl Into<std::borrow::Cow<'static, str>>) -> Self {
14 Self(widget::Id::new(id))
15 }
16
17 pub fn unique() -> Self {
21 Self(widget::Id::unique())
22 }
23
24 pub fn into_chain(self) -> Chain {
26 Chain::new(self)
27 }
28
29 pub fn into_chain_with_children(self, children: Vec<Button>) -> Chain {
31 Chain::with_children(self, children)
32 }
33
34 pub fn as_widget<'a, Message, Renderer>(
36 self,
37 timeline: &crate::Timeline,
38 content: impl Into<Element<'a, Message, Renderer>>,
39 ) -> widget::Button<'a, Message, Renderer>
40 where
41 Renderer: iced_native::Renderer,
42 Renderer::Theme: widget::button::StyleSheet,
43 {
44 Button::as_widget(self, timeline, content)
45 }
46}
47
48impl From<Id> for widget::Id {
49 fn from(id: Id) -> Self {
50 id.0
51 }
52}
53
54#[derive(Debug)]
55pub struct Chain {
56 id: Id,
57 links: Vec<Button>,
58 repeat: Repeat,
59}
60
61impl Chain {
62 pub fn new(id: Id) -> Self {
63 Chain {
64 id,
65 links: Vec::new(),
66 repeat: Repeat::Never,
67 }
68 }
69
70 pub fn with_children(id: Id, children: Vec<Button>) -> Self {
71 Chain {
72 id,
73 links: children,
74 repeat: Repeat::Never,
75 }
76 }
77
78 pub fn link(mut self, button: Button) -> Self {
79 self.links.push(button);
80 self
81 }
82
83 pub fn loop_forever(mut self) -> Self {
84 self.repeat = Repeat::Forever;
85 self
86 }
87
88 pub fn loop_once(mut self) -> Self {
89 self.repeat = Repeat::Never;
90 self
91 }
92}
93
94impl From<Chain> for crate::timeline::Chain {
95 fn from(chain: Chain) -> Self {
96 crate::timeline::Chain::new(
97 chain.id.into(),
98 chain.repeat,
99 chain
100 .links
101 .into_iter()
102 .map(|b| b.into())
103 .collect::<Vec<_>>(),
104 )
105 }
106}
107
108#[must_use = "Keyframes are intended to be used in an animation chain."]
109#[derive(Debug, Clone, Copy)]
110pub struct Button {
111 at: MovementType,
112 ease: Ease,
113 width: Option<Length>,
114 height: Option<Length>,
115 padding: Option<Padding>,
116 is_eager: bool,
117}
118
119impl Button {
120 pub fn new(at: impl Into<MovementType>) -> Button {
121 let at = at.into();
122 Button {
123 at,
124 ease: Linear::InOut.into(),
125 width: None,
126 height: None,
127 padding: None,
128 is_eager: true,
129 }
130 }
131
132 pub fn lazy(at: impl Into<MovementType>) -> Button {
133 let at = at.into();
134 Button {
135 at,
136 ease: Linear::InOut.into(),
137 width: None,
138 height: None,
139 padding: None,
140 is_eager: false,
141 }
142 }
143
144 pub fn as_widget<'a, Message, Renderer>(
145 id: Id,
146 timeline: &crate::Timeline,
147 content: impl Into<Element<'a, Message, Renderer>>,
148 ) -> widget::Button<'a, Message, Renderer>
149 where
150 Renderer: iced_native::Renderer,
151 Renderer::Theme: widget::button::StyleSheet,
152 {
153 let id: widget::Id = id.into();
154
155 widget::Button::new(content)
156 .width(get_length(&id, timeline, 0, Length::Shrink))
157 .height(get_length(&id, timeline, 1, Length::Shrink))
158 .padding([
159 timeline.get(&id, 2).map(|m| m.value).unwrap_or(5.0),
160 timeline.get(&id, 3).map(|m| m.value).unwrap_or(5.0),
161 timeline.get(&id, 4).map(|m| m.value).unwrap_or(5.0),
162 timeline.get(&id, 5).map(|m| m.value).unwrap_or(5.0),
163 ])
164 }
165
166 pub fn width(mut self, width: Length) -> Self {
167 self.width = Some(width);
168 self
169 }
170
171 pub fn height(mut self, height: Length) -> Self {
172 self.height = Some(height);
173 self
174 }
175
176 pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
177 self.padding = Some(padding.into());
178 self
179 }
180
181 pub fn ease<E: Into<Ease>>(mut self, ease: E) -> Self {
182 self.ease = ease.into();
183 self
184 }
185}
186
187#[rustfmt::skip]
188impl From<Button> for Vec<Option<Frame>> {
189 fn from(button: Button) -> Vec<Option<Frame>> {
190 if button.is_eager {
191 vec![as_f32(button.width).map(|w| Frame::eager(button.at, w, button.ease)), as_f32(button.height).map(|h| Frame::eager(button.at, h, button.ease)), button.padding.map(|p| Frame::eager(button.at, p.top, button.ease)), button.padding.map(|p| Frame::eager(button.at, p.right, button.ease)), button.padding.map(|p| Frame::eager(button.at, p.bottom, button.ease)), button.padding.map(|p| Frame::eager(button.at, p.left, button.ease)), ]
198 } else {
199 vec![Some(Frame::lazy(button.at, 0., button.ease)), Some(Frame::lazy(button.at, 0., button.ease)), Some(Frame::lazy(button.at, 5., button.ease)), Some(Frame::lazy(button.at, 5., button.ease)), Some(Frame::lazy(button.at, 5., button.ease)), Some(Frame::lazy(button.at, 5., button.ease)), ]
206 }
207 }
208}