ferroui_base/rendering/composition/server/
server_composition_property_set.rs1use super::{
2 CompositionProperty, IAnimatedServerObject, IServerAnimatedPropertyHost, IServerObject, IServerPropertyHost,
3 ServerCompositionSurfaceChanged, ServerCompositor, ServerObject, ServerValueChange,
4};
5use crate::rendering::composition::animations::IAnimationInstance;
6use crate::rendering::composition::animations::AnimationInstanceFactory;
7use crate::rendering::composition::expressions::ExpressionVariant;
8use crate::rendering::composition::transport::BatchStreamReader;
9use std::any::Any;
10use std::cell::RefCell;
11use std::collections::HashMap;
12use std::rc::{Rc, Weak};
13use std::time::Duration;
14
15#[derive(Default)]
18pub(crate) struct PropertySetChanges {
19 pub(crate) values: Vec<(String, ExpressionVariant)>,
20 pub(crate) animations: Vec<(String, AnimationInstanceFactory)>,
21}
22
23pub struct ServerCompositionPropertySet {
33 object: ServerObject,
34 values: RefCell<HashMap<i32, ExpressionVariant>>,
35 changed: ServerCompositionSurfaceChanged,
39}
40
41impl ServerCompositionPropertySet {
42 pub fn new(compositor: &Rc<ServerCompositor>) -> Rc<ServerCompositionPropertySet> {
45 let set = Rc::new_cyclic(|this: &Weak<ServerCompositionPropertySet>| ServerCompositionPropertySet {
46 object: ServerObject::new(compositor, this.clone() as Weak<dyn IAnimatedServerObject>),
47 values: RefCell::new(HashMap::new()),
48 changed: ServerCompositionSurfaceChanged::new(),
49 });
50 set.object.activate();
51 set
52 }
53
54 pub fn get_value(&self, name: &str) -> ExpressionVariant {
57 self.object.get_property(name)
58 }
59
60 fn property(name: &str) -> &'static CompositionProperty {
61 CompositionProperty::dynamic(name)
62 }
63
64 pub fn changed(&self) -> &ServerCompositionSurfaceChanged {
68 &self.changed
69 }
70}
71
72
73impl IServerObject for ServerCompositionPropertySet {
74 fn deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration) {
75 let Some(changes) = reader.read_value::<PropertySetChanges>() else { return };
76 for (name, value) in changes.values {
77 let property = Self::property(&name);
78 self.values.borrow_mut().insert(property.id(), value);
79 self.object.remove_animation_for_property(property);
82 }
83 for (name, factory) in changes.animations {
84 let property = Self::property(&name);
85 let current = self.values.borrow().get(&property.id()).copied().unwrap_or_default();
86 self.object.set_animated_value(property, current, committed_at, factory.create());
87 }
88 self.changed.invoke();
89 }
90
91 fn as_animated(self: Rc<Self>) -> Option<Rc<dyn IAnimatedServerObject>> {
92 Some(self)
93 }
94
95 fn as_any(&self) -> &dyn Any {
96 self
97 }
98
99 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
100 self
101 }
102}
103
104impl IServerPropertyHost for ServerCompositionPropertySet {
105 fn server_compositor(&self) -> Option<Rc<ServerCompositor>> {
106 self.object.compositor()
107 }
108
109 fn set_value(&self, property: &'static CompositionProperty, change: ServerValueChange<'_>) {
110 self.object.set_value(property, change);
111 }
112}
113
114impl IServerAnimatedPropertyHost for ServerCompositionPropertySet {
115 fn set_animated_value(
116 &self,
117 property: &'static CompositionProperty,
118 current_value: ExpressionVariant,
119 committed_at: Duration,
120 animation: Rc<dyn IAnimationInstance>,
121 ) {
122 self.object.set_animated_value(property, current_value, committed_at, animation);
123 }
124
125 fn remove_animation_for_property(&self, property: &'static CompositionProperty) {
126 self.object.remove_animation_for_property(property);
127 }
128
129 fn notify_animated_value_changed(&self, _property: &'static CompositionProperty) {
130 self.changed.invoke();
131 }
132}
133
134impl IAnimatedServerObject for ServerCompositionPropertySet {
135 fn server_object(&self) -> &ServerObject {
136 &self.object
137 }
138
139 fn get_composition_property(&self, field_name: &str) -> Option<&'static CompositionProperty> {
142 Some(Self::property(field_name))
143 }
144
145 fn as_server_object_dyn(&self) -> &dyn IServerObject {
146 self
147 }
148
149 fn read_property_variant(&self, property: &'static CompositionProperty) -> ExpressionVariant {
150 self.values.borrow().get(&property.id()).copied().unwrap_or_default()
151 }
152
153 fn write_property_variant(&self, property: &'static CompositionProperty, value: ExpressionVariant) {
154 self.values.borrow_mut().insert(property.id(), value);
155 }
156}