1use crate::core::{AnimationError, MotionData, TypedAnimation, TypedFrame};
3use gpui_kit::{App, Window};
4
5use std::{
6 ops::{Deref, DerefMut},
7 time::Duration,
8};
9
10#[derive(Debug)]
12pub struct TypedState<T, const N: usize> {
13 inner: crate::core::TypedState<T, N>,
14 clock: crate::Clock,
15}
16
17impl<T, const N: usize> Deref for TypedState<T, N> {
18 type Target = crate::core::TypedState<T, N>;
19
20 fn deref(&self) -> &Self::Target {
21 &self.inner
22 }
23}
24
25impl<T, const N: usize> DerefMut for TypedState<T, N> {
26 fn deref_mut(&mut self) -> &mut Self::Target {
27 &mut self.inner
28 }
29}
30
31impl<T: MotionData<N>, const N: usize> TypedState<T, N> {
32 pub fn new(value: T) -> Self {
34 Self {
35 inner: crate::core::TypedState::new(value),
36 clock: Default::default(),
37 }
38 }
39
40 pub fn now(&self, cx: &App) -> Duration {
42 self.clock.now(cx)
43 }
44
45 pub fn frame(
47 &mut self,
48 clip: &TypedAnimation<T, N>,
49 window: &mut Window,
50 cx: &App,
51 ) -> TypedFrame<T> {
52 let now = self.clock.tick(cx);
53 let frame = self.inner.sample(clip, now, cx.reduce_motion());
54
55 if frame.is_animating() {
56 window.request_animation_frame();
57 }
58
59 frame
60 }
61}
62
63#[derive(Debug, Default)]
65pub struct TypedTimeline {
66 inner: crate::core::TypedTimeline,
67 clock: crate::Clock,
68}
69
70impl Deref for TypedTimeline {
71 type Target = crate::core::TypedTimeline;
72
73 fn deref(&self) -> &Self::Target {
74 &self.inner
75 }
76}
77
78impl DerefMut for TypedTimeline {
79 fn deref_mut(&mut self) -> &mut Self::Target {
80 &mut self.inner
81 }
82}
83
84impl TypedTimeline {
85 pub fn now(&self, cx: &App) -> Duration {
87 self.clock.now(cx)
88 }
89
90 pub fn frame(&mut self, window: &mut Window, cx: &App) {
92 self.inner.sample(self.clock.tick(cx), cx.reduce_motion());
93
94 if self.inner.is_animating() {
95 window.request_animation_frame();
96 }
97 }
98
99 pub fn speed(&mut self, speed: f64, cx: &App) -> Result<(), AnimationError> {
101 self.inner.set_speed(speed, self.now(cx))
102 }
103}