use super::{
CompositionAnimation, ExpressionAnimationInstance, ICompositionAnimation,
ICompositionAnimationBase,
};
use crate::rendering::composition::expressions::{Expression, ExpressionParser, ExpressionVariant};
use crate::rendering::composition::server::ServerObjectId;
use crate::rendering::composition::{AsCompositionObject, CompositionObject, Compositor};
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
pub struct ExpressionAnimation {
base: CompositionAnimation,
expression: RefCell<Option<String>>,
parsed_expression: RefCell<Option<std::sync::Arc<Expression>>>,
}
impl Deref for ExpressionAnimation {
type Target = CompositionAnimation;
fn deref(&self) -> &CompositionAnimation {
&self.base
}
}
impl ExpressionAnimation {
pub(crate) fn new(compositor: &Rc<Compositor>) -> Rc<ExpressionAnimation> {
Rc::new(ExpressionAnimation {
base: CompositionAnimation::new(compositor),
expression: RefCell::new(None),
parsed_expression: RefCell::new(None),
})
}
pub fn expression(&self) -> Option<String> {
self.expression.borrow().clone()
}
pub fn set_expression(&self, value: Option<String>) {
*self.expression.borrow_mut() = value;
*self.parsed_expression.borrow_mut() = None;
}
fn parsed_expression(&self) -> std::sync::Arc<Expression> {
if let Some(parsed) = self.parsed_expression.borrow().clone() {
return parsed;
}
let source = self.expression.borrow().clone().unwrap_or_default();
let parsed = match ExpressionParser::parse(&source) {
Ok(parsed) => std::sync::Arc::new(parsed),
Err(error) => panic!("{error}"),
};
*self.parsed_expression.borrow_mut() = Some(parsed.clone());
parsed
}
}
impl ICompositionAnimationBase for ExpressionAnimation {
fn as_composition_animation(&self) -> Option<&dyn ICompositionAnimation> {
Some(self)
}
}
impl ICompositionAnimation for ExpressionAnimation {
fn target(&self) -> Option<String> {
self.base.target()
}
fn create_instance(
&self,
target_object: ServerObjectId,
final_value: Option<ExpressionVariant>,
) -> super::AnimationInstanceFactory {
let expression = self.parsed_expression();
let parameters = self.create_snapshot_source();
super::AnimationInstanceFactory::new(move || {
ExpressionAnimationInstance::new(expression, target_object, final_value, Rc::new(parameters.build()))
})
}
}
impl AsCompositionObject for ExpressionAnimation {
fn as_composition_object(&self) -> &CompositionObject {
self.base.object()
}
fn composition_type_name(&self) -> &'static str {
"ExpressionAnimation"
}
}