ferroui_base/logical_tree/
logical_extensions.rs1use crate::{ObjectType, Ref, StyledElement};
5use std::rc::Rc;
6
7pub struct LogicalAncestors {
10 next: Option<Ref<StyledElement>>,
11}
12
13impl Iterator for LogicalAncestors {
14 type Item = Ref<StyledElement>;
15
16 fn next(&mut self) -> Option<Ref<StyledElement>> {
17 let current = self.next.take()?;
18 self.next = current.parent();
19 Some(current)
20 }
21}
22
23pub struct LogicalDescendants {
26 stack: Vec<(Rc<Vec<Ref<StyledElement>>>, usize)>,
29 pending: Option<Ref<StyledElement>>,
30}
31
32impl LogicalDescendants {
33 fn push_children(&mut self, logical: &StyledElement) {
34 let children = logical.logical_children().snapshot();
35 if !children.is_empty() {
36 self.stack.push((children, 0));
37 }
38 }
39}
40
41impl Iterator for LogicalDescendants {
42 type Item = Ref<StyledElement>;
43
44 fn next(&mut self) -> Option<Ref<StyledElement>> {
45 if let Some(pending) = self.pending.take() {
46 return Some(pending);
47 }
48
49 loop {
50 let (children, index) = self.stack.last_mut()?;
51 if *index >= children.len() {
52 self.stack.pop();
53 continue;
54 }
55
56 let child = children[*index].clone();
57 *index += 1;
58 self.push_children(&child);
59 return Some(child);
60 }
61 }
62}
63
64impl StyledElement {
65 pub fn get_logical_ancestors(&self) -> LogicalAncestors {
68 LogicalAncestors { next: self.parent() }
69 }
70
71 pub fn get_self_and_logical_ancestors(&self) -> LogicalAncestors {
73 LogicalAncestors { next: Some(self.to_ref()) }
74 }
75
76 pub fn find_logical_ancestor_of_type<T: ObjectType>(&self, include_self: bool) -> Option<Ref<T>> {
79 let mut parent = if include_self { Some(self.to_ref()) } else { self.parent() };
80
81 while let Some(current) = parent {
82 if let Some(result) = current.clone().cast::<T>() {
83 return Some(result);
84 }
85 parent = current.parent();
86 }
87
88 None
89 }
90
91 pub fn get_logical_children(&self) -> Rc<Vec<Ref<StyledElement>>> {
94 self.logical_children().snapshot()
95 }
96
97 pub fn get_logical_descendants(&self) -> LogicalDescendants {
100 let mut result = LogicalDescendants { stack: Vec::new(), pending: None };
101 result.push_children(self);
102 result
103 }
104
105 pub fn get_self_and_logical_descendants(&self) -> LogicalDescendants {
108 let mut result = self.get_logical_descendants();
109 result.pending = Some(self.to_ref());
110 result
111 }
112
113 pub fn find_logical_descendant_of_type<T: ObjectType>(&self, include_self: bool) -> Option<Ref<T>> {
116 if include_self {
117 if let Some(result) = self.to_ref().cast::<T>() {
118 return Some(result);
119 }
120 }
121
122 Self::find_descendant_of_type_core::<T>(self)
123 }
124
125 pub fn get_logical_parent(&self) -> Option<Ref<StyledElement>> {
127 self.parent()
128 }
129
130 pub fn get_logical_parent_of_type<T: ObjectType>(&self) -> Option<Ref<T>> {
132 self.parent().and_then(|parent| parent.cast::<T>())
133 }
134
135 pub fn get_logical_siblings(&self) -> Rc<Vec<Ref<StyledElement>>> {
139 match self.parent() {
140 Some(parent) => parent.logical_children().snapshot(),
141 None => Rc::default(),
142 }
143 }
144
145 pub fn is_logical_ancestor_of(&self, target: Option<&StyledElement>) -> bool {
148 let mut current = target.and_then(StyledElement::parent);
149
150 while let Some(parent) = current {
151 if std::ptr::eq::<StyledElement>(&*parent, self) {
152 return true;
153 }
154 current = parent.parent();
155 }
156
157 false
158 }
159
160 fn find_descendant_of_type_core<T: ObjectType>(logical: &StyledElement) -> Option<Ref<T>> {
161 let logical_children = logical.logical_children().snapshot();
162
163 for child in logical_children.iter() {
164 if let Some(result) = child.clone().cast::<T>() {
165 return Some(result);
166 }
167
168 if let Some(child_result) = Self::find_descendant_of_type_core::<T>(child) {
169 return Some(child_result);
170 }
171 }
172
173 None
174 }
175}