use super::{
CompositionProperty, IAnimatedServerObject, IServerAnimatedPropertyHost, IServerObject, IServerPropertyHost,
ServerCompositionSurfaceChanged, ServerCompositor, ServerObject, ServerValueChange,
};
use crate::rendering::composition::animations::IAnimationInstance;
use crate::rendering::composition::animations::AnimationInstanceFactory;
use crate::rendering::composition::expressions::ExpressionVariant;
use crate::rendering::composition::transport::BatchStreamReader;
use std::any::Any;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::{Rc, Weak};
use std::time::Duration;
#[derive(Default)]
pub(crate) struct PropertySetChanges {
pub(crate) values: Vec<(String, ExpressionVariant)>,
pub(crate) animations: Vec<(String, AnimationInstanceFactory)>,
}
pub struct ServerCompositionPropertySet {
object: ServerObject,
values: RefCell<HashMap<i32, ExpressionVariant>>,
changed: ServerCompositionSurfaceChanged,
}
impl ServerCompositionPropertySet {
pub fn new(compositor: &Rc<ServerCompositor>) -> Rc<ServerCompositionPropertySet> {
let set = Rc::new_cyclic(|this: &Weak<ServerCompositionPropertySet>| ServerCompositionPropertySet {
object: ServerObject::new(compositor, this.clone() as Weak<dyn IAnimatedServerObject>),
values: RefCell::new(HashMap::new()),
changed: ServerCompositionSurfaceChanged::new(),
});
set.object.activate();
set
}
pub fn get_value(&self, name: &str) -> ExpressionVariant {
self.object.get_property(name)
}
fn property(name: &str) -> &'static CompositionProperty {
CompositionProperty::dynamic(name)
}
pub fn changed(&self) -> &ServerCompositionSurfaceChanged {
&self.changed
}
}
impl IServerObject for ServerCompositionPropertySet {
fn deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration) {
let Some(changes) = reader.read_value::<PropertySetChanges>() else { return };
for (name, value) in changes.values {
let property = Self::property(&name);
self.values.borrow_mut().insert(property.id(), value);
self.object.remove_animation_for_property(property);
}
for (name, factory) in changes.animations {
let property = Self::property(&name);
let current = self.values.borrow().get(&property.id()).copied().unwrap_or_default();
self.object.set_animated_value(property, current, committed_at, factory.create());
}
self.changed.invoke();
}
fn as_animated(self: Rc<Self>) -> Option<Rc<dyn IAnimatedServerObject>> {
Some(self)
}
fn as_any(&self) -> &dyn Any {
self
}
fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
self
}
}
impl IServerPropertyHost for ServerCompositionPropertySet {
fn server_compositor(&self) -> Option<Rc<ServerCompositor>> {
self.object.compositor()
}
fn set_value(&self, property: &'static CompositionProperty, change: ServerValueChange<'_>) {
self.object.set_value(property, change);
}
}
impl IServerAnimatedPropertyHost for ServerCompositionPropertySet {
fn set_animated_value(
&self,
property: &'static CompositionProperty,
current_value: ExpressionVariant,
committed_at: Duration,
animation: Rc<dyn IAnimationInstance>,
) {
self.object.set_animated_value(property, current_value, committed_at, animation);
}
fn remove_animation_for_property(&self, property: &'static CompositionProperty) {
self.object.remove_animation_for_property(property);
}
fn notify_animated_value_changed(&self, _property: &'static CompositionProperty) {
self.changed.invoke();
}
}
impl IAnimatedServerObject for ServerCompositionPropertySet {
fn server_object(&self) -> &ServerObject {
&self.object
}
fn get_composition_property(&self, field_name: &str) -> Option<&'static CompositionProperty> {
Some(Self::property(field_name))
}
fn as_server_object_dyn(&self) -> &dyn IServerObject {
self
}
fn read_property_variant(&self, property: &'static CompositionProperty) -> ExpressionVariant {
self.values.borrow().get(&property.id()).copied().unwrap_or_default()
}
fn write_property_variant(&self, property: &'static CompositionProperty, value: ExpressionVariant) {
self.values.borrow_mut().insert(property.id(), value);
}
}