maycoon_widgets/
animator.rs

1use maycoon_core::app::context::AppContext;
2use maycoon_core::app::info::AppInfo;
3use maycoon_core::app::update::Update;
4use maycoon_core::layout::{LayoutNode, StyleNode};
5use maycoon_core::vg::Scene;
6use maycoon_core::widget::Widget;
7use maycoon_theme::id::WidgetId;
8use maycoon_theme::theme::Theme;
9use std::time::{Duration, Instant};
10
11/// A widget that animates another widget using an animation function.
12pub struct Animator<W: Widget, A: Fn(&mut W, f32) -> Update> {
13    start: Instant,
14    duration: Duration,
15    widget: W,
16    animation: A,
17}
18
19impl<W: Widget, A: Fn(&mut W, f32) -> Update> Animator<W, A> {
20    /// Creates a new animator widget with the given duration, child widget and animation function.
21    ///
22    /// The animation function is called with a value between `0.0` and `1.0` based on the elapsed time since the start of the animation
23    /// and the total duration of the animation.
24    pub fn new(duration: Duration, widget: W, animation: A) -> Self {
25        Self {
26            start: Instant::now(),
27            duration,
28            widget,
29            animation,
30        }
31    }
32}
33
34impl<W: Widget, A: Fn(&mut W, f32) -> Update> Widget for Animator<W, A> {
35    fn render(
36        &mut self,
37        scene: &mut Scene,
38        theme: &mut dyn Theme,
39        layout_node: &LayoutNode,
40        info: &AppInfo,
41        context: AppContext,
42    ) {
43        self.widget.render(scene, theme, layout_node, info, context);
44    }
45
46    fn layout_style(&self) -> StyleNode {
47        self.widget.layout_style()
48    }
49
50    fn update(&mut self, layout: &LayoutNode, context: AppContext, info: &AppInfo) -> Update {
51        let elapsed = self.start.elapsed();
52
53        let mut update = self.widget.update(layout, context, info);
54
55        if elapsed < self.duration {
56            let f = elapsed.as_secs_f32() / self.duration.as_secs_f32();
57
58            update.insert((self.animation)(&mut self.widget, f));
59        }
60
61        update
62    }
63
64    fn widget_id(&self) -> WidgetId {
65        WidgetId::new("maycoon-widgets", "Animator")
66    }
67}