ferroui_base/media/
geometry_collection.rs1use crate::media::{Geometry, GeometryGroup, MediaCollection, ResetBehavior};
2use crate::reactive::IDisposable;
3use crate::{Ref, WeakRef};
4use std::cell::RefCell;
5use std::ops::Deref;
6use std::rc::Rc;
7
8type ChildSubscriptions = Rc<RefCell<Vec<(Ref<Geometry>, Rc<dyn IDisposable>)>>>;
9
10#[derive(Clone)]
15pub struct GeometryCollection {
16 list: MediaCollection<Ref<Geometry>>,
17 parent: Rc<RefCell<Option<WeakRef<GeometryGroup>>>>,
18}
19
20impl PartialEq for GeometryCollection {
21 #[inline]
22 fn eq(&self, other: &Self) -> bool {
23 self.list == other.list
24 }
25}
26
27impl Default for GeometryCollection {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl Deref for GeometryCollection {
34 type Target = MediaCollection<Ref<Geometry>>;
35 #[inline]
36 fn deref(&self) -> &Self::Target {
37 &self.list
38 }
39}
40
41impl FromIterator<Ref<Geometry>> for GeometryCollection {
42 fn from_iter<I: IntoIterator<Item = Ref<Geometry>>>(iter: I) -> Self {
43 Self::from_items(iter)
44 }
45}
46
47impl GeometryCollection {
48 pub fn new() -> Self {
50 Self::from_items([])
51 }
52
53 pub fn from_items(items: impl IntoIterator<Item = Ref<Geometry>>) -> Self {
55 let list = MediaCollection::from_items(items);
56 list.set_reset_behavior(ResetBehavior::Remove);
57 let parent: Rc<RefCell<Option<WeakRef<GeometryGroup>>>> = Rc::new(RefCell::new(None));
58 let subscriptions: ChildSubscriptions = Rc::new(RefCell::new(Vec::new()));
59
60 let invalidate_parent = {
61 let parent = parent.clone();
62 move || {
63 let parent = parent.borrow().as_ref().and_then(WeakRef::upgrade);
64 if let Some(parent) = parent {
65 parent.invalidate();
66 }
67 }
68 };
69
70 let subscriptions_added = subscriptions.clone();
71 let (invalidate_added, invalidate_removed) = (invalidate_parent.clone(), invalidate_parent);
72 let _ = list.for_each_item(
74 move |_, x: &Ref<Geometry>| {
75 let child_changed = invalidate_added.clone();
76 let subscription = x.changed(child_changed);
77 subscriptions_added.borrow_mut().push((x.clone(), subscription));
78 invalidate_added();
79 },
80 move |_, x: &Ref<Geometry>| {
81 let position = subscriptions.borrow().iter().position(|(g, _)| g.ptr_eq(x));
82 if let Some(position) = position {
83 let (_, subscription) = subscriptions.borrow_mut().remove(position);
84 subscription.dispose();
85 }
86 invalidate_removed();
87 },
88 || panic!("Collection reset is not supported."),
89 );
90
91 Self { list, parent }
92 }
93
94 pub fn parent(&self) -> Option<Ref<GeometryGroup>> {
96 self.parent.borrow().as_ref().and_then(WeakRef::upgrade)
97 }
98
99 pub fn set_parent(&self, value: Option<&Ref<GeometryGroup>>) {
101 *self.parent.borrow_mut() = value.map(Ref::downgrade);
102 }
103}