1use gpui::prelude::*;
14use gpui::{div, AnyElement, App, ElementId, Entity, IntoElement, Window};
15
16use super::{Animator, Clip, Motion, Motioned, Sequence};
17use crate::devtools::{Probed, ProbedAny};
18use crate::transition::TransitionKind;
19
20#[derive(IntoElement)]
22pub struct Animated {
23 id: ElementId,
24 clip: Clip,
25 animator: Option<Entity<Animator>>,
26 child: Option<AnyElement>,
27}
28
29impl Animated {
30 pub fn new(id: impl Into<ElementId>) -> Self {
31 Animated {
32 id: id.into(),
33 clip: Clip::default(),
34 animator: None,
35 child: None,
36 }
37 }
38
39 pub fn motion(mut self, motion: Motion) -> Self {
41 self.clip = Clip::Motion(motion);
42 self
43 }
44
45 pub fn sequence(mut self, sequence: Sequence) -> Self {
47 self.clip = Clip::Sequence(sequence);
48 self
49 }
50
51 pub fn clip(mut self, clip: impl Into<Clip>) -> Self {
52 self.clip = clip.into();
53 self
54 }
55
56 pub fn enter(self, kind: TransitionKind) -> Self {
58 self.motion(Motion::enter(kind))
59 }
60
61 pub fn animator(mut self, animator: &Entity<Animator>) -> Self {
64 self.animator = Some(animator.clone());
65 self
66 }
67
68 pub fn child(mut self, child: impl IntoElement) -> Self {
69 self.child = Some(child.into_any_element());
70 self
71 }
72}
73
74impl RenderOnce for Animated {
75 fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
76 let child = self.child.unwrap_or_else(|| div().into_any_element());
77
78 if let Some(animator) = self.animator {
79 let frame = animator.read(cx).frame(window);
80 let progress = frame.progress;
81 return frame
82 .apply(div())
83 .child(child)
84 .probe("Animated")
85 .attr_with("progress", || format!("{progress:.2}"))
86 .into_any_element();
87 }
88
89 div()
90 .child(child)
91 .animate(self.id, self.clip)
92 .probe_any("Animated")
93 .into_any_element()
94 }
95}