ferroui_base/rendering/composition/animations/
expression_animation.rs1use super::{
2 CompositionAnimation, ExpressionAnimationInstance, ICompositionAnimation,
3 ICompositionAnimationBase,
4};
5use crate::rendering::composition::expressions::{Expression, ExpressionParser, ExpressionVariant};
6use crate::rendering::composition::server::ServerObjectId;
7use crate::rendering::composition::{AsCompositionObject, CompositionObject, Compositor};
8use std::cell::RefCell;
9use std::ops::Deref;
10use std::rc::Rc;
11
12pub struct ExpressionAnimation {
21 base: CompositionAnimation,
22 expression: RefCell<Option<String>>,
23 parsed_expression: RefCell<Option<std::sync::Arc<Expression>>>,
24}
25
26impl Deref for ExpressionAnimation {
27 type Target = CompositionAnimation;
28
29 fn deref(&self) -> &CompositionAnimation {
30 &self.base
31 }
32}
33
34impl ExpressionAnimation {
35 pub(crate) fn new(compositor: &Rc<Compositor>) -> Rc<ExpressionAnimation> {
36 Rc::new(ExpressionAnimation {
37 base: CompositionAnimation::new(compositor),
38 expression: RefCell::new(None),
39 parsed_expression: RefCell::new(None),
40 })
41 }
42
43 pub fn expression(&self) -> Option<String> {
50 self.expression.borrow().clone()
51 }
52
53 pub fn set_expression(&self, value: Option<String>) {
54 *self.expression.borrow_mut() = value;
55 *self.parsed_expression.borrow_mut() = None;
56 }
57
58 fn parsed_expression(&self) -> std::sync::Arc<Expression> {
61 if let Some(parsed) = self.parsed_expression.borrow().clone() {
62 return parsed;
63 }
64 let source = self.expression.borrow().clone().unwrap_or_default();
65 let parsed = match ExpressionParser::parse(&source) {
66 Ok(parsed) => std::sync::Arc::new(parsed),
67 Err(error) => panic!("{error}"),
68 };
69 *self.parsed_expression.borrow_mut() = Some(parsed.clone());
70 parsed
71 }
72}
73
74impl ICompositionAnimationBase for ExpressionAnimation {
75 fn as_composition_animation(&self) -> Option<&dyn ICompositionAnimation> {
76 Some(self)
77 }
78}
79
80impl ICompositionAnimation for ExpressionAnimation {
81 fn target(&self) -> Option<String> {
82 self.base.target()
83 }
84
85 fn create_instance(
86 &self,
87 target_object: ServerObjectId,
88 final_value: Option<ExpressionVariant>,
89 ) -> super::AnimationInstanceFactory {
90 let expression = self.parsed_expression();
91 let parameters = self.create_snapshot_source();
92 super::AnimationInstanceFactory::new(move || {
93 ExpressionAnimationInstance::new(expression, target_object, final_value, Rc::new(parameters.build()))
94 })
95 }
96}
97
98impl AsCompositionObject for ExpressionAnimation {
99 fn as_composition_object(&self) -> &CompositionObject {
100 self.base.object()
101 }
102
103 fn composition_type_name(&self) -> &'static str {
104 "ExpressionAnimation"
105 }
106}