1use super::Widget;
9use crate::event::{ConfigCx, Event, EventCx, IsUsed, NavAdvance};
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, 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
32 fn _configure(&mut self, cx: &mut ConfigCx, id: Id);
33 fn _update(&mut self, cx: &mut ConfigCx);
34
35 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed;
36 fn _replay(&mut self, cx: &mut EventCx, id: Id);
37 fn _nav_next(
38 &mut self,
39 cx: &mut ConfigCx,
40 focus: Option<&Id>,
41 advance: NavAdvance,
42 ) -> Option<Id>;
43}
44#[cfg(not(feature = "unsafe_node"))]
45impl<'a, T> NodeT for (&'a mut dyn Widget<Data = T>, &'a T) {
46 fn id_ref(&self) -> &Id {
47 self.0.id_ref()
48 }
49 fn rect(&self) -> Rect {
50 self.0.rect()
51 }
52
53 fn clone_node(&mut self) -> Node<'_> {
54 Node::new(self.0, self.1)
55 }
56 fn as_tile(&self) -> &dyn Tile {
57 self.0.as_tile()
58 }
59
60 fn find_child_index(&self, id: &Id) -> Option<usize> {
61 self.0.find_child_index(id)
62 }
63
64 fn child_node(&mut self, index: usize) -> Option<Node<'_>> {
65 self.0.child_node(self.1, index)
66 }
67
68 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
69 self.0.size_rules(sizer, axis)
70 }
71 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
72 self.0.set_rect(cx, rect, hints);
73 }
74
75 fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
76 self.0.nav_next(reverse, from)
77 }
78
79 fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
80 self.0._configure(cx, self.1, id);
81 }
82 fn _update(&mut self, cx: &mut ConfigCx) {
83 self.0._update(cx, self.1);
84 }
85
86 fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
87 self.0._send(cx, self.1, id, event)
88 }
89 fn _replay(&mut self, cx: &mut EventCx, id: Id) {
90 self.0._replay(cx, self.1, id);
91 }
92 fn _nav_next(
93 &mut self,
94 cx: &mut ConfigCx,
95 focus: Option<&Id>,
96 advance: NavAdvance,
97 ) -> Option<Id> {
98 self.0._nav_next(cx, self.1, focus, advance)
99 }
100}
101
102pub struct Node<'a>(
112 #[cfg(not(feature = "unsafe_node"))] Box<dyn NodeT + 'a>,
113 #[cfg(feature = "unsafe_node")] &'a mut dyn Widget<Data = ()>,
114 #[cfg(feature = "unsafe_node")] &'a (),
115);
116
117impl<'a> Node<'a> {
118 #[inline(always)]
120 pub fn new<T: 'a>(widget: &'a mut dyn Widget<Data = T>, data: &'a T) -> Self {
121 cfg_if::cfg_if! {
122 if #[cfg(feature = "unsafe_node")] {
123 use std::mem::transmute;
128 #[allow(clippy::missing_transmute_annotations)]
129 unsafe { Node(transmute(widget), transmute(data)) }
130 } else {
131 Node(Box::new((widget, data)))
132 }
133 }
134 }
135
136 #[inline(always)]
142 pub fn re<'b>(&'b mut self) -> Node<'b>
143 where
144 'a: 'b,
145 {
146 cfg_if::cfg_if! {
147 if #[cfg(feature = "unsafe_node")] {
148 Node(self.0, self.1)
149 } else {
150 self.0.clone_node()
151 }
152 }
153 }
154
155 pub fn as_tile(&self) -> &dyn Tile {
157 self.0.as_tile()
158 }
159
160 #[inline]
162 pub fn id_ref(&self) -> &Id {
163 self.0.id_ref()
164 }
165
166 #[inline]
168 pub fn id(&self) -> Id {
169 self.0.id_ref().clone()
170 }
171
172 #[inline]
176 pub fn identify(&self) -> IdentifyWidget<'_> {
177 self.0.as_tile().identify()
178 }
179
180 #[inline]
185 pub fn eq_id<T>(&self, rhs: T) -> bool
186 where
187 Id: PartialEq<T>,
188 {
189 *self.id_ref() == rhs
190 }
191
192 #[inline]
196 pub fn is_ancestor_of(&self, id: &Id) -> bool {
197 self.id().is_ancestor_of(id)
198 }
199
200 #[inline]
204 pub fn is_strict_ancestor_of(&self, id: &Id) -> bool {
205 !self.eq_id(id) && self.id().is_ancestor_of(id)
206 }
207
208 #[inline]
210 pub fn rect(&self) -> Rect {
211 self.0.rect()
212 }
213
214 #[inline]
216 pub fn try_probe(&self, coord: Coord) -> Option<Id> {
217 self.0.as_tile().try_probe(coord)
218 }
219
220 #[inline(always)]
222 pub fn get_child(&mut self, index: usize) -> Option<Node<'_>> {
223 cfg_if::cfg_if! {
224 if #[cfg(feature = "unsafe_node")] {
225 self.0.child_node(self.1, index)
226 } else {
227 self.0.child_node(index)
228 }
229 }
230 }
231
232 #[inline]
237 pub fn find_child_index(&self, id: &Id) -> Option<usize> {
238 self.0.find_child_index(id)
239 }
240
241 #[inline(always)]
245 pub fn find_node<F: FnOnce(Node<'_>) -> T, T>(&mut self, id: &Id, cb: F) -> Option<T> {
246 if let Some(index) = self.find_child_index(id) {
247 if let Some(mut node) = self.get_child(index) {
248 node.find_node(id, cb)
249 } else {
250 debug_assert!(false);
251 None
252 }
253 } else if self.eq_id(id) {
254 Some(cb(self.re()))
255 } else {
256 None
257 }
258 }
259}
260
261#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
262#[cfg_attr(docsrs, doc(cfg(internal_doc)))]
263impl<'a> Node<'a> {
264 pub(crate) fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
266 self.0.size_rules(sizer, axis)
267 }
268
269 pub(crate) fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
271 self.0.set_rect(cx, rect, hints);
272 }
273
274 pub(crate) fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
276 self.0.nav_next(reverse, from)
277 }
278
279 pub(crate) fn _configure(&mut self, cx: &mut ConfigCx, id: Id) {
281 cfg_if::cfg_if! {
282 if #[cfg(feature = "unsafe_node")] {
283 self.0._configure(cx, self.1, id);
284 } else {
285 self.0._configure(cx, id);
286 }
287 }
288 }
289
290 pub(crate) fn _update(&mut self, cx: &mut ConfigCx) {
292 cfg_if::cfg_if! {
293 if #[cfg(feature = "unsafe_node")] {
294 self.0._update(cx, self.1);
295 } else {
296 self.0._update(cx);
297 }
298 }
299 }
300
301 pub(crate) fn _send(&mut self, cx: &mut EventCx, id: Id, event: Event) -> IsUsed {
303 cfg_if::cfg_if! {
304 if #[cfg(feature = "unsafe_node")] {
305 self.0._send(cx, self.1, id, event)
306 } else {
307 self.0._send(cx, id, event)
308 }
309 }
310 }
311
312 pub(crate) fn _replay(&mut self, cx: &mut EventCx, id: Id) {
314 cfg_if::cfg_if! {
315 if #[cfg(feature = "unsafe_node")] {
316 self.0._replay(cx, self.1, id);
317 } else {
318 self.0._replay(cx, id);
319 }
320 }
321 }
322
323 pub fn _nav_next(
326 &mut self,
327 cx: &mut ConfigCx,
328 focus: Option<&Id>,
329 advance: NavAdvance,
330 ) -> Option<Id> {
331 cfg_if::cfg_if! {
332 if #[cfg(feature = "unsafe_node")] {
333 self.0._nav_next(cx, self.1, focus, advance)
334 } else {
335 self.0._nav_next(cx, focus, advance)
336 }
337 }
338 }
339}