ferroui_base/rendering/composition/
visual_collection.rs1use super::generated::{CompositionVisualCollectionHooks, CompositionVisualCollectionProps};
2use super::server::{CompositionProperty, ServerObjectId};
3use super::transport::{BatchStreamWriter, IRegisterForSerialization};
4use super::{
5 AsCompositionObject, CompositionObject, ICompositionObjectAnimations, CompositionVisual, Compositor, ICompositionObject, ICompositionObjectHost,
6 ICompositorSerializable, PendingAnimations,
7};
8use crate::rendering::composition::animations::{ICompositionAnimation, ICompositionAnimationBase};
9use crate::rendering::composition::expressions::ExpressionVariant;
10use std::any::Any;
11use std::rc::{Rc, Weak};
12
13pub struct CompositionVisualCollection {
15 this: Weak<CompositionVisualCollection>,
16 object: CompositionObject,
17 owner: Weak<CompositionVisual>,
18 props: CompositionVisualCollectionProps<CompositionVisual>,
19}
20
21impl CompositionVisualCollection {
22 pub(crate) fn new(
23 compositor: &Rc<Compositor>,
24 parent: Weak<CompositionVisual>,
25 server: ServerObjectId,
26 ) -> Rc<CompositionVisualCollection> {
27 let collection = Rc::new_cyclic(|this: &Weak<CompositionVisualCollection>| CompositionVisualCollection {
28 this: this.clone(),
29 object: CompositionObject::new(compositor, Some(server)),
30 owner: parent,
31 props: CompositionVisualCollectionProps::new(),
32 });
33 collection.props.initialize_defaults(&*collection);
34 collection
35 }
36
37 fn owner(&self) -> Option<Rc<CompositionVisual>> {
38 self.owner.upgrade()
39 }
40
41 pub fn insert_above(&self, new_child: Rc<CompositionVisual>, sibling: &Rc<CompositionVisual>) {
42 let Some(idx) = self.props.index_of(sibling) else { panic!("the sibling is not in the collection") };
43 self.insert(idx + 1, new_child);
44 }
45
46 pub fn insert_below(&self, new_child: Rc<CompositionVisual>, sibling: &Rc<CompositionVisual>) {
47 let Some(idx) = self.props.index_of(sibling) else { panic!("the sibling is not in the collection") };
48 self.insert(idx, new_child);
49 }
50
51 pub fn insert_at_top(&self, new_child: Rc<CompositionVisual>) {
52 self.insert(self.props.count(), new_child);
53 }
54
55 pub fn insert_at_bottom(&self, new_child: Rc<CompositionVisual>) {
56 self.insert(0, new_child);
57 }
58
59 pub fn remove_all(&self) {
60 self.clear();
61 }
62
63 pub fn items(&self) -> Vec<Rc<CompositionVisual>> {
67 self.props.items()
68 }
69
70 pub fn add(&self, item: Rc<CompositionVisual>) {
71 self.props.add(self, item);
72 }
73
74 pub fn clear(&self) {
75 self.props.clear(self);
76 }
77
78 pub fn contains(&self, item: &Rc<CompositionVisual>) -> bool {
79 self.props.contains(item)
80 }
81
82 pub fn remove(&self, item: &Rc<CompositionVisual>) -> bool {
83 self.props.remove(self, item)
84 }
85
86 pub fn count(&self) -> usize {
87 self.props.count()
88 }
89
90 pub fn is_read_only(&self) -> bool {
91 self.props.is_read_only()
92 }
93
94 pub fn index_of(&self, item: &Rc<CompositionVisual>) -> Option<usize> {
95 self.props.index_of(item)
96 }
97
98 pub fn insert(&self, index: usize, item: Rc<CompositionVisual>) {
99 self.props.insert(self, index, item);
100 }
101
102 pub fn remove_at(&self, index: usize) {
103 self.props.remove_at(self, index);
104 }
105
106 pub fn get(&self, index: usize) -> Rc<CompositionVisual> {
107 self.props.get(index)
108 }
109
110 pub fn set(&self, index: usize, value: Rc<CompositionVisual>) {
111 self.props.set(self, index, value);
112 }
113}
114
115impl CompositionVisualCollectionHooks<CompositionVisual> for CompositionVisualCollection {
116 fn on_added(&self, item: &Rc<CompositionVisual>) {
117 let owner = self.owner();
118 item.set_parent(owner.clone());
119 if let Some(owner) = owner {
120 owner.add_hit_test_child(item);
121 }
122 }
123
124 fn on_before_replace(&self, old_item: &Rc<CompositionVisual>, new_item: &Rc<CompositionVisual>) {
125 if !Rc::ptr_eq(old_item, new_item) {
126 self.on_before_added(new_item);
127 }
128 }
129
130 fn on_replace(&self, old_item: &Rc<CompositionVisual>, new_item: &Rc<CompositionVisual>) {
131 if !Rc::ptr_eq(old_item, new_item) {
132 self.on_removed(old_item);
133 self.on_added(new_item);
134 }
135 }
136
137 fn on_removed(&self, item: &Rc<CompositionVisual>) {
138 item.set_parent(None);
139 if let Some(owner) = self.owner() {
140 owner.remove_hit_test_child(item);
141 }
142 }
143
144 fn on_before_clear(&self) {
145 for item in self.items() {
146 item.set_parent(None);
147 }
148 }
149
150 fn on_clear(&self) {
151 if let Some(owner) = self.owner() {
152 owner.clear_hit_test_children();
153 }
154 }
155
156 fn on_before_added(&self, item: &Rc<CompositionVisual>) {
157 if item.parent().is_some() {
158 panic!("Visual already has a parent");
159 }
160 item.set_parent(self.owner());
161 }
162}
163
164impl IRegisterForSerialization for CompositionVisualCollection {
165 fn register_for_serialization(&self) {
166 self.object
167 .register_for_serialization(|| self.this.upgrade().map(|this| this as Rc<dyn ICompositorSerializable>));
168 }
169}
170
171impl ICompositionObjectHost for CompositionVisualCollection {
172 fn server(&self) -> ServerObjectId {
173 self.object.required_server()
174 }
175
176 fn pending_animations(&self) -> &PendingAnimations {
177 self.object.pending_animations()
178 }
179
180 fn implicit_animation(&self, property_name: &str) -> Option<Rc<dyn ICompositionAnimationBase>> {
181 self.object.implicit_animation(property_name)
182 }
183
184 fn start_animation_group(
185 &self,
186 grp: &Rc<dyn ICompositionAnimationBase>,
187 target: &str,
188 final_value: ExpressionVariant,
189 ) -> bool {
190 self.start_animation_group_for(&**grp, target, final_value)
191 }
192}
193
194impl ICompositionObjectAnimations for CompositionVisualCollection {
197 fn try_start_animation(
198 &self,
199 _property_name: &str,
200 _animation: &dyn ICompositionAnimation,
201 _final_value: Option<ExpressionVariant>,
202 ) -> bool {
203 false
204 }
205
206 fn get_composition_property(&self, property_name: &str) -> Option<&'static CompositionProperty> {
207 let _ = property_name;
208 None
209 }
210
211 fn composition_object(&self) -> &CompositionObject {
212 &self.object
213 }
214}
215
216impl AsCompositionObject for CompositionVisualCollection {
217 fn as_composition_object(&self) -> &CompositionObject {
218 &self.object
219 }
220
221 fn composition_type_name(&self) -> &'static str {
222 "CompositionVisualCollection"
223 }
224}
225
226impl ICompositionObject for CompositionVisualCollection {
227 fn server(&self) -> ServerObjectId {
228 self.object.required_server()
229 }
230
231 fn as_any(&self) -> &dyn Any {
232 self
233 }
234
235 fn into_any_rc(self: Rc<Self>) -> Rc<dyn Any> {
236 self
237 }
238}
239
240impl ICompositorSerializable for CompositionVisualCollection {
241 fn try_get_server(&self, c: &Compositor) -> Option<ServerObjectId> {
242 self.object.try_get_server(c)
243 }
244
245 fn serialize_changes(&self, c: &Compositor, writer: &mut BatchStreamWriter<'_>) {
246 self.object.begin_serialize_changes(c);
247 self.props.serialize_changes_core(self, writer);
248 }
249}