1use super::Widget;
9use crate::event::{ConfigCx, Event, EventCx, IsUsed};
10use crate::geom::{Coord, Rect};
11use crate::layout::{AlignHints, AxisInfo, SizeRules};
12use crate::theme::{DrawCx, SizeCx};
13use crate::{Id, Layout, NavAdvance};
14
15#[cfg(not(feature = "unsafe_node"))]
16trait NodeT {
17 fn id_ref(&self) -> &Id;
18 fn rect(&self) -> Rect;
19
20 fn clone_node(&mut self) -> Node<'_>;
21 fn as_layout(&self) -> &dyn Layout;
22
23 fn num_children(&self) -> usize;
24 fn find_child_index(&self, id: &Id) -> Option<usize>;
25 fn for_child_node(&mut self, index: usize, f: Box<dyn FnOnce(Node<'_>) + '_>);
26
27 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules;
28 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints);
29
30 fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize>;
31 fn find_id(&mut self, coord: Coord) -> Option<Id>;
32 fn _draw(&mut self, draw: DrawCx);
33
34 fn _configure(&mut self, cx: &mut ConfigCx, id: Id);
35 fn _update(&mut self, cx: &mut ConfigCx);
36
37 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed;
38 fn _replay(&mut self, cx: &mut EventCx, id: Id);
39 fn _nav_next(
40 &mut self,
41 cx: &mut ConfigCx,
42 focus: Option<&Id>,
43 advance: NavAdvance,
44 ) -> Option<Id>;
45}
46#[cfg(not(feature = "unsafe_node"))]
47impl<'a, T> NodeT for (&'a mut dyn Widget<Data = T>, &'a T) {
48 fn id_ref(&self) -> &Id {
49 self.0.id_ref()
50 }
51 fn rect(&self) -> Rect {
52 self.0.rect()
53 }
54
55 fn clone_node(&mut self) -> Node<'_> {
56 Node::new(self.0, self.1)
57 }
58 fn as_layout(&self) -> &dyn Layout {
59 self.0.as_layout()
60 }
61
62 fn num_children(&self) -> usize {
63 self.0.num_children()
64 }
65 fn find_child_index(&self, id: &Id) -> Option<usize> {
66 self.0.find_child_index(id)
67 }
68
69 fn for_child_node(&mut self, index: usize, f: Box<dyn FnOnce(Node<'_>) + '_>) {
70 self.0.for_child_node(self.1, index, f);
71 }
72
73 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
74 self.0.size_rules(sizer, axis)
75 }
76 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
77 self.0.set_rect(cx, rect, hints);
78 }
79
80 fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
81 self.0.nav_next(reverse, from)
82 }
83 fn find_id(&mut self, coord: Coord) -> Option<Id> {
84 self.0.find_id(coord)
85 }
86 fn _draw(&mut self, mut draw: DrawCx) {
87 draw.recurse(&mut self.0);
88 }
89
90 fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
91 self.0._configure(cx, self.1, id);
92 }
93 fn _update(&mut self, cx: &mut ConfigCx) {
94 self.0._update(cx, self.1);
95 }
96
97 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
98 self.0._send(cx, self.1, id, event)
99 }
100 fn _replay(&mut self, cx: &mut EventCx, id: Id) {
101 self.0._replay(cx, self.1, id);
102 }
103 fn _nav_next(
104 &mut self,
105 cx: &mut ConfigCx,
106 focus: Option<&Id>,
107 advance: NavAdvance,
108 ) -> Option<Id> {
109 self.0._nav_next(cx, self.1, focus, advance)
110 }
111}
112
113pub struct Node<'a>(
123 #[cfg(not(feature = "unsafe_node"))] Box<dyn NodeT + 'a>,
124 #[cfg(feature = "unsafe_node")] &'a mut dyn Widget<Data = ()>,
125 #[cfg(feature = "unsafe_node")] &'a (),
126);
127
128impl<'a> Node<'a> {
129 #[inline(always)]
131 pub fn new<T: 'a>(widget: &'a mut dyn Widget<Data = T>, data: &'a T) -> Self {
132 cfg_if::cfg_if! {
133 if #[cfg(feature = "unsafe_node")] {
134 use std::mem::transmute;
139 unsafe { Node(transmute(widget), transmute(data)) }
140 } else {
141 Node(Box::new((widget, data)))
142 }
143 }
144 }
145
146 #[inline(always)]
152 pub fn re<'b>(&'b mut self) -> Node<'b>
153 where
154 'a: 'b,
155 {
156 cfg_if::cfg_if! {
157 if #[cfg(feature = "unsafe_node")] {
158 Node(self.0, self.1)
159 } else {
160 self.0.clone_node()
161 }
162 }
163 }
164
165 pub fn as_layout(&self) -> &dyn Layout {
167 self.0.as_layout()
168 }
169
170 #[inline]
172 pub fn id_ref(&self) -> &Id {
173 self.0.id_ref()
174 }
175
176 #[inline]
178 pub fn id(&self) -> Id {
179 self.id_ref().clone()
180 }
181
182 #[inline]
187 pub fn eq_id<T>(&self, rhs: T) -> bool
188 where
189 Id: PartialEq<T>,
190 {
191 *self.id_ref() == rhs
192 }
193
194 #[inline]
198 pub fn is_ancestor_of(&self, id: &Id) -> bool {
199 self.id().is_ancestor_of(id)
200 }
201
202 #[inline]
206 pub fn is_strict_ancestor_of(&self, id: &Id) -> bool {
207 !self.eq_id(id) && self.id().is_ancestor_of(id)
208 }
209
210 #[inline]
212 pub fn rect(&self) -> Rect {
213 self.0.rect()
214 }
215
216 #[inline]
221 pub fn num_children(&self) -> usize {
222 self.0.num_children()
223 }
224
225 pub fn for_child<R>(&mut self, index: usize, f: impl FnOnce(Node<'_>) -> R) -> Option<R> {
230 let mut result = None;
231 let out = &mut result;
232 let f: Box<dyn for<'b> FnOnce(Node<'b>)> = Box::new(|node| {
233 *out = Some(f(node));
234 });
235 cfg_if::cfg_if! {
236 if #[cfg(feature = "unsafe_node")] {
237 self.0.for_child_node(self.1, index, f);
238 } else {
239 self.0.for_child_node(index, f);
240 }
241 }
242 result
243 }
244
245 pub fn for_children(&mut self, mut f: impl FnMut(Node<'_>)) {
247 for index in 0..self.0.num_children() {
248 let f = &mut f;
250 let f: Box<dyn for<'b> FnOnce(Node<'b>)> = Box::new(|node| {
251 f(node);
252 });
253 cfg_if::cfg_if! {
254 if #[cfg(feature = "unsafe_node")] {
255 self.0.for_child_node(self.1, index, f);
256 } else {
257 self.0.for_child_node(index, f);
258 }
259 }
260 }
261 }
262
263 #[inline]
268 pub fn find_child_index(&self, id: &Id) -> Option<usize> {
269 self.0.find_child_index(id)
270 }
271
272 pub fn find_node<F: FnOnce(Node<'_>) -> T, T>(&mut self, id: &Id, cb: F) -> Option<T> {
276 if let Some(index) = self.find_child_index(id) {
277 self.for_child(index, |mut node| node.find_node(id, cb))
278 .unwrap()
279 } else if self.eq_id(id) {
280 Some(cb(self.re()))
281 } else {
282 None
283 }
284 }
285}
286
287#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
288#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
289impl<'a> Node<'a> {
290 pub(crate) fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
292 self.0.size_rules(sizer, axis)
293 }
294
295 pub(crate) fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
297 self.0.set_rect(cx, rect, hints);
298 }
299
300 pub(crate) fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
302 self.0.nav_next(reverse, from)
303 }
304
305 pub(crate) fn find_id(&mut self, coord: Coord) -> Option<Id> {
307 self.0.find_id(coord)
308 }
309
310 cfg_if::cfg_if! {
311 if #[cfg(feature = "unsafe_node")] {
312 pub(crate) fn _draw(&mut self, mut draw: DrawCx) {
314 draw.recurse(&mut self.0);
315 }
316 } else {
317 pub(crate) fn _draw(&mut self, draw: DrawCx) {
319 self.0._draw(draw);
320 }
321 }
322 }
323
324 pub(crate) fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
326 cfg_if::cfg_if! {
327 if #[cfg(feature = "unsafe_node")] {
328 self.0._configure(cx, self.1, id);
329 } else {
330 self.0._configure(cx, id);
331 }
332 }
333 }
334
335 pub(crate) fn _update(&mut self, cx: &mut ConfigCx) {
337 cfg_if::cfg_if! {
338 if #[cfg(feature = "unsafe_node")] {
339 self.0._update(cx, self.1);
340 } else {
341 self.0._update(cx);
342 }
343 }
344 }
345
346 pub(crate) fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
348 cfg_if::cfg_if! {
349 if #[cfg(feature = "unsafe_node")] {
350 self.0._send(cx, self.1, id, event)
351 } else {
352 self.0._send(cx, id, event)
353 }
354 }
355 }
356
357 pub(crate) fn _replay(&mut self, cx: &mut EventCx, id: Id) {
359 cfg_if::cfg_if! {
360 if #[cfg(feature = "unsafe_node")] {
361 self.0._replay(cx, self.1, id);
362 } else {
363 self.0._replay(cx, id);
364 }
365 }
366 }
367
368 pub fn _nav_next(
371 &mut self,
372 cx: &mut ConfigCx,
373 focus: Option<&Id>,
374 advance: NavAdvance,
375 ) -> Option<Id> {
376 cfg_if::cfg_if! {
377 if #[cfg(feature = "unsafe_node")] {
378 self.0._nav_next(cx, self.1, focus, advance)
379 } else {
380 self.0._nav_next(cx, focus, advance)
381 }
382 }
383 }
384}