ferroui_dynamic_data/cache/
node.rs1use super::{IObservableCache, ISourceUpdater, ObservableCache, SourceCache};
4use ferroui_system::IDisposable;
5use std::cell::{Cell, RefCell};
6use std::fmt;
7use std::hash::{Hash, Hasher};
8use std::rc::{Rc, Weak};
9
10pub struct Node<T, K> {
17 children_source: SourceCache<Rc<Node<T, K>>, K>,
18 children: ObservableCache<Rc<Node<T, K>>, K>,
19 item: T,
20 key: K,
21 parent: RefCell<Option<Weak<Node<T, K>>>>,
22 is_disposed: Cell<bool>,
23}
24
25impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> Node<T, K> {
26 pub fn new(item: T, key: K) -> Rc<Self> {
28 Self::with_parent(item, key, None)
29 }
30
31 pub fn with_parent(item: T, key: K, parent: Option<&Rc<Node<T, K>>>) -> Rc<Self> {
33 let children_source = SourceCache::new(|node: &Rc<Node<T, K>>| node.key.clone());
34 let children = children_source.as_observable_cache_inner().clone();
35 Rc::new(Self { children_source, children, item, key, parent: RefCell::new(parent.map(Rc::downgrade)), is_disposed: Cell::new(false) })
36 }
37
38 pub fn children(&self) -> &ObservableCache<Rc<Node<T, K>>, K> {
40 &self.children
41 }
42
43 pub fn depth(&self) -> usize {
45 let mut depth = 0;
46 let mut parent = self.parent();
47 while let Some(node) = parent {
48 depth += 1;
49 parent = node.parent();
50 }
51 depth
52 }
53
54 pub fn is_root(&self) -> bool {
56 self.parent().is_none()
57 }
58
59 pub fn item(&self) -> &T {
61 &self.item
62 }
63
64 pub fn key(&self) -> &K {
66 &self.key
67 }
68
69 pub fn parent(&self) -> Option<Rc<Node<T, K>>> {
71 self.parent.borrow().as_ref().and_then(Weak::upgrade)
72 }
73
74 pub(crate) fn set_parent(&self, parent: Option<&Rc<Node<T, K>>>) {
76 *self.parent.borrow_mut() = parent.map(Rc::downgrade);
77 }
78
79 pub(crate) fn update(&self, update_action: impl FnOnce(&mut dyn ISourceUpdater<Rc<Node<T, K>>, K>)) {
81 self.children_source.edit(update_action);
82 }
83}
84
85impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IDisposable for Node<T, K> {
86 fn dispose(&self) {
88 if self.is_disposed.replace(true) {
89 return;
90 }
91 self.children_source.dispose();
93 }
94}
95
96impl<T, K: PartialEq> PartialEq for Node<T, K> {
97 fn eq(&self, other: &Self) -> bool {
99 std::ptr::eq(self, other) || self.key == other.key
100 }
101}
102
103impl<T, K: Eq> Eq for Node<T, K> {}
104
105impl<T, K: Hash> Hash for Node<T, K> {
106 fn hash<H: Hasher>(&self, state: &mut H) {
108 self.key.hash(state);
109 }
110}
111
112impl<T: fmt::Display + Clone + 'static, K: Eq + Hash + Clone + 'static> fmt::Display for Node<T, K> {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 let count = self.children.count();
116 if count == 0 {
117 write!(f, "{}", self.item)
118 } else {
119 write!(f, "{} ({} children)", self.item, count)
120 }
121 }
122}
123
124impl<T: fmt::Debug, K: fmt::Debug> fmt::Debug for Node<T, K> {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 f.debug_struct("Node").field("key", &self.key).field("item", &self.item).finish()
127 }
128}