1use super::Widget;
9use crate::event::{ConfigCx, Event, EventCx, IsUsed};
10use crate::geom::{Coord, Rect};
11use crate::layout::{AlignHints, AxisInfo, SizeRules};
12use crate::theme::SizeCx;
13use crate::util::IdentifyWidget;
14use crate::{Id, Tile};
15
16#[cfg(not(feature = "unsafe_node"))]
17trait NodeT {
18 fn id_ref(&self) -> &Id;
19 fn rect(&self) -> Rect;
20
21 fn clone_node(&mut self) -> Node<'_>;
22 fn as_tile(&self) -> &dyn Tile;
23
24 fn find_child_index(&self, id: &Id) -> Option<usize>;
25 fn child_node(&mut self, index: usize) -> Option<Node<'_>>;
26
27 fn size_rules(&mut self, cx: &mut SizeCx, axis: AxisInfo) -> SizeRules;
28 fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints);
29
30 fn _configure(&mut self, cx: &mut ConfigCx, id: Id);
31 fn _update(&mut self, cx: &mut ConfigCx);
32
33 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed;
34 fn _replay(&mut self, cx: &mut EventCx, id: Id);
35}
36#[cfg(not(feature = "unsafe_node"))]
37impl<'a, T> NodeT for (&'a mut dyn Widget<Data = T>, &'a T) {
38 fn id_ref(&self) -> &Id {
39 self.0.id_ref()
40 }
41 fn rect(&self) -> Rect {
42 self.0.rect()
43 }
44
45 fn clone_node(&mut self) -> Node<'_> {
46 Node::new(self.0, self.1)
47 }
48 fn as_tile(&self) -> &dyn Tile {
49 self.0.as_tile()
50 }
51
52 fn find_child_index(&self, id: &Id) -> Option<usize> {
53 self.0.find_child_index(id)
54 }
55
56 fn child_node(&mut self, index: usize) -> Option<Node<'_>> {
57 self.0.child_node(self.1, index)
58 }
59
60 fn size_rules(&mut self, cx: &mut SizeCx, axis: AxisInfo) -> SizeRules {
61 self.0.size_rules(cx, axis)
62 }
63 fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints) {
64 self.0.set_rect(cx, rect, hints);
65 }
66
67 fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
68 self.0._configure(cx, self.1, id);
69 }
70 fn _update(&mut self, cx: &mut ConfigCx) {
71 self.0._update(cx, self.1);
72 }
73
74 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
75 self.0._send(cx, self.1, id, event)
76 }
77 fn _replay(&mut self, cx: &mut EventCx, id: Id) {
78 self.0._replay(cx, self.1, id);
79 }
80}
81
82pub struct Node<'a>(
92 #[cfg(not(feature = "unsafe_node"))] Box<dyn NodeT + 'a>,
93 #[cfg(feature = "unsafe_node")] &'a mut dyn Widget<Data = ()>,
94 #[cfg(feature = "unsafe_node")] &'a (),
95);
96
97impl<'a> Node<'a> {
98 #[inline(always)]
100 pub fn new<T: 'a>(widget: &'a mut dyn Widget<Data = T>, data: &'a T) -> Self {
101 cfg_if::cfg_if! {
102 if #[cfg(feature = "unsafe_node")] {
103 use std::mem::transmute;
108 #[allow(clippy::missing_transmute_annotations)]
109 unsafe { Node(transmute(widget), transmute(data)) }
110 } else {
111 Node(Box::new((widget, data)))
112 }
113 }
114 }
115
116 #[inline(always)]
122 pub fn re<'b>(&'b mut self) -> Node<'b>
123 where
124 'a: 'b,
125 {
126 cfg_if::cfg_if! {
127 if #[cfg(feature = "unsafe_node")] {
128 Node(self.0, self.1)
129 } else {
130 self.0.clone_node()
131 }
132 }
133 }
134
135 pub fn as_tile(&self) -> &dyn Tile {
137 self.0.as_tile()
138 }
139
140 #[inline]
142 pub fn id_ref(&self) -> &Id {
143 self.0.id_ref()
144 }
145
146 #[inline]
148 pub fn id(&self) -> Id {
149 self.0.id_ref().clone()
150 }
151
152 #[inline]
156 pub fn identify(&self) -> IdentifyWidget<'_> {
157 self.0.as_tile().identify()
158 }
159
160 #[inline]
165 pub fn eq_id<T>(&self, rhs: T) -> bool
166 where
167 Id: PartialEq<T>,
168 {
169 *self.id_ref() == rhs
170 }
171
172 #[inline]
176 pub fn is_ancestor_of(&self, id: &Id) -> bool {
177 self.id().is_ancestor_of(id)
178 }
179
180 #[inline]
184 pub fn is_strict_ancestor_of(&self, id: &Id) -> bool {
185 !self.eq_id(id) && self.id().is_ancestor_of(id)
186 }
187
188 #[inline]
190 pub fn rect(&self) -> Rect {
191 self.0.rect()
192 }
193
194 #[inline]
196 pub fn try_probe(&self, coord: Coord) -> Option<Id> {
197 self.0.as_tile().try_probe(coord)
198 }
199
200 #[inline(always)]
202 pub fn get_child(&mut self, index: usize) -> Option<Node<'_>> {
203 cfg_if::cfg_if! {
204 if #[cfg(feature = "unsafe_node")] {
205 self.0.child_node(self.1, index)
206 } else {
207 self.0.child_node(index)
208 }
209 }
210 }
211
212 #[inline]
217 pub fn find_child_index(&self, id: &Id) -> Option<usize> {
218 self.0.find_child_index(id)
219 }
220
221 #[inline(always)]
225 pub fn find_node<F: FnOnce(Node<'_>) -> T, T>(&mut self, id: &Id, cb: F) -> Option<T> {
226 if let Some(index) = self.find_child_index(id) {
227 if let Some(mut node) = self.get_child(index) {
228 node.find_node(id, cb)
229 } else {
230 debug_assert!(false);
231 None
232 }
233 } else if self.eq_id(id) {
234 Some(cb(self.re()))
235 } else {
236 None
237 }
238 }
239}
240
241#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
242#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
243impl<'a> Node<'a> {
244 pub(crate) fn size_rules(&mut self, cx: &mut SizeCx, axis: AxisInfo) -> SizeRules {
246 self.0.size_rules(cx, axis)
247 }
248
249 pub(crate) fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints) {
251 self.0.set_rect(cx, rect, hints);
252 }
253
254 pub(crate) fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
256 cfg_if::cfg_if! {
257 if #[cfg(feature = "unsafe_node")] {
258 self.0._configure(cx, self.1, id);
259 } else {
260 self.0._configure(cx, id);
261 }
262 }
263 }
264
265 pub(crate) fn _update(&mut self, cx: &mut ConfigCx) {
267 cfg_if::cfg_if! {
268 if #[cfg(feature = "unsafe_node")] {
269 self.0._update(cx, self.1);
270 } else {
271 self.0._update(cx);
272 }
273 }
274 }
275
276 pub(crate) fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
278 cfg_if::cfg_if! {
279 if #[cfg(feature = "unsafe_node")] {
280 self.0._send(cx, self.1, id, event)
281 } else {
282 self.0._send(cx, id, event)
283 }
284 }
285 }
286
287 pub(crate) fn _replay(&mut self, cx: &mut EventCx, id: Id) {
289 cfg_if::cfg_if! {
290 if #[cfg(feature = "unsafe_node")] {
291 self.0._replay(cx, self.1, id);
292 } else {
293 self.0._replay(cx, id);
294 }
295 }
296 }
297}