zng_app/widget/
node.rs

1//! Widget nodes types, [`UiNode`], [`UiNodeList`] and others.
2
3use std::{
4    any::{Any, TypeId},
5    fmt,
6};
7
8mod adopt;
9pub use adopt::*;
10
11mod arc;
12pub use arc::*;
13
14mod extend;
15pub use extend::*;
16
17mod match_node;
18pub use match_node::*;
19
20mod when;
21pub use when::*;
22
23mod list;
24pub use list::*;
25use zng_app_proc_macros::{ui_node, widget};
26use zng_layout::unit::PxSize;
27use zng_var::{ContextInitHandle, ResponseVar, Var};
28
29use crate::{
30    render::{FrameBuilder, FrameUpdate},
31    update::{EventUpdate, WidgetUpdates},
32};
33
34use super::{
35    WIDGET, WidgetId, WidgetUpdateMode,
36    base::{PARALLEL_VAR, Parallel},
37    info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
38};
39
40/// Represents an UI tree node.
41///
42/// You can use the [`match_node`] helper to quickly declare a new node from a closure, most property nodes are implemented
43/// using the match helpers. For more advanced nodes you can use the [`ui_node`] proc-macro attribute.
44///
45/// [`match_node`]:fn@match_node
46#[diagnostic::on_unimplemented(
47    note = "you can use `match_node` to declare a node from a closure",
48    note = "you can use `#[ui_node]` to implement `UiNode` for `{Self}`"
49)]
50pub trait UiNode: Any + Send {
51    /// Initializes the node in a new UI context.
52    ///
53    /// Common init operations are subscribing to variables and events and initializing data.
54    /// You can use [`WIDGET`] to subscribe events and vars, the subscriptions live until the widget is deinited.
55    ///
56    /// If the node is a custom widget ([`is_widget`]) it must request an info, layout and render updates, other nodes
57    /// do not need to request any sort of update on init.
58    ///
59    /// Note that this method can be called again, after a [`deinit`].
60    ///
61    /// [`is_widget`]: UiNode::is_widget
62    /// [`deinit`]: UiNode::deinit
63    fn init(&mut self);
64
65    /// Deinitializes the node in the current UI context.
66    ///
67    /// Common deinit operations include dropping allocations and handlers.
68    ///
69    /// If the node is a custom widget ([`is_widget`]) it must request an info, layout and render updates, other nodes
70    /// do not need to request any sort of update on deinit.
71    ///
72    /// Note that [`init`] can be called again after this.
73    ///
74    /// [`is_widget`]: UiNode::is_widget
75    /// [`init`]: UiNode::init
76    fn deinit(&mut self);
77
78    /// Builds widget info.
79    ///
80    /// This method is called every time there are structural changes in the UI tree such as a node added or removed, you
81    /// can also request an info rebuild using [`WIDGET.update_info`].
82    ///
83    /// Only nodes in widgets that requested info rebuild and nodes in their ancestors receive this call. Other
84    /// widgets reuse their info in the new info tree. The widget's latest built info is available in [`WIDGET.info`].
85    ///
86    /// Note that info rebuild has higher priority over event, update, layout and render, this means that if you set a variable
87    /// and request info update the next info rebuild will still observe the old variable value, you can work around this issue by
88    /// only requesting info rebuild after the variable updates.
89    ///
90    /// [`WIDGET.info`]: crate::widget::WIDGET::info
91    /// [`WIDGET.update_info`]: crate::widget::WIDGET::update_info
92    fn info(&mut self, info: &mut WidgetInfoBuilder);
93
94    /// Receives an event.
95    ///
96    /// Every call to this method is for a single update of a single event type, you can listen to events
97    /// by subscribing to then on init and using the [`Event::on`] method in this method to detect the event.
98    ///
99    /// Note that events sent to descendant nodes also flow through this method and must be delegated. If you observe
100    /// an event for a descendant before delegating to the descendant this is a ***preview*** handling, in the normal handling
101    /// you delegate first, then check the event propagation.
102    ///
103    /// [`Event::on`]: crate::event::Event::on
104    fn event(&mut self, update: &EventUpdate);
105
106    /// Receives variable and other non-event updates.
107    ///
108    /// Calls to this method aggregate all updates that happen in the last pass, multiple variables can be new at the same time.
109    /// You can listen to variable updates by subscribing to then on init and using the [`Var::get_new`] method in this method to
110    /// receive the new values.
111    ///
112    /// A custom update can be requested using the context [`WIDGET.update`]. Common update operations include reacting to variable
113    /// changes that generate an intermediary value for layout or render, the update implementation uses [`WIDGET`] to request layout
114    /// and render after updating the data. Note that for simple variables that are used directly on layout or render you can subscribe
115    /// to that operation directly, skipping update.
116    ///
117    /// [`Var::get_new`]: zng_var::Var::get_new
118    /// [`WIDGET.update`]: crate::widget::WIDGET::update
119    fn update(&mut self, updates: &WidgetUpdates);
120
121    /// Computes the widget size given the contextual layout metrics without actually updating the widget layout.
122    ///
123    /// Implementers must return the same size [`layout`] returns for the given [`LayoutMetrics`], without
124    /// affecting the actual widget render. Panel widgets that implement some complex layouts need to get an
125    /// what the widget would be given some constraints, this value is used to inform the actual [`layout`] call.
126    ///
127    /// Nodes that implement [`layout`] must also implement this method, the [`LAYOUT`] context can be used to retrieve the metrics,
128    /// the [`WidgetMeasure`] parameter can be used to communicate with the parent layout, such as disabling inline layout, the
129    /// returned [`PxSize`] is the desired size given the parent constraints.
130    ///
131    /// [`layout`]: Self::layout
132    /// [`LayoutMetrics`]: zng_layout::context::LayoutMetrics
133    /// [`LAYOUT`]: zng_layout::context::LAYOUT
134    /// [`PxSize`]: zng_layout::unit::PxSize
135    #[must_use]
136    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize;
137
138    /// Computes the widget layout given the contextual layout metrics.
139    ///
140    /// Implementers must also implement [`measure`]. This method is called by the parent layout once the final constraints
141    /// for the frame are defined, the [`LAYOUT`] context can be used to retrieve the constraints, the [`WidgetLayout`] parameter
142    /// can be used to communicate layout metadata such as inline segments to the parent layout, the returned [`PxSize`] is the
143    /// final size given the constraints.
144    ///
145    /// Only widgets and ancestors that requested layout or use metrics that changed since last layout receive this call. Other
146    /// widgets reuse the last layout result.
147    ///
148    /// Nodes that render can also implement this operation just to observe the latest widget size, if changes are detected
149    /// the [`WIDGET.render`] method can be used to request render.
150    ///
151    /// [`measure`]: Self::measure
152    /// [`LayoutMetrics`]: zng_layout::context::LayoutMetrics
153    /// [`constraints`]: zng_layout::context::LayoutMetrics::constraints
154    /// [`WIDGET.render`]: crate::widget::WIDGET::render
155    /// [`LAYOUT`]: zng_layout::context::LAYOUT
156    /// [`PxSize`]: zng_layout::unit::PxSize
157    #[must_use]
158    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize;
159
160    /// Generates render instructions and updates transforms and hit-test areas.
161    ///
162    /// This method does not generate pixels immediately, it generates *display items* that are visual building block instructions
163    /// for the renderer that will run after the window *display list* is built.
164    ///
165    /// Only widgets and ancestors that requested render receive this call, other widgets reuse the display items and transforms
166    /// from the last frame.
167    fn render(&mut self, frame: &mut FrameBuilder);
168
169    /// Updates values in the last generated frame.
170    ///
171    /// Some display item values and transforms can be updated directly, without needing to rebuild the display list. All [`FrameBuilder`]
172    /// methods that accept a [`FrameValue<T>`] input can be bound to an ID that can be used to update that value.
173    ///
174    /// Only widgets and ancestors that requested render update receive this call. Note that if any other widget in the same window
175    /// requests render all pending render update requests are upgraded to render requests.
176    ///
177    /// [`FrameValue<T>`]: crate::render::FrameValue
178    fn render_update(&mut self, update: &mut FrameUpdate);
179
180    /// Box this node or just returns `self` if it is already a `BoxedUiNode`.
181    fn boxed(self) -> BoxedUiNode
182    where
183        Self: Sized,
184    {
185        debug_assert_ne!(self.type_id(), TypeId::of::<BoxedUiNode>());
186        Box::new(self)
187    }
188
189    /// Helper for complying with the `"dyn_node"` feature, boxes the node or just returns it depending of the
190    /// compile time feature.
191    #[cfg(feature = "dyn_node")]
192    fn cfg_boxed(self) -> BoxedUiNode
193    where
194        Self: Sized,
195    {
196        self.boxed()
197    }
198
199    /// Helper for complying with the `"dyn_node"` feature, boxes the node or just returns it depending of the
200    /// compile time feature.
201    #[cfg(not(feature = "dyn_node"))]
202    fn cfg_boxed(self) -> Self
203    where
204        Self: Sized,
205    {
206        self
207    }
208
209    /// Gets if this node represents a full widget, that is, it is the outer-most widget node and defines a widget context.
210    ///
211    /// If this is `true` the [`with_context`] method can be used to get the widget context.
212    ///
213    /// [`with_context`]: UiNode::with_context
214    fn is_widget(&self) -> bool {
215        false
216    }
217
218    /// Gets if this node does nothing and is layout collapsed.
219    ///
220    /// Implementers must return `true` only if the node will always do nothing, nodes that may change
221    /// and stop being collapsed are not nil.
222    fn is_nil(&self) -> bool {
223        false
224    }
225
226    /// Calls `f` with the [`WIDGET`] context of the node if it [`is_widget`].
227    ///
228    /// Returns `None` if the node does not represent a widget.
229    ///
230    /// If `update_mode` is [`WidgetUpdateMode::Bubble`] the update flags requested for the widget in `f` will be copied to the
231    /// caller widget context, otherwise they are ignored.
232    ///
233    /// [`is_widget`]: UiNode::is_widget
234    fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
235    where
236        F: FnOnce() -> R,
237    {
238        let _ = (update_mode, f);
239        None
240    }
241
242    /// Gets a [`BoxedUiNode`] that is a full widget.
243    ///
244    /// If this node [`is_widget`] returns `self` boxed. Otherwise returns a new minimal widget
245    /// that has `self` as a child node.
246    ///
247    /// Use this if you know that the widget is not a full widget or you don't mind that some
248    /// nodes become full widgets only after init, otherwise use [`init_widget`].
249    ///
250    /// [`is_widget`]: UiNode::is_widget
251    /// [`init_widget`]: UiNode::init_widget
252    fn into_widget(self) -> BoxedUiNode
253    where
254        Self: Sized,
255    {
256        if self.is_widget() {
257            return self.boxed();
258        }
259
260        into_widget! {
261            child = self;
262        }
263        .boxed()
264    }
265
266    /// Gets a [`BoxedUiNode`] that already is a full widget or will be after init and a response var that
267    /// already is the widget ID or will update once after init with the ID.
268    ///
269    /// If this node [`is_widget`] returns `self` boxed and an already responded var. Otherwise returns
270    /// a node that will ensure `self` is a full widget after init and update the response var with the
271    /// widget ID.
272    ///
273    /// Some nodes become full widgets only after init, the [`ArcNode::take_on_init`] for example, this node
274    /// supports these cases at the expense of having to reinit inside the generated widget when `self` is
275    /// not a full widget even after init.
276    ///
277    /// [`is_widget`]: UiNode::is_widget
278    /// [`ArcNode::take_on_init`]: crate::widget::node::ArcNode::take_on_init
279    fn init_widget(mut self) -> (BoxedUiNode, ResponseVar<WidgetId>)
280    where
281        Self: Sized,
282    {
283        if let Some(id) = self.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()) {
284            return (self.boxed(), crate::var::response_done_var(id));
285        }
286
287        let (responder, response) = crate::var::response_var();
288        let widget = match_widget(self.boxed(), move |c, op| {
289            if let UiNodeOp::Init = op {
290                c.init();
291                let widget_id = if let Some(id) = c.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()) {
292                    id
293                } else {
294                    c.deinit();
295                    let not_widget = std::mem::replace(c.child(), NilUiNode.boxed());
296                    *c.child() = not_widget.into_widget();
297
298                    c.init();
299                    c.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()).unwrap()
300                };
301
302                responder.respond(widget_id);
303            }
304        });
305        (widget.boxed(), response)
306    }
307
308    /// Downcast to `T`, if `self` is `T` or `self` is a [`BoxedUiNode`] that is `T`.
309    fn downcast_unbox<T: UiNode>(self) -> Result<T, BoxedUiNode>
310    where
311        Self: Sized,
312    {
313        let boxed = self.boxed();
314        if boxed.actual_type_id() == TypeId::of::<T>() {
315            Ok(*boxed.into_any_boxed().downcast().unwrap())
316        } else if TypeId::of::<T>() == TypeId::of::<BoxedUiNode>() {
317            Ok(*(Box::new(boxed) as Box<dyn Any>).downcast().unwrap())
318        } else {
319            Err(boxed)
320        }
321    }
322
323    /// Returns the [`type_id`] of the unboxed node.
324    ///
325    /// [`type_id`]: Any::type_id
326    fn actual_type_id(&self) -> TypeId {
327        self.type_id()
328    }
329
330    /// Access to `dyn Any` methods.
331    fn as_any(&self) -> &dyn Any
332    where
333        Self: Sized,
334    {
335        self
336    }
337
338    /// Access to mut `dyn Any` methods.
339    fn as_any_mut(&mut self) -> &mut dyn Any
340    where
341        Self: Sized,
342    {
343        self
344    }
345
346    /// Wraps the node in a node that, before delegating each method, calls a closure with
347    /// the [`UiNodeOpMethod`], the closure can return a *span* that is dropped after the method delegation.
348    ///
349    /// You can use the [`tracing`](https://docs.rs/tracing) crate to create the span.
350    fn trace<E, S>(self, mut enter_mtd: E) -> BoxedUiNode
351    where
352        Self: Sized,
353        E: FnMut(UiNodeOpMethod) -> S + Send + 'static,
354    {
355        match_node(self, move |node, op| {
356            let _span = enter_mtd(op.mtd());
357            node.op(op);
358        })
359        .boxed()
360    }
361
362    /// Runs the [ `UiNodeOp`].
363    fn op(&mut self, op: UiNodeOp) {
364        match op {
365            UiNodeOp::Init => self.init(),
366            UiNodeOp::Deinit => self.deinit(),
367            UiNodeOp::Info { info } => self.info(info),
368            UiNodeOp::Event { update } => self.event(update),
369            UiNodeOp::Update { updates } => self.update(updates),
370            UiNodeOp::Measure { wm, desired_size } => *desired_size = self.measure(wm),
371            UiNodeOp::Layout { wl, final_size } => *final_size = self.layout(wl),
372            UiNodeOp::Render { frame } => self.render(frame),
373            UiNodeOp::RenderUpdate { update } => self.render_update(update),
374        }
375    }
376}
377
378/// See [`UiNode::into_widget`]
379#[expect(non_camel_case_types)]
380#[widget($crate::widget::node::into_widget)]
381struct into_widget(crate::widget::base::WidgetBase);
382#[zng_app_proc_macros::property(CHILD, capture, widget_impl(into_widget))]
383fn child(child: impl UiNode) {}
384impl into_widget {
385    fn widget_intrinsic(&mut self) {
386        self.widget_builder().push_build_action(|b| {
387            let child = b.capture_ui_node(crate::property_id!(Self::child)).unwrap();
388            b.set_child(child);
389        });
390    }
391}
392
393/// Represents a list of UI nodes.
394///
395/// There are multiple node list types, panel implementers receive children as `impl UiNodeList` and usually wrap it in a [`PanelList`].
396///
397/// UI node lists delegate the [`UiNode`] method for each node in the list, potentially in parallel. Panel implementers call the `*_all`
398/// methods to delegate, they can also use the [`match_node_list`] to implement delegation. The trait also offers [`for_each`], [`par_each`]
399/// and other methods for direct access to the nodes, both sequentially and in parallel.
400///
401/// Note that trying to access the nodes before init will probably not work, the [`ArcNodeList`] type is used by properties that request
402/// `impl UiNodeList` input, so captured property lists will always be empty before init.
403///
404/// [`for_each`]: UiNodeList::for_each
405/// [`par_each`]: UiNodeList::par_each
406pub trait UiNodeList: UiNodeListBoxed {
407    /// Visit the specific node.
408    ///
409    /// # Panics
410    ///
411    /// Panics if `index` is out of bounds.
412    fn with_node<R, F>(&mut self, index: usize, f: F) -> R
413    where
414        F: FnOnce(&mut BoxedUiNode) -> R;
415
416    /// Calls `f` for each node in the list with the index, sequentially.
417    fn for_each<F>(&mut self, f: F)
418    where
419        F: FnMut(usize, &mut BoxedUiNode);
420
421    /// Calls `f` for each node in the list with the index, in parallel.
422    fn par_each<F>(&mut self, f: F)
423    where
424        F: Fn(usize, &mut BoxedUiNode) + Send + Sync;
425
426    /// Calls `fold` for each node in the list in parallel, with fold accumulators produced by `identity`, then merges the folded results
427    /// using `reduce` to produce the final value also in parallel.
428    ///
429    /// If `reduce` is [associative] the order is preserved in the result.
430    ///
431    /// # Example
432    ///
433    /// This example will collect the node indexes in order:
434    ///
435    /// ```
436    /// # use zng_app::widget::node::UiNodeList;
437    /// # fn demo(mut list: impl UiNodeList) -> Vec<usize> {
438    /// list.par_fold_reduce(
439    ///     Vec::new,
440    ///     |mut v, i, _| {
441    ///         v.push(i);
442    ///         v
443    ///     },
444    ///     |mut a, b| {
445    ///         a.extend(b);
446    ///         a
447    ///     },
448    /// )
449    /// # }
450    /// ```
451    ///
452    /// [associative]: https://en.wikipedia.org/wiki/Associative_property
453    fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, reduce: R) -> T
454    where
455        T: Send + 'static,
456        I: Fn() -> T + Send + Sync,
457        F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
458        R: Fn(T, T) -> T + Send + Sync;
459
460    /// Gets the current number of nodes in the list.
461    fn len(&self) -> usize;
462
463    /// Returns `true` if the list does not contain any nodes.
464    fn is_empty(&self) -> bool {
465        self.len() == 0
466    }
467
468    /// Gets `self` boxed, or itself if it is already boxed.
469    fn boxed(self) -> BoxedUiNodeList;
470
471    /// Move all nodes into `vec`.
472    fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>);
473
474    /// Init the list in a context, all nodes are also inited.
475    ///
476    /// The behavior of some list implementations depend on this call, manually initializing nodes is an error.
477    fn init_all(&mut self) {
478        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::INIT) {
479            self.par_each(|_, c| {
480                c.init();
481            });
482        } else {
483            self.for_each(|_, c| {
484                c.init();
485            })
486        }
487    }
488
489    /// Deinit the list in a context, all nodes are also deinited.
490    ///
491    /// The behavior of some list implementations depend on this call, manually deiniting nodes is an error.
492    fn deinit_all(&mut self) {
493        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::DEINIT) {
494            self.par_each(|_, c| {
495                c.deinit();
496            });
497        } else {
498            self.for_each(|_, c| {
499                c.deinit();
500            });
501        }
502    }
503
504    /// Rebuilds the list in a context, all node info is rebuilt.
505    fn info_all(&mut self, info: &mut WidgetInfoBuilder) {
506        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::INFO) {
507            let p_info = self.par_fold_reduce(
508                || info.parallel_split(),
509                |mut info, _, node| {
510                    node.info(&mut info);
511                    info
512                },
513                |mut a, b| {
514                    a.parallel_fold(b);
515                    a
516                },
517            );
518            info.parallel_fold(p_info);
519        } else {
520            self.for_each(|_, c| {
521                c.info(info);
522            });
523        }
524    }
525
526    /// Receive updates for the list in a context, all nodes are also updated.
527    ///
528    /// The behavior of some list implementations depend on this call, manually updating nodes is an error.
529    fn update_all(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
530        let _ = observer;
531
532        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::UPDATE) {
533            self.par_each(|_, c| {
534                c.update(updates);
535            });
536        } else {
537            self.for_each(|_, c| {
538                c.update(updates);
539            });
540        }
541    }
542
543    /// Receive an event for the list in a context, all nodes are also notified.
544    ///
545    /// The behavior of some list implementations depend on this call, manually notifying nodes is an error.
546    fn event_all(&mut self, update: &EventUpdate) {
547        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::EVENT) {
548            self.par_each(|_, c| {
549                c.event(update);
550            });
551        } else {
552            self.for_each(|_, c| {
553                c.event(update);
554            });
555        }
556    }
557
558    /// Call `measure` for each node and combines the final size using `fold_size`.
559    ///
560    /// The call to `measure` can be parallel if [`Parallel::LAYOUT`] is enabled.
561    #[must_use]
562    fn measure_each<F, S>(&mut self, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
563    where
564        F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
565        S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
566        Self: Sized,
567    {
568        default_measure_each(self, wm, measure, fold_size)
569    }
570
571    /// Call `layout` for each node and combines the final size using `fold_size`.
572    ///
573    /// The call to `layout` can be parallel if [`Parallel::LAYOUT`] is enabled.
574    #[must_use]
575    fn layout_each<F, S>(&mut self, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
576    where
577        F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
578        S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
579        Self: Sized,
580    {
581        default_layout_each(self, wl, layout, fold_size)
582    }
583
584    /// Render all nodes.
585    ///
586    /// The correct behavior of some list implementations depend on this call, using [`for_each`] to render nodes can
587    /// break it.
588    ///
589    /// [`for_each`]: UiNodeList::for_each
590    fn render_all(&mut self, frame: &mut FrameBuilder) {
591        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::RENDER) {
592            let p_frame = self.par_fold_reduce(
593                || frame.parallel_split(),
594                |mut frame, _, node| {
595                    node.render(&mut frame);
596                    frame
597                },
598                |mut a, b| {
599                    a.parallel_fold(b);
600                    a
601                },
602            );
603            frame.parallel_fold(p_frame);
604        } else {
605            self.for_each(|_, c| {
606                c.render(frame);
607            })
608        }
609    }
610
611    /// Render all nodes.
612    ///
613    /// The correct behavior of some list implementations depend on this call, using [`for_each`] to render nodes can
614    /// break it.
615    ///
616    /// [`for_each`]: UiNodeList::for_each
617    fn render_update_all(&mut self, update: &mut FrameUpdate) {
618        if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::RENDER) {
619            let p_update = self.par_fold_reduce(
620                || update.parallel_split(),
621                |mut update, _, node| {
622                    node.render_update(&mut update);
623                    update
624                },
625                |mut a, b| {
626                    a.parallel_fold(b);
627                    a
628                },
629            );
630            update.parallel_fold(p_update);
631        } else {
632            self.for_each(|_, c| {
633                c.render_update(update);
634            })
635        }
636    }
637    /// Downcast to `L`, if `self` is `L` or is a [`BoxedUiNodeList`] that is `L`.
638    fn downcast_unbox<L: UiNodeList>(self) -> Result<L, BoxedUiNodeList>
639    where
640        Self: Sized,
641    {
642        let boxed = self.boxed();
643        if boxed.actual_type_id() == TypeId::of::<L>() {
644            Ok(*boxed.into_any_boxed().downcast().unwrap())
645        } else if TypeId::of::<L>() == TypeId::of::<BoxedUiNodeList>() {
646            Ok(*(Box::new(boxed) as Box<dyn Any>).downcast().unwrap())
647        } else {
648            Err(boxed)
649        }
650    }
651
652    /// Returns the [`type_id`] of the unboxed list.
653    ///
654    /// [`type_id`]: Any::type_id
655    fn actual_type_id(&self) -> TypeId {
656        self.type_id()
657    }
658
659    /// Access to mut `dyn Any` methods.
660    fn as_any(&mut self) -> &mut dyn Any
661    where
662        Self: Sized,
663    {
664        self
665    }
666
667    /// Runs the [`UiNodeOp`].
668    fn op(&mut self, op: UiNodeOp)
669    where
670        Self: Sized,
671    {
672        match op {
673            UiNodeOp::Init => ui_node_list_default::init_all(self),
674            UiNodeOp::Deinit => ui_node_list_default::deinit_all(self),
675            UiNodeOp::Info { info } => ui_node_list_default::info_all(self, info),
676            UiNodeOp::Event { update } => ui_node_list_default::event_all(self, update),
677            UiNodeOp::Update { updates } => ui_node_list_default::update_all(self, updates),
678            UiNodeOp::Measure { wm, desired_size } => *desired_size = ui_node_list_default::measure_all(self, wm),
679            UiNodeOp::Layout { wl, final_size } => *final_size = ui_node_list_default::layout_all(self, wl),
680            UiNodeOp::Render { frame } => ui_node_list_default::render_all(self, frame),
681            UiNodeOp::RenderUpdate { update } => ui_node_list_default::render_update_all(self, update),
682        }
683    }
684}
685
686fn default_measure_each<F, S>(self_: &mut impl UiNodeList, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
687where
688    F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
689    S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
690{
691    #[cfg(feature = "dyn_closure")]
692    let measure: Box<dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync> = Box::new(measure);
693    #[cfg(feature = "dyn_closure")]
694    let fold_size: Box<dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync> = Box::new(fold_size);
695
696    default_measure_each_impl(self_, wm, measure, fold_size)
697}
698fn default_measure_each_impl<F, S>(self_: &mut impl UiNodeList, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
699where
700    F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
701    S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
702{
703    if self_.len() > 1 && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
704        // fold a tuple of `(wm, size)`
705        let (pwm, size) = self_.par_fold_reduce(
706            || (wm.parallel_split(), PxSize::zero()),
707            |(mut a_wm, a_size), i, n| {
708                let b_size = measure(i, n, &mut a_wm);
709                (a_wm, fold_size(a_size, b_size))
710            },
711            |(mut awm, a_size), (bwm, b_size)| {
712                (
713                    {
714                        awm.parallel_fold(bwm);
715                        awm
716                    },
717                    fold_size(a_size, b_size),
718                )
719            },
720        );
721        wm.parallel_fold(pwm);
722        size
723    } else {
724        let mut size = PxSize::zero();
725        self_.for_each(|i, n| {
726            let b = measure(i, n, wm);
727            size = fold_size(size, b);
728        });
729        size
730    }
731}
732
733fn default_layout_each<F, S>(self_: &mut impl UiNodeList, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
734where
735    F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
736    S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
737{
738    #[cfg(feature = "dyn_closure")]
739    let layout: Box<dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync> = Box::new(layout);
740    #[cfg(feature = "dyn_closure")]
741    let fold_size: Box<dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync> = Box::new(fold_size);
742
743    default_layout_each_impl(self_, wl, layout, fold_size)
744}
745fn default_layout_each_impl<F, S>(self_: &mut impl UiNodeList, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
746where
747    F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
748    S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
749{
750    if self_.len() > 1 && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
751        // fold a tuple of `(wl, size)`
752        let (pwl, size) = self_.par_fold_reduce(
753            || (wl.parallel_split(), PxSize::zero()),
754            |(mut awl, a_size), i, n| {
755                let b_size = layout(i, n, &mut awl);
756                (awl, fold_size(a_size, b_size))
757            },
758            |(mut awl, a_size), (bwl, b_size)| {
759                (
760                    {
761                        awl.parallel_fold(bwl);
762                        awl
763                    },
764                    fold_size(a_size, b_size),
765                )
766            },
767        );
768        wl.parallel_fold(pwl);
769        size
770    } else {
771        let mut size = PxSize::zero();
772        self_.for_each(|i, n| {
773            let b = layout(i, n, wl);
774            size = fold_size(size, b);
775        });
776        size
777    }
778}
779
780#[doc(hidden)]
781pub mod ui_node_list_default {
782    use super::*;
783
784    pub fn init_all(list: &mut impl UiNodeList) {
785        list.init_all();
786    }
787
788    pub fn deinit_all(list: &mut impl UiNodeList) {
789        list.deinit_all();
790    }
791
792    pub fn info_all(list: &mut impl UiNodeList, info: &mut WidgetInfoBuilder) {
793        list.info_all(info)
794    }
795
796    pub fn event_all(list: &mut impl UiNodeList, update: &EventUpdate) {
797        list.event_all(update);
798    }
799
800    pub fn update_all(list: &mut impl UiNodeList, updates: &WidgetUpdates) {
801        let mut changed = false;
802
803        list.update_all(updates, &mut changed);
804
805        if changed {
806            WIDGET.layout().render();
807        }
808    }
809
810    pub fn measure_all(list: &mut impl UiNodeList, wm: &mut WidgetMeasure) -> PxSize {
811        list.measure_each(wm, |_, n, wm| n.measure(wm), PxSize::max)
812    }
813
814    pub fn layout_all(list: &mut impl UiNodeList, wl: &mut WidgetLayout) -> PxSize {
815        list.layout_each(wl, |_, n, wl| n.layout(wl), PxSize::max)
816    }
817
818    pub fn render_all(list: &mut impl UiNodeList, frame: &mut FrameBuilder) {
819        list.render_all(frame);
820    }
821
822    pub fn render_update_all(list: &mut impl UiNodeList, update: &mut FrameUpdate) {
823        list.render_update_all(update)
824    }
825}
826
827#[doc(hidden)]
828pub trait UiNodeBoxed: Any + Send {
829    fn info_boxed(&mut self, info: &mut WidgetInfoBuilder);
830    fn init_boxed(&mut self);
831    fn deinit_boxed(&mut self);
832    fn update_boxed(&mut self, updates: &WidgetUpdates);
833    fn event_boxed(&mut self, update: &EventUpdate);
834    fn measure_boxed(&mut self, wm: &mut WidgetMeasure) -> PxSize;
835    fn layout_boxed(&mut self, wl: &mut WidgetLayout) -> PxSize;
836    fn render_boxed(&mut self, frame: &mut FrameBuilder);
837    fn render_update_boxed(&mut self, update: &mut FrameUpdate);
838
839    fn is_widget_boxed(&self) -> bool;
840    fn is_nil_boxed(&self) -> bool;
841    fn with_context_boxed(&mut self, update_mode: WidgetUpdateMode, f: &mut dyn FnMut());
842    fn into_widget_boxed(self: Box<Self>) -> BoxedUiNode;
843    fn as_any_boxed(&self) -> &dyn Any;
844    fn as_any_mut_boxed(&mut self) -> &mut dyn Any;
845
846    fn actual_type_id_boxed(&self) -> TypeId;
847    fn into_any_boxed(self: Box<Self>) -> Box<dyn Any>;
848}
849
850impl<U: UiNode> UiNodeBoxed for U {
851    fn info_boxed(&mut self, info: &mut WidgetInfoBuilder) {
852        self.info(info);
853    }
854
855    fn init_boxed(&mut self) {
856        self.init();
857    }
858
859    fn deinit_boxed(&mut self) {
860        self.deinit();
861    }
862
863    fn update_boxed(&mut self, updates: &WidgetUpdates) {
864        self.update(updates);
865    }
866
867    fn event_boxed(&mut self, update: &EventUpdate) {
868        self.event(update);
869    }
870
871    fn measure_boxed(&mut self, wm: &mut WidgetMeasure) -> PxSize {
872        self.measure(wm)
873    }
874
875    fn layout_boxed(&mut self, wl: &mut WidgetLayout) -> PxSize {
876        self.layout(wl)
877    }
878
879    fn render_boxed(&mut self, frame: &mut FrameBuilder) {
880        self.render(frame);
881    }
882
883    fn render_update_boxed(&mut self, update: &mut FrameUpdate) {
884        self.render_update(update);
885    }
886
887    fn is_widget_boxed(&self) -> bool {
888        self.is_widget()
889    }
890
891    fn is_nil_boxed(&self) -> bool {
892        self.is_nil()
893    }
894
895    fn into_widget_boxed(self: Box<Self>) -> BoxedUiNode {
896        self.into_widget()
897    }
898
899    fn actual_type_id_boxed(&self) -> TypeId {
900        self.type_id()
901    }
902
903    fn into_any_boxed(self: Box<Self>) -> Box<dyn Any> {
904        self
905    }
906
907    fn with_context_boxed(&mut self, update_mode: WidgetUpdateMode, f: &mut dyn FnMut()) {
908        self.with_context(update_mode, f);
909    }
910
911    fn as_any_boxed(&self) -> &dyn Any {
912        self.as_any()
913    }
914
915    fn as_any_mut_boxed(&mut self) -> &mut dyn Any {
916        self.as_any_mut()
917    }
918}
919
920#[doc(hidden)]
921pub trait UiNodeListBoxed: Any + Send {
922    fn with_node_boxed(&mut self, index: usize, f: &mut dyn FnMut(&mut BoxedUiNode));
923    fn for_each_boxed(&mut self, f: &mut dyn FnMut(usize, &mut BoxedUiNode));
924    fn par_each_boxed(&mut self, f: &(dyn Fn(usize, &mut BoxedUiNode) + Send + Sync));
925    fn par_fold_reduce_boxed(
926        &mut self,
927        identity: &(dyn Fn() -> Box<dyn Any + Send> + Send + Sync),
928        fold: &(dyn Fn(Box<dyn Any + Send>, usize, &mut BoxedUiNode) -> Box<dyn Any + Send> + Send + Sync),
929        reduce: &(dyn Fn(Box<dyn Any + Send>, Box<dyn Any + Send>) -> Box<dyn Any + Send> + Send + Sync),
930    ) -> Box<dyn Any + Send>;
931    fn measure_each_boxed(
932        &mut self,
933        wm: &mut WidgetMeasure,
934        measure: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync),
935        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
936    ) -> PxSize;
937    fn layout_each_boxed(
938        &mut self,
939        wl: &mut WidgetLayout,
940        layout: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync),
941        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
942    ) -> PxSize;
943    fn len_boxed(&self) -> usize;
944    fn drain_into_boxed(&mut self, vec: &mut Vec<BoxedUiNode>);
945    fn init_all_boxed(&mut self);
946    fn deinit_all_boxed(&mut self);
947    fn info_all_boxed(&mut self, info: &mut WidgetInfoBuilder);
948    fn event_all_boxed(&mut self, update: &EventUpdate);
949    fn update_all_boxed(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver);
950    fn render_all_boxed(&mut self, frame: &mut FrameBuilder);
951    fn render_update_all_boxed(&mut self, update: &mut FrameUpdate);
952    fn actual_type_id_boxed(&self) -> TypeId;
953    fn into_any_boxed(self: Box<Self>) -> Box<dyn Any>;
954    fn as_any_boxed(&mut self) -> &mut dyn Any;
955}
956impl<L: UiNodeList> UiNodeListBoxed for L {
957    fn with_node_boxed(&mut self, index: usize, f: &mut dyn FnMut(&mut BoxedUiNode)) {
958        self.with_node(index, f)
959    }
960
961    fn for_each_boxed(&mut self, f: &mut dyn FnMut(usize, &mut BoxedUiNode)) {
962        self.for_each(f);
963    }
964
965    fn par_each_boxed(&mut self, f: &(dyn Fn(usize, &mut BoxedUiNode) + Send + Sync)) {
966        self.par_each(f)
967    }
968
969    fn par_fold_reduce_boxed(
970        &mut self,
971        identity: &(dyn Fn() -> Box<dyn Any + Send> + Send + Sync),
972        fold: &(dyn Fn(Box<dyn Any + Send>, usize, &mut BoxedUiNode) -> Box<dyn Any + Send> + Send + Sync),
973        reduce: &(dyn Fn(Box<dyn Any + Send>, Box<dyn Any + Send>) -> Box<dyn Any + Send> + Send + Sync),
974    ) -> Box<dyn Any + Send> {
975        self.par_fold_reduce(identity, fold, reduce)
976    }
977
978    fn measure_each_boxed(
979        &mut self,
980        wm: &mut WidgetMeasure,
981        measure: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync),
982        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
983    ) -> PxSize {
984        self.measure_each(wm, measure, fold_size)
985    }
986
987    fn layout_each_boxed(
988        &mut self,
989        wl: &mut WidgetLayout,
990        layout: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync),
991        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
992    ) -> PxSize {
993        self.layout_each(wl, layout, fold_size)
994    }
995
996    fn len_boxed(&self) -> usize {
997        self.len()
998    }
999
1000    fn drain_into_boxed(&mut self, vec: &mut Vec<BoxedUiNode>) {
1001        self.drain_into(vec)
1002    }
1003
1004    fn init_all_boxed(&mut self) {
1005        self.init_all();
1006    }
1007
1008    fn deinit_all_boxed(&mut self) {
1009        self.deinit_all();
1010    }
1011
1012    fn info_all_boxed(&mut self, info: &mut WidgetInfoBuilder) {
1013        self.info_all(info);
1014    }
1015
1016    fn event_all_boxed(&mut self, update: &EventUpdate) {
1017        self.event_all(update);
1018    }
1019
1020    fn update_all_boxed(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1021        self.update_all(updates, observer);
1022    }
1023
1024    fn render_all_boxed(&mut self, frame: &mut FrameBuilder) {
1025        self.render_all(frame);
1026    }
1027
1028    fn render_update_all_boxed(&mut self, update: &mut FrameUpdate) {
1029        self.render_update_all(update);
1030    }
1031
1032    fn actual_type_id_boxed(&self) -> TypeId {
1033        self.type_id()
1034    }
1035
1036    fn into_any_boxed(self: Box<Self>) -> Box<dyn Any> {
1037        self
1038    }
1039
1040    fn as_any_boxed(&mut self) -> &mut dyn Any {
1041        self.as_any()
1042    }
1043}
1044
1045/// An [`UiNode`] in a box.
1046pub type BoxedUiNode = Box<dyn UiNodeBoxed>;
1047
1048/// An [`UiNodeList`] in a box.
1049pub type BoxedUiNodeList = Box<dyn UiNodeListBoxed>;
1050
1051impl UiNode for BoxedUiNode {
1052    fn info(&mut self, info: &mut WidgetInfoBuilder) {
1053        self.as_mut().info_boxed(info);
1054    }
1055
1056    fn init(&mut self) {
1057        self.as_mut().init_boxed();
1058    }
1059
1060    fn deinit(&mut self) {
1061        self.as_mut().deinit_boxed();
1062    }
1063
1064    fn update(&mut self, updates: &WidgetUpdates) {
1065        self.as_mut().update_boxed(updates);
1066    }
1067
1068    fn event(&mut self, update: &EventUpdate) {
1069        self.as_mut().event_boxed(update);
1070    }
1071
1072    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1073        self.as_mut().measure_boxed(wm)
1074    }
1075
1076    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1077        self.as_mut().layout_boxed(wl)
1078    }
1079
1080    fn render(&mut self, frame: &mut FrameBuilder) {
1081        self.as_mut().render_boxed(frame);
1082    }
1083
1084    fn render_update(&mut self, update: &mut FrameUpdate) {
1085        self.as_mut().render_update_boxed(update);
1086    }
1087
1088    fn boxed(self) -> BoxedUiNode
1089    where
1090        Self: Sized,
1091    {
1092        self
1093    }
1094
1095    fn actual_type_id(&self) -> TypeId {
1096        self.as_ref().actual_type_id_boxed()
1097    }
1098
1099    fn is_widget(&self) -> bool {
1100        self.as_ref().is_widget_boxed()
1101    }
1102
1103    fn is_nil(&self) -> bool {
1104        self.as_ref().is_nil_boxed()
1105    }
1106
1107    fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
1108    where
1109        F: FnOnce() -> R,
1110    {
1111        let mut f = Some(f);
1112        let mut r = None;
1113        self.as_mut()
1114            .with_context_boxed(update_mode, &mut || r = Some((f.take().unwrap())()));
1115        r
1116    }
1117
1118    fn into_widget(self) -> BoxedUiNode
1119    where
1120        Self: Sized,
1121    {
1122        self.into_widget_boxed()
1123    }
1124
1125    fn as_any(&self) -> &dyn Any
1126    where
1127        Self: Sized,
1128    {
1129        self.as_ref().as_any_boxed()
1130    }
1131
1132    fn as_any_mut(&mut self) -> &mut dyn Any
1133    where
1134        Self: Sized,
1135    {
1136        self.as_mut().as_any_mut_boxed()
1137    }
1138}
1139
1140impl UiNodeList for BoxedUiNodeList {
1141    fn with_node<R, F>(&mut self, index: usize, f: F) -> R
1142    where
1143        F: FnOnce(&mut BoxedUiNode) -> R,
1144    {
1145        let mut f = Some(f);
1146        let mut r = None;
1147        self.as_mut().with_node_boxed(index, &mut |n| r = Some((f.take().unwrap())(n)));
1148        r.unwrap()
1149    }
1150
1151    fn for_each<F>(&mut self, mut f: F)
1152    where
1153        F: FnMut(usize, &mut BoxedUiNode),
1154    {
1155        self.as_mut().for_each_boxed(&mut f)
1156    }
1157
1158    fn par_each<F>(&mut self, f: F)
1159    where
1160        F: Fn(usize, &mut BoxedUiNode) + Send + Sync,
1161    {
1162        self.as_mut().par_each_boxed(&f)
1163    }
1164
1165    fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, reduce: R) -> T
1166    where
1167        T: Send + 'static,
1168        I: Fn() -> T + Send + Sync,
1169        F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
1170        R: Fn(T, T) -> T + Send + Sync,
1171    {
1172        self.as_mut()
1173            .par_fold_reduce_boxed(
1174                &move || Box::new(Some(identity())),
1175                &move |mut r, i, n| {
1176                    let r_mut = r.downcast_mut::<Option<T>>().unwrap();
1177                    *r_mut = Some(fold(r_mut.take().unwrap(), i, n));
1178                    r
1179                },
1180                &|mut a, b| {
1181                    let a_mut = a.downcast_mut::<Option<T>>().unwrap();
1182                    *a_mut = Some(reduce(a_mut.take().unwrap(), b.downcast::<Option<T>>().unwrap().unwrap()));
1183                    a
1184                },
1185            )
1186            .downcast::<Option<T>>()
1187            .unwrap()
1188            .unwrap()
1189    }
1190
1191    fn len(&self) -> usize {
1192        self.as_ref().len_boxed()
1193    }
1194
1195    fn boxed(self) -> BoxedUiNodeList {
1196        self
1197    }
1198
1199    fn actual_type_id(&self) -> TypeId {
1200        self.as_ref().actual_type_id_boxed()
1201    }
1202
1203    fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>) {
1204        self.as_mut().drain_into_boxed(vec)
1205    }
1206
1207    fn init_all(&mut self) {
1208        self.as_mut().init_all_boxed();
1209    }
1210
1211    fn deinit_all(&mut self) {
1212        self.as_mut().deinit_all_boxed();
1213    }
1214
1215    fn update_all(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1216        self.as_mut().update_all_boxed(updates, observer);
1217    }
1218
1219    fn info_all(&mut self, info: &mut WidgetInfoBuilder) {
1220        self.as_mut().info_all_boxed(info);
1221    }
1222
1223    fn event_all(&mut self, update: &EventUpdate) {
1224        self.as_mut().event_all_boxed(update);
1225    }
1226
1227    fn render_all(&mut self, frame: &mut FrameBuilder) {
1228        self.as_mut().render_all_boxed(frame);
1229    }
1230
1231    fn render_update_all(&mut self, update: &mut FrameUpdate) {
1232        self.as_mut().render_update_all_boxed(update);
1233    }
1234
1235    fn measure_each<F, S>(&mut self, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
1236    where
1237        F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
1238        S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
1239    {
1240        self.as_mut().measure_each_boxed(wm, &measure, &fold_size)
1241    }
1242
1243    fn layout_each<F, S>(&mut self, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
1244    where
1245        F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
1246        S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
1247    {
1248        self.as_mut().layout_each_boxed(wl, &layout, &fold_size)
1249    }
1250
1251    fn as_any(&mut self) -> &mut dyn Any
1252    where
1253        Self: Sized,
1254    {
1255        self.as_mut().as_any_boxed()
1256    }
1257}
1258
1259impl<U: UiNode> UiNode for Option<U> {
1260    fn info(&mut self, info: &mut WidgetInfoBuilder) {
1261        if let Some(node) = self {
1262            node.info(info);
1263        }
1264    }
1265
1266    fn init(&mut self) {
1267        if let Some(node) = self {
1268            node.init();
1269        }
1270    }
1271
1272    fn deinit(&mut self) {
1273        if let Some(node) = self {
1274            node.deinit();
1275        }
1276    }
1277
1278    fn event(&mut self, update: &EventUpdate) {
1279        if let Some(node) = self {
1280            node.event(update);
1281        }
1282    }
1283
1284    fn update(&mut self, updates: &WidgetUpdates) {
1285        if let Some(node) = self {
1286            node.update(updates);
1287        }
1288    }
1289
1290    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1291        if let Some(node) = self { node.measure(wm) } else { PxSize::zero() }
1292    }
1293
1294    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1295        if let Some(node) = self { node.layout(wl) } else { PxSize::zero() }
1296    }
1297
1298    fn render(&mut self, frame: &mut FrameBuilder) {
1299        if let Some(node) = self {
1300            node.render(frame);
1301        }
1302    }
1303
1304    fn render_update(&mut self, update: &mut FrameUpdate) {
1305        if let Some(node) = self {
1306            node.render_update(update);
1307        }
1308    }
1309
1310    fn boxed(self) -> BoxedUiNode
1311    where
1312        Self: Sized,
1313    {
1314        match self {
1315            Some(node) => node.boxed(),
1316            None => NilUiNode.boxed(),
1317        }
1318    }
1319
1320    fn is_widget(&self) -> bool {
1321        match self {
1322            Some(node) => node.is_widget(),
1323            None => false,
1324        }
1325    }
1326
1327    fn is_nil(&self) -> bool {
1328        self.is_none()
1329    }
1330
1331    fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
1332    where
1333        F: FnOnce() -> R,
1334    {
1335        match self {
1336            Some(node) => node.with_context(update_mode, f),
1337            None => None,
1338        }
1339    }
1340
1341    fn into_widget(self) -> BoxedUiNode
1342    where
1343        Self: Sized,
1344    {
1345        match self {
1346            Some(node) => node.into_widget(),
1347            None => NilUiNode.into_widget(),
1348        }
1349    }
1350}
1351
1352impl UiNodeList for Option<BoxedUiNode> {
1353    fn with_node<R, F>(&mut self, index: usize, f: F) -> R
1354    where
1355        F: FnOnce(&mut BoxedUiNode) -> R,
1356    {
1357        match self {
1358            Some(node) => {
1359                assert_bounds(1, index);
1360                f(node)
1361            }
1362            None => {
1363                assert_bounds(0, index);
1364                unreachable!()
1365            }
1366        }
1367    }
1368
1369    fn for_each<F>(&mut self, mut f: F)
1370    where
1371        F: FnMut(usize, &mut BoxedUiNode),
1372    {
1373        if let Some(node) = self {
1374            f(0, node);
1375        }
1376    }
1377
1378    fn par_each<F>(&mut self, f: F)
1379    where
1380        F: Fn(usize, &mut BoxedUiNode) + Send + Sync,
1381    {
1382        if let Some(node) = self {
1383            f(0, node);
1384        }
1385    }
1386
1387    fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, _: R) -> T
1388    where
1389        T: Send,
1390        I: Fn() -> T + Send + Sync,
1391        F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
1392        R: Fn(T, T) -> T + Send + Sync,
1393    {
1394        if let Some(node) = self {
1395            fold(identity(), 0, node)
1396        } else {
1397            identity()
1398        }
1399    }
1400
1401    fn len(&self) -> usize {
1402        match self {
1403            Some(_) => 1,
1404            None => 0,
1405        }
1406    }
1407
1408    fn boxed(self) -> BoxedUiNodeList {
1409        Box::new(self)
1410    }
1411
1412    fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>) {
1413        if let Some(n) = self.take() {
1414            vec.push(n);
1415        }
1416    }
1417}
1418
1419fn assert_bounds(len: usize, i: usize) {
1420    if i >= len {
1421        panic!("index `{i}` is >= len `{len}`")
1422    }
1423}
1424
1425/// A UI node that does nothing and has collapsed layout (zero size).
1426pub struct NilUiNode;
1427#[super::ui_node(none)]
1428impl UiNode for NilUiNode {
1429    fn measure(&mut self, _: &mut WidgetMeasure) -> PxSize {
1430        PxSize::zero()
1431    }
1432
1433    fn layout(&mut self, _: &mut WidgetLayout) -> PxSize {
1434        PxSize::zero()
1435    }
1436
1437    fn is_nil(&self) -> bool {
1438        true
1439    }
1440}
1441
1442/// A UI node that fills the available layout space.
1443///
1444/// The space is blank, the node does nothing other then layout to fill.
1445pub struct FillUiNode;
1446#[ui_node(none)]
1447impl UiNode for FillUiNode {}
1448
1449/// Wraps `child` in a node that provides a unique [`ContextInitHandle`], refreshed every (re)init.
1450///
1451/// [`ContextInitHandle`]: zng_var::ContextInitHandle
1452pub fn with_new_context_init_id(child: impl UiNode) -> impl UiNode {
1453    let mut id = None;
1454
1455    match_node(child, move |child, op| {
1456        let is_deinit = matches!(op, UiNodeOp::Deinit);
1457        id.get_or_insert_with(ContextInitHandle::new).with_context(|| child.op(op));
1458
1459        if is_deinit {
1460            id = None;
1461        }
1462    })
1463}
1464
1465#[cfg(test)]
1466mod tests {
1467    use super::*;
1468
1469    #[test]
1470    pub fn downcast_unbox() {
1471        fn node() -> impl UiNode {
1472            NilUiNode
1473        }
1474
1475        assert!(node().downcast_unbox::<NilUiNode>().is_ok())
1476    }
1477
1478    #[test]
1479    pub fn downcast_unbox_boxed() {
1480        fn node() -> BoxedUiNode {
1481            NilUiNode.boxed()
1482        }
1483
1484        assert!(node().downcast_unbox::<NilUiNode>().is_ok())
1485    }
1486
1487    #[test]
1488    pub fn downcast_unbox_to_boxed() {
1489        fn node() -> impl UiNode {
1490            NilUiNode.boxed()
1491        }
1492
1493        assert!(node().downcast_unbox::<BoxedUiNode>().is_ok())
1494    }
1495
1496    #[test]
1497    pub fn downcast_unbox_widget() {
1498        fn node() -> BoxedUiNode {
1499            NilUiNode.into_widget()
1500        }
1501
1502        assert!(node().downcast_unbox::<BoxedUiNode>().is_ok())
1503    }
1504}