ferroui_diagnostics/diagnostics/view_models/
tree_node_collection.rs1use super::TreeNode;
4use ferroui_base::collections::{CollectionChangedHandler, FerroList, IFerroReadOnlyList};
5use ferroui_base::data::model::{CollectionChange, Event, INotifyCollectionChanged, INotifyPropertyChanged};
6use ferroui_base::{ferro_markup_type, BoxedValue};
7use ferroui_controls::{IItemsList, ItemsChangedHandler};
8use ferroui_treedatagrid_core::model_collection::{ModelCollection, ModelsChangedHandler};
9use std::any::Any;
10use std::cell::OnceCell;
11use std::rc::{Rc, Weak};
12
13pub trait TreeNodeCollectionImpl {
16 fn initialize(&self, this: &TreeNodeCollection, nodes: &FerroList<Rc<TreeNode>>);
20
21 fn dispose(&self, this: &TreeNodeCollection) {
25 this.base_dispose();
26 }
27}
28
29pub struct TreeNodeCollection {
38 this: Weak<TreeNodeCollection>,
39 owner: Weak<TreeNode>,
40 inner: OnceCell<FerroList<Rc<TreeNode>>>,
41 kind: Box<dyn TreeNodeCollectionImpl>,
42}
43
44struct EmptyTreeNodeCollection;
46
47impl TreeNodeCollectionImpl for EmptyTreeNodeCollection {
48 fn initialize(&self, _this: &TreeNodeCollection, _nodes: &FerroList<Rc<TreeNode>>) {}
49}
50
51ferroui_base::ferro_thread_local! {
52 static EMPTY: Rc<TreeNodeCollection> = TreeNodeCollection::new(Weak::new(), Box::new(EmptyTreeNodeCollection));
53}
54
55impl PartialEq for TreeNodeCollection {
56 fn eq(&self, other: &Self) -> bool {
57 std::ptr::eq(self, other)
58 }
59}
60
61impl TreeNodeCollection {
62 pub fn new(owner: Weak<TreeNode>, kind: Box<dyn TreeNodeCollectionImpl>) -> Rc<Self> {
65 Rc::new_cyclic(|this| Self { this: this.clone(), owner, inner: OnceCell::new(), kind })
66 }
67
68 pub(crate) fn to_rc(&self) -> Rc<TreeNodeCollection> {
70 self.this.upgrade().expect("the collection is alive while it is used")
71 }
72
73 pub fn empty() -> Rc<TreeNodeCollection> {
76 EMPTY.with(Rc::clone)
77 }
78
79 pub fn get(&self, index: usize) -> Rc<TreeNode> {
84 self.ensure_initialized().get(index)
85 }
86
87 pub fn count(&self) -> usize {
89 self.ensure_initialized().count()
90 }
91
92 pub fn owner(&self) -> Option<Rc<TreeNode>> {
95 self.owner.upgrade()
96 }
97
98 pub fn dispose(&self) {
100 self.kind.dispose(self);
101 }
102
103 pub fn base_dispose(&self) {
106 if let Some(inner) = self.inner.get() {
107 for node in inner.snapshot().iter() {
108 node.dispose();
109 }
110 }
111 }
112
113 pub fn is_initialized(&self) -> bool {
117 self.inner.get().is_some()
118 }
119
120 pub fn to_vec(&self) -> Vec<Rc<TreeNode>> {
122 self.ensure_initialized().to_vec()
123 }
124
125 pub fn contains(&self, node: &Rc<TreeNode>) -> bool {
127 self.ensure_initialized().contains(node)
128 }
129
130 pub fn index_of(&self, node: &Rc<TreeNode>) -> i32 {
132 self.ensure_initialized().index_of(node).map_or(-1, |index| index as i32)
133 }
134
135 fn ensure_initialized(&self) -> &FerroList<Rc<TreeNode>> {
139 if self.inner.get().is_none() {
140 let nodes = FerroList::new();
141 let _ = self.inner.set(nodes.clone());
142 self.kind.initialize(self, &nodes);
143 }
144 self.inner.get().expect("the nodes were just created")
145 }
146}
147
148impl INotifyCollectionChanged for TreeNodeCollection {
149 fn collection_changed(&self) -> &Event<CollectionChange> {
151 self.ensure_initialized().collection_changed()
152 }
153}
154
155impl INotifyPropertyChanged for TreeNodeCollection {
156 fn property_changed(&self) -> &Event<str> {
158 self.ensure_initialized().property_changed()
159 }
160}
161
162impl IFerroReadOnlyList<Rc<TreeNode>> for TreeNodeCollection {
163 fn count(&self) -> usize {
164 TreeNodeCollection::count(self)
165 }
166
167 fn get(&self, index: usize) -> Rc<TreeNode> {
168 TreeNodeCollection::get(self, index)
169 }
170
171 fn snapshot(&self) -> Rc<Vec<Rc<TreeNode>>> {
172 self.ensure_initialized().snapshot()
173 }
174
175 fn add_collection_changed(&self, handler: Rc<CollectionChangedHandler<Rc<TreeNode>>>) -> u64 {
176 self.ensure_initialized().add_collection_changed(handler)
177 }
178
179 fn remove_collection_changed(&self, token: u64) -> bool {
180 self.ensure_initialized().remove_collection_changed(token)
181 }
182}
183
184impl IItemsList for TreeNodeCollection {
187 fn count(&self) -> usize {
188 TreeNodeCollection::count(self)
189 }
190
191 fn get_at(&self, index: usize) -> Option<BoxedValue> {
192 <FerroList<Rc<TreeNode>> as IItemsList>::get_at(self.ensure_initialized(), index)
193 }
194
195 fn index_of(&self, item: &Option<BoxedValue>) -> i32 {
196 <FerroList<Rc<TreeNode>> as IItemsList>::index_of(self.ensure_initialized(), item)
197 }
198
199 fn is_notifying(&self) -> bool {
200 true
201 }
202
203 fn add_collection_changed(&self, handler: Rc<ItemsChangedHandler>) -> Option<u64> {
204 <FerroList<Rc<TreeNode>> as IItemsList>::add_collection_changed(self.ensure_initialized(), handler)
205 }
206
207 fn remove_collection_changed(&self, token: u64) {
208 <FerroList<Rc<TreeNode>> as IItemsList>::remove_collection_changed(self.ensure_initialized(), token);
209 }
210
211 fn as_any(&self) -> &dyn Any {
212 self
213 }
214}
215
216impl ModelCollection<TreeNode> for TreeNodeCollection {
221 fn count(&self) -> usize {
222 TreeNodeCollection::count(self)
223 }
224
225 fn get(&self, index: usize) -> Rc<TreeNode> {
226 TreeNodeCollection::get(self, index)
227 }
228
229 fn index_of(&self, model: &Rc<TreeNode>) -> Option<usize> {
230 self.ensure_initialized().index_of(model)
231 }
232
233 fn add_collection_changed(&self, handler: Rc<ModelsChangedHandler<TreeNode>>) -> Option<u64> {
234 Some(self.ensure_initialized().add_collection_changed(handler))
235 }
236
237 fn remove_collection_changed(&self, token: u64) {
238 self.ensure_initialized().remove_collection_changed(token);
239 }
240
241 fn is_notifying(&self) -> bool {
242 true
243 }
244
245 fn to_vec(&self) -> Vec<Rc<TreeNode>> {
246 TreeNodeCollection::to_vec(self)
247 }
248}
249
250ferro_markup_type!(class TreeNodeCollection {
251 this: Rc<TreeNodeCollection>,
252 handles: [TreeNodeCollection, Rc<TreeNodeCollection>, Option<Rc<TreeNodeCollection>>],
253 properties: [
254 Count: i32 { get: |this: &Rc<TreeNodeCollection>| this.count() as i32 },
255 ],
256});