zng_app/widget/
node.rs

1//! Widget nodes types, [`UiNode`], [`UiVec`] and others.
2
3use std::{any::Any, ops::ControlFlow};
4
5mod adopt;
6pub use adopt::*;
7
8mod arc;
9pub use arc::*;
10
11mod extend;
12pub use extend::*;
13
14mod match_node;
15pub use match_node::*;
16
17mod when;
18pub use when::*;
19
20mod trace;
21
22mod list;
23pub use list::*;
24use zng_app_proc_macros::widget;
25use zng_layout::{context::LAYOUT, unit::PxSize};
26use zng_var::{BoxAnyVarValue, ContextInitHandle, ResponseVar, response_done_var, response_var};
27
28use crate::{
29    render::{FrameBuilder, FrameUpdate},
30    update::{EventUpdate, WidgetUpdates},
31};
32
33use super::{
34    WIDGET, WidgetId, WidgetUpdateMode,
35    info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
36};
37
38macro_rules! debug_warn_list {
39    ($self:ident, $op:tt) => {
40        #[cfg(debug_assertions)]
41        {
42            if $self.is_list() {
43                let op = $op;
44                tracing::warn!("UiNodeImpl is_list without implementing `{op}`");
45            }
46        }
47    };
48}
49
50/// Represents an [`UiNode`] implementation.
51///
52/// You can use the [`match_node`] helper to quickly declare a new node from a closure, most property nodes are implemented
53/// using the match helpers. For more advanced nodes you can manually implement this trait.
54pub trait UiNodeImpl: Any + Send {
55    /// Gets the current count of children nodes.
56    fn children_len(&self) -> usize;
57
58    /// Gets if the node represents a list of other nodes.
59    ///
60    /// If `true` the node provides only minimal layout implementations and expects the caller
61    /// to use [`measure_list`], [`layout_list`] or direct access to child nodes for layout.
62    ///
63    /// If `true` the node must implement all methods that iterate over children, for better performance and if possible, parallelization.
64    /// A warning is logged in debug builds if a list node did not implement one of these methods.
65    ///
66    /// [`measure_list`]: UiNodeImpl::measure_list
67    /// [`layout_list`]: UiNodeImpl::layout_list
68    fn is_list(&self) -> bool {
69        false
70    }
71
72    /// Visit a child node by `index`. If the index is not valid `visitor` is not called.
73    ///
74    /// Nodes with many children should also implement [`for_each_child`] and [`par_each_child`] for better performance.
75    ///
76    /// [`for_each_child`]: UiNodeImpl::for_each_child
77    /// [`par_each_child`]: UiNodeImpl::par_each_child
78    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode));
79
80    /// Call `visitor` for each child node of `self`, one at a time.
81    ///
82    /// The closure parameters are the child index and the child.
83    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
84        debug_warn_list!(self, "for_each_child");
85
86        for i in 0..self.children_len() {
87            self.with_child(i, &mut |n| visitor(i, n));
88        }
89    }
90
91    /// Call `visitor` for each child node of `self`, one at a time, with control flow.
92    ///
93    /// The closure parameters are the child index and the child.
94    fn try_for_each_child(
95        &mut self,
96        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
97    ) -> ControlFlow<BoxAnyVarValue> {
98        debug_warn_list!(self, "try_for_each_child");
99
100        for i in 0..self.children_len() {
101            let mut flow = ControlFlow::Continue(());
102            self.with_child(i, &mut |n| flow = visitor(i, n));
103            flow?;
104        }
105        ControlFlow::Continue(())
106    }
107
108    /// Calls `visitor` for each child node in parallel.
109    ///
110    /// The closure parameters are the child index and the child.
111    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
112        debug_warn_list!(self, "par_each_child");
113
114        for i in 0..self.children_len() {
115            self.with_child(i, &mut |n| visitor(i, n));
116        }
117    }
118
119    /// Calls `fold` for each child node in parallel, with fold accumulators produced by cloning `identity`, then merges the folded results
120    /// using `reduce` to produce the final value also in parallel.
121    ///
122    /// If the `reduce` closure is [associative], an *append* like operation will produce a result in the same order as the input items.
123    ///
124    /// [associative]: https://en.wikipedia.org/wiki/Associative_property
125    fn par_fold_reduce(
126        &mut self,
127        identity: BoxAnyVarValue,
128        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
129        reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
130    ) -> BoxAnyVarValue {
131        debug_warn_list!(self, "par_fold_reduce");
132
133        let _ = reduce;
134        let mut accumulator = identity;
135        for i in 0..self.children_len() {
136            self.with_child(i, &mut |n| {
137                accumulator = fold(std::mem::replace(&mut accumulator, BoxAnyVarValue::new(())), i, n);
138            });
139        }
140        accumulator
141    }
142
143    /// Initializes the node in a new UI context.
144    ///
145    /// Common init operations are subscribing to variables and events and initializing data.
146    /// You can use [`WIDGET`] to subscribe events and vars, the subscriptions live until the widget is deinited.
147    ///
148    /// If the node is a custom widget it must request an info, layout and render updates, other nodes
149    /// do not need to request any sort of update on init.
150    ///
151    /// Note that this method can be called again, after a [`deinit`].
152    ///
153    /// [`deinit`]: UiNode::deinit
154    fn init(&mut self) {
155        match self.children_len() {
156            0 => {}
157            1 => self.with_child(0, &mut |c| c.0.init()),
158            _ => {
159                debug_warn_list!(self, "init");
160                self.for_each_child(&mut |_, n| n.0.init())
161            }
162        }
163    }
164
165    /// Deinitializes the node in the current UI context.
166    ///
167    /// Common deinit operations include dropping allocations and handlers.
168    ///
169    /// If the node is a custom widget it must request an info, layout and render updates, other nodes
170    /// do not need to request any sort of update on deinit.
171    ///
172    /// Note that [`init`] can be called again after this.
173    ///
174    /// [`init`]: UiNode::init
175    fn deinit(&mut self) {
176        match self.children_len() {
177            0 => {}
178            1 => self.with_child(0, &mut |c| c.0.deinit()),
179            _ => {
180                debug_warn_list!(self, "deinit");
181                self.for_each_child(&mut |_, n| n.0.deinit())
182            }
183        }
184    }
185
186    /// Builds widget info.
187    ///
188    /// This method is called every time there are structural changes in the UI tree such as a node added or removed, you
189    /// can also request an info rebuild using [`WIDGET.update_info`].
190    ///
191    /// Only nodes in widgets that requested info rebuild and nodes in their ancestors receive this call. Other
192    /// widgets reuse their info in the new info tree. The widget's latest built info is available in [`WIDGET.info`].
193    ///
194    /// Note that info rebuild has higher priority over event, update, layout and render, this means that if you set a variable
195    /// and request info update the next info rebuild will still observe the old variable value, you can work around this issue by
196    /// only requesting info rebuild after the variable updates.
197    ///
198    /// [`WIDGET.info`]: crate::widget::WIDGET::info
199    /// [`WIDGET.update_info`]: crate::widget::WIDGET::update_info
200    fn info(&mut self, info: &mut WidgetInfoBuilder) {
201        match self.children_len() {
202            0 => {}
203            1 => self.with_child(0, &mut |c| c.0.info(info)),
204            _ => {
205                debug_warn_list!(self, "info");
206                self.for_each_child(&mut |_, n| n.0.info(info))
207            }
208        }
209    }
210
211    /// Receives an event.
212    ///
213    /// Every call to this method is for a single update of a single event type, you can listen to events
214    /// by subscribing to then on init and using the [`Event::on`] method in this method to detect the event.
215    ///
216    /// Note that events sent to descendant nodes also flow through this method and must be delegated. If you observe
217    /// an event for a descendant before delegating to the descendant this is a ***preview*** handling, in the normal handling
218    /// you delegate first, then check the event propagation.
219    ///
220    /// [`Event::on`]: crate::event::Event::on
221    fn event(&mut self, update: &EventUpdate) {
222        match self.children_len() {
223            0 => {}
224            1 => self.with_child(0, &mut |c| c.0.event(update)),
225            _ => {
226                debug_warn_list!(self, "event");
227                self.for_each_child(&mut |_, n| n.0.event(update))
228            }
229        }
230    }
231
232    /// Receives variable and other non-event updates.
233    ///
234    /// Calls to this method aggregate all updates that happen in the last pass, multiple variables can be new at the same time.
235    /// You can listen to variable updates by subscribing to then on init and using the [`Var::get_new`] method in this method to
236    /// receive the new values.
237    ///
238    /// A custom update can be requested using the context [`WIDGET.update`]. Common update operations include reacting to variable
239    /// changes that generate an intermediary value for layout or render, the update implementation uses [`WIDGET`] to request layout
240    /// and render after updating the data. Note that for simple variables that are used directly on layout or render you can subscribe
241    /// to that operation directly, skipping update.
242    ///
243    /// [`Var::get_new`]: zng_var::Var::get_new
244    /// [`WIDGET.update`]: crate::widget::WIDGET::update
245    fn update(&mut self, updates: &WidgetUpdates) {
246        match self.children_len() {
247            0 => {}
248            1 => self.with_child(0, &mut |c| c.0.update(updates)),
249            _ => {
250                debug_warn_list!(self, "update");
251                self.for_each_child(&mut |_, n| n.0.update(updates))
252            }
253        }
254    }
255
256    /// Does [`update`] and if the node is a list notifies list changes to the `observer`.
257    ///
258    /// [`update`]: UiNodeImpl::update
259    fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
260        if self.is_list() {
261            debug_warn_list!(self, "update_list");
262            let len = self.children_len();
263            self.update(updates);
264            if len != self.children_len() {
265                observer.reset();
266            }
267        } else {
268            self.update(updates);
269        }
270    }
271
272    /// Computes the widget size given the contextual layout metrics without actually updating the widget layout.
273    ///
274    /// Implementers must return the same size [`layout`] returns for the given [`LayoutMetrics`], without
275    /// affecting the actual widget render. Panel widgets that implement some complex layouts need to get an
276    /// what the widget would be given some constraints, this value is used to inform the actual [`layout`] call.
277    ///
278    /// Nodes that implement [`layout`] must also implement this method, the [`LAYOUT`] context can be used to retrieve the metrics,
279    /// the [`WidgetMeasure`] parameter can be used to communicate with the parent layout, such as disabling inline layout, the
280    /// returned [`PxSize`] is the desired size given the parent constraints.
281    ///
282    /// [`layout`]: Self::layout
283    /// [`LayoutMetrics`]: zng_layout::context::LayoutMetrics
284    /// [`LAYOUT`]: zng_layout::context::LAYOUT
285    /// [`PxSize`]: zng_layout::unit::PxSize
286    #[must_use]
287    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
288        match self.children_len() {
289            0 => LAYOUT.constraints().fill_size(),
290            1 => {
291                let mut r = PxSize::zero();
292                self.with_child(0, &mut |c| r = c.measure(wm));
293                r
294            }
295            _ => {
296                debug_warn_list!(self, "measure");
297                let mut accumulator = PxSize::zero();
298                self.for_each_child(&mut |_, n| accumulator = accumulator.max(n.0.measure(wm)));
299                accumulator
300            }
301        }
302    }
303
304    /// If the node [`is_list`] measure each child and combine the size using `fold_size`.
305    ///
306    /// If the node is not a list, simply measures it.
307    ///
308    /// [`is_list`]: UiNodeImpl::is_list
309    #[must_use]
310    fn measure_list(
311        &mut self,
312        wm: &mut WidgetMeasure,
313        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
314        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
315    ) -> PxSize {
316        if self.is_list() {
317            match self.children_len() {
318                0 => PxSize::zero(),
319                1 => {
320                    let mut r = PxSize::zero();
321                    self.with_child(0, &mut |c| r = measure(0, c, wm));
322                    r
323                }
324                _ => {
325                    debug_warn_list!(self, "measure_list");
326
327                    let mut accumulator = PxSize::zero();
328                    self.for_each_child(&mut |i, n| {
329                        let c_s = measure(i, n, wm);
330                        accumulator = fold_size(accumulator, c_s)
331                    });
332                    accumulator
333                }
334            }
335        } else {
336            self.measure(wm)
337        }
338    }
339
340    /// Computes the widget layout given the contextual layout metrics.
341    ///
342    /// Implementers must also implement [`measure`]. This method is called by the parent layout once the final constraints
343    /// for the frame are defined, the [`LAYOUT`] context can be used to retrieve the constraints, the [`WidgetLayout`] parameter
344    /// can be used to communicate layout metadata such as inline segments to the parent layout, the returned [`PxSize`] is the
345    /// final size given the constraints.
346    ///
347    /// Only widgets and ancestors that requested layout or use metrics that changed since last layout receive this call. Other
348    /// widgets reuse the last layout result.
349    ///
350    /// Nodes that render can also implement this operation just to observe the latest widget size, if changes are detected
351    /// the [`WIDGET.render`] method can be used to request render.
352    ///
353    /// [`measure`]: Self::measure
354    /// [`LayoutMetrics`]: zng_layout::context::LayoutMetrics
355    /// [`constraints`]: zng_layout::context::LayoutMetrics::constraints
356    /// [`WIDGET.render`]: crate::widget::WIDGET::render
357    /// [`LAYOUT`]: zng_layout::context::LAYOUT
358    /// [`PxSize`]: zng_layout::unit::PxSize
359    #[must_use]
360    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
361        match self.children_len() {
362            0 => LAYOUT.constraints().fill_size(),
363            1 => {
364                let mut r = PxSize::zero();
365                self.with_child(0, &mut |c| r = c.layout(wl));
366                r
367            }
368            _ => {
369                debug_warn_list!(self, "layout");
370
371                let mut accumulator = PxSize::zero();
372                self.for_each_child(&mut |_, n| accumulator = accumulator.max(n.0.layout(wl)));
373                accumulator
374            }
375        }
376    }
377
378    /// If the node [`is_list`] layout each child and combine the size using `fold_size`.
379    ///
380    /// If the node is not a list, simply layout it.
381    ///
382    /// [`is_list`]: UiNodeImpl::is_list
383    #[must_use]
384    fn layout_list(
385        &mut self,
386        wl: &mut WidgetLayout,
387        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
388        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
389    ) -> PxSize {
390        if self.is_list() {
391            match self.children_len() {
392                0 => PxSize::zero(),
393                1 => {
394                    let mut r = PxSize::zero();
395                    self.with_child(0, &mut |c| r = layout(0, c, wl));
396                    r
397                }
398                _ => {
399                    debug_warn_list!(self, "layout_list");
400
401                    let mut accumulator = PxSize::zero();
402                    self.for_each_child(&mut |i, n| {
403                        let c_s = layout(i, n, wl);
404                        accumulator = fold_size(accumulator, c_s)
405                    });
406                    accumulator
407                }
408            }
409        } else {
410            self.layout(wl)
411        }
412    }
413
414    /// Generates render instructions and updates transforms and hit-test areas.
415    ///
416    /// This method does not generate pixels immediately, it generates *display items* that are visual building block instructions
417    /// for the renderer that will run after the window *display list* is built.
418    ///
419    /// Only widgets and ancestors that requested render receive this call, other widgets reuse the display items and transforms
420    /// from the last frame.
421    fn render(&mut self, frame: &mut FrameBuilder) {
422        match self.children_len() {
423            0 => {}
424            1 => self.with_child(0, &mut |c| c.render(frame)),
425            _ => {
426                debug_warn_list!(self, "render");
427
428                self.for_each_child(&mut |_, n| n.0.render(frame));
429            }
430        }
431    }
432
433    /// If the node [`is_list`] render each child.
434    ///
435    /// If the node is not a list, simply renders it.
436    ///
437    /// [`is_list`]: UiNodeImpl::is_list
438    fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
439        if self.is_list() {
440            match self.children_len() {
441                0 => {}
442                1 => self.with_child(0, &mut |n| render(0, n, frame)),
443                _ => {
444                    debug_warn_list!(self, "render_list");
445
446                    self.for_each_child(&mut |i, n| render(i, n, frame));
447                }
448            }
449        } else {
450            self.render(frame);
451        }
452    }
453
454    /// Updates values in the last generated frame.
455    ///
456    /// Some display item values and transforms can be updated directly, without needing to rebuild the display list. All [`FrameBuilder`]
457    /// methods that accept a [`FrameValue<T>`] input can be bound to an ID that can be used to update that value.
458    ///
459    /// Only widgets and ancestors that requested render update receive this call. Note that if any other widget in the same window
460    /// requests render all pending render update requests are upgraded to render requests.
461    ///
462    /// [`FrameValue<T>`]: crate::render::FrameValue
463    fn render_update(&mut self, update: &mut FrameUpdate) {
464        match self.children_len() {
465            0 => {}
466            1 => self.with_child(0, &mut |c| c.render_update(update)),
467            _ => {
468                debug_warn_list!(self, "render_update");
469
470                self.for_each_child(&mut |_, n| n.0.render_update(update));
471            }
472        }
473    }
474
475    /// If the node [`is_list`] render_update each child.
476    ///
477    /// If the node is not a list, simply render_update it.
478    ///
479    /// [`is_list`]: UiNodeImpl::is_list
480    fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
481        if self.is_list() {
482            match self.children_len() {
483                0 => {}
484                1 => self.with_child(0, &mut |n| render_update(0, n, update)),
485                _ => {
486                    debug_warn_list!(self, "render_update_list");
487
488                    self.for_each_child(&mut |i, n| render_update(i, n, update));
489                }
490            }
491        } else {
492            self.render_update(update);
493        }
494    }
495
496    /// Gets the node implementation as a [`WidgetUiNodeImpl`], if the node defines a widget instance scope.
497    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
498        None
499    }
500}
501impl dyn UiNodeImpl {
502    /// Gets if this node is a good candidate for parallelization when visiting children.
503    ///
504    /// List implementers should check this and [`PARALLEL_VAR`] to enable parallelization of node methods.
505    ///
506    /// [`PARALLEL_VAR`]: crate::widget::base::PARALLEL_VAR
507    pub fn parallelize_hint(&mut self) -> bool {
508        self.children_len() > 1 && self.non_parallel_count() >= MIN_PARALLEL
509    }
510    fn non_parallel_count(&mut self) -> usize {
511        let mut count = 0;
512        let _ = self.try_for_each_child(&mut |_, child| {
513            let cc = child.0.non_parallel_count();
514            if cc < MIN_PARALLEL {
515                count += 1 + cc;
516            }
517            if count >= MIN_PARALLEL {
518                ControlFlow::Break(BoxAnyVarValue::new(()))
519            } else {
520                ControlFlow::Continue(())
521            }
522        });
523        count
524    }
525}
526const MIN_PARALLEL: usize = 24;
527
528/// Represents an [`UiNodeImpl`] that defines a widget instance scope.
529///
530/// Widget defining nodes implement this trait and [`UiNodeImpl::as_widget`].
531pub trait WidgetUiNodeImpl: UiNodeImpl {
532    /// Calls `visitor` with the [`WIDGET`] context of the widget instance defined by the node.
533    ///
534    /// If `update_mode` is [`WidgetUpdateMode::Bubble`] the update flags requested for the widget in `visitor` will be copied to the
535    /// caller widget context, otherwise they are ignored.
536    fn with_context(&mut self, update_mode: WidgetUpdateMode, visitor: &mut dyn FnMut());
537}
538
539/// Represents a value that can become a [`UiNode`] instance.
540#[diagnostic::on_unimplemented(note = "`IntoUiNode` is implemented for all `U: UiNodeImpl`")]
541pub trait IntoUiNode {
542    /// Instantiate the UI node.
543    fn into_node(self) -> UiNode;
544}
545
546impl<U: UiNodeImpl> IntoUiNode for U {
547    #[inline(always)]
548    fn into_node(self) -> UiNode {
549        UiNode::new(self)
550    }
551}
552impl IntoUiNode for UiNode {
553    #[inline(always)]
554    fn into_node(self) -> UiNode {
555        self
556    }
557}
558impl<U: IntoUiNode> IntoUiNode for Option<U> {
559    /// Unwrap or nil.
560    fn into_node(self) -> UiNode {
561        self.map(IntoUiNode::into_node).unwrap_or_else(UiNode::nil)
562    }
563}
564
565impl<A, B> IntoUiNode for std::iter::Chain<A, B>
566where
567    A: Iterator<Item = UiNode>,
568    B: Iterator<Item = A::Item>,
569{
570    fn into_node(self) -> UiNode {
571        let vec: Vec<UiNode> = self.collect();
572        vec.into_node()
573    }
574}
575impl IntoUiNode for std::iter::Empty<UiNode> {
576    fn into_node(self) -> UiNode {
577        ui_vec![].into_node()
578    }
579}
580impl<I, P> IntoUiNode for std::iter::Filter<I, P>
581where
582    I: Iterator<Item = UiNode>,
583    P: FnMut(&<I as Iterator>::Item) -> bool,
584{
585    fn into_node(self) -> UiNode {
586        let vec: Vec<UiNode> = self.collect();
587        vec.into_node()
588    }
589}
590impl<I, F> IntoUiNode for std::iter::FilterMap<I, F>
591where
592    I: Iterator,
593    F: FnMut(<I as Iterator>::Item) -> Option<UiNode>,
594{
595    fn into_node(self) -> UiNode {
596        let vec: Vec<UiNode> = self.collect();
597        vec.into_node()
598    }
599}
600impl<I, U, F> IntoUiNode for std::iter::FlatMap<I, U, F>
601where
602    I: Iterator,
603    U: IntoIterator<Item = UiNode>,
604    F: FnMut(I::Item) -> U,
605{
606    fn into_node(self) -> UiNode {
607        let vec: Vec<UiNode> = self.collect();
608        vec.into_node()
609    }
610}
611impl<I, U> IntoUiNode for std::iter::Flatten<I>
612where
613    I: Iterator,
614    <I as Iterator>::Item: IntoIterator<IntoIter = U, Item = <U as Iterator>::Item>,
615    U: Iterator<Item = UiNode>,
616{
617    fn into_node(self) -> UiNode {
618        let vec: Vec<UiNode> = self.collect();
619        vec.into_node()
620    }
621}
622impl<F> IntoUiNode for std::iter::FromFn<F>
623where
624    F: FnMut() -> Option<UiNode>,
625{
626    fn into_node(self) -> UiNode {
627        let vec: Vec<UiNode> = self.collect();
628        vec.into_node()
629    }
630}
631impl<I, F> IntoUiNode for std::iter::Inspect<I, F>
632where
633    I: Iterator<Item = UiNode>,
634    F: FnMut(&<I as Iterator>::Item),
635{
636    fn into_node(self) -> UiNode {
637        let vec: Vec<UiNode> = self.collect();
638        vec.into_node()
639    }
640}
641impl<I, F> IntoUiNode for std::iter::Map<I, F>
642where
643    I: Iterator,
644    F: FnMut(I::Item) -> UiNode,
645{
646    fn into_node(self) -> UiNode {
647        let vec: Vec<UiNode> = self.collect();
648        vec.into_node()
649    }
650}
651impl<I, P> IntoUiNode for std::iter::MapWhile<I, P>
652where
653    I: Iterator,
654    P: FnMut(<I as Iterator>::Item) -> Option<UiNode>,
655{
656    fn into_node(self) -> UiNode {
657        let vec: Vec<UiNode> = self.collect();
658        vec.into_node()
659    }
660}
661impl<I> IntoUiNode for std::iter::Peekable<I>
662where
663    I: Iterator<Item = UiNode>,
664{
665    fn into_node(self) -> UiNode {
666        let vec: Vec<UiNode> = self.collect();
667        vec.into_node()
668    }
669}
670impl<I> IntoUiNode for std::iter::Rev<I>
671where
672    I: DoubleEndedIterator<Item = UiNode>,
673{
674    fn into_node(self) -> UiNode {
675        let vec: Vec<UiNode> = self.collect();
676        vec.into_node()
677    }
678}
679impl<I, St, F> IntoUiNode for std::iter::Scan<I, St, F>
680where
681    I: Iterator,
682    F: FnMut(&mut St, <I as Iterator>::Item) -> Option<UiNode>,
683{
684    fn into_node(self) -> UiNode {
685        let vec: Vec<UiNode> = self.collect();
686        vec.into_node()
687    }
688}
689impl<I> IntoUiNode for std::iter::Skip<I>
690where
691    I: Iterator<Item = UiNode>,
692{
693    fn into_node(self) -> UiNode {
694        let vec: Vec<UiNode> = self.collect();
695        vec.into_node()
696    }
697}
698impl<I, P> IntoUiNode for std::iter::SkipWhile<I, P>
699where
700    I: Iterator<Item = UiNode>,
701    P: FnMut(&<I as Iterator>::Item) -> bool,
702{
703    fn into_node(self) -> UiNode {
704        let vec: Vec<UiNode> = self.collect();
705        vec.into_node()
706    }
707}
708impl<I> IntoUiNode for std::iter::StepBy<I>
709where
710    I: Iterator<Item = UiNode>,
711{
712    fn into_node(self) -> UiNode {
713        let vec: Vec<UiNode> = self.collect();
714        vec.into_node()
715    }
716}
717impl<F> IntoUiNode for std::iter::Successors<UiNode, F>
718where
719    F: FnMut(&UiNode) -> Option<UiNode>,
720{
721    fn into_node(self) -> UiNode {
722        let vec: Vec<UiNode> = self.collect();
723        vec.into_node()
724    }
725}
726impl<I> IntoUiNode for std::iter::Take<I>
727where
728    I: Iterator<Item = UiNode>,
729{
730    fn into_node(self) -> UiNode {
731        let vec: Vec<UiNode> = self.collect();
732        vec.into_node()
733    }
734}
735impl<I, P> IntoUiNode for std::iter::TakeWhile<I, P>
736where
737    I: Iterator<Item = UiNode>,
738    P: FnMut(&<I as Iterator>::Item) -> bool,
739{
740    fn into_node(self) -> UiNode {
741        let vec: Vec<UiNode> = self.collect();
742        vec.into_node()
743    }
744}
745
746/// Represents an UI tree node instance.
747///
748/// You can use the [`match_node`] helper to quickly declare a new node from a closure, most property nodes are implemented
749/// using the match helpers. For more advanced nodes can implement the [`UiNodeImpl`] trait. Other types can be converted to nodes
750/// if they implement [`IntoUiNode`].
751///
752/// [`match_node`]:fn@match_node
753pub struct UiNode(Box<dyn UiNodeImpl>);
754
755/// Constructors.
756impl UiNode {
757    /// New UI node instance from implementation.
758    ///
759    /// Note that [`IntoUiNode`] is implemented for all `U: UiNodeImpl` so you don't usually need to call this.
760    pub fn new(implementation: impl UiNodeImpl) -> Self {
761        Self(Box::new(implementation))
762    }
763
764    /// New UI node that does nothing and collapses layout.
765    pub fn nil() -> Self {
766        Self::new(NilUiNode)
767    }
768}
769
770/// UI operations.
771impl UiNode {
772    /// Calls the [`UiNodeOp`].
773    #[inline(always)]
774    pub fn op(&mut self, op: UiNodeOp) {
775        match op {
776            UiNodeOp::Init => self.init(),
777            UiNodeOp::Deinit => self.deinit(),
778            UiNodeOp::Info { info } => self.info(info),
779            UiNodeOp::Event { update } => self.event(update),
780            UiNodeOp::Update { updates } => self.update(updates),
781            UiNodeOp::Measure { wm, desired_size } => *desired_size = self.measure(wm),
782            UiNodeOp::Layout { wl, final_size } => *final_size = self.layout(wl),
783            UiNodeOp::Render { frame } => self.render(frame),
784            UiNodeOp::RenderUpdate { update } => self.render_update(update),
785        }
786    }
787
788    /// Initialize the node in a new UI context.
789    ///
790    /// See [`UiNodeImpl::init`] for more details.
791    #[inline(always)]
792    pub fn init(&mut self) {
793        self.0.init();
794    }
795
796    /// Deinitialize the node in the current UI context.
797    ///
798    /// This must be called before dropping the node.
799    ///
800    /// After calling this you can move the node to a new context and call [`init`] again.
801    ///
802    /// See [`UiNodeImpl::deinit`] for more details.
803    ///
804    /// [`init`]: Self::init
805    #[inline(always)]
806    pub fn deinit(&mut self) {
807        self.0.deinit();
808    }
809
810    /// Continue building widget info metadata.
811    ///
812    /// See [`UiNodeImpl::info`] for more details.
813    #[inline(always)]
814    pub fn info(&mut self, info: &mut WidgetInfoBuilder) {
815        self.0.info(info);
816    }
817
818    /// Notify event update.
819    ///
820    /// See [`UiNodeImpl::event`] for more details.
821    #[inline(always)]
822    pub fn event(&mut self, update: &EventUpdate) {
823        self.0.event(update);
824    }
825
826    /// Notify non-event update.
827    ///
828    /// See [`UiNodeImpl::update`] for more details.
829    #[inline(always)]
830    pub fn update(&mut self, updates: &WidgetUpdates) {
831        self.0.update(updates);
832    }
833
834    /// Notify non-event update and observe list changes if the widget is a list.
835    ///
836    /// See [`UiNodeImpl::update_list`] for more details.
837    #[inline(always)]
838    pub fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut impl UiNodeListObserver) {
839        self.0.update_list(updates, observer);
840    }
841
842    /// Estimate node layout without actually updating the node render state.
843    ///
844    /// See [`UiNodeImpl::measure`] for more details.
845    #[inline(always)]
846    #[must_use]
847    pub fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
848        self.0.measure(wm)
849    }
850
851    /// If the node [`is_list`] measure each child and combine the size using `fold_size`.
852    ///
853    /// If the node is not a list, simply measures it.
854    ///
855    /// See [`UiNodeImpl::measure_list`] for more details.
856    ///
857    /// [`is_list`]: UiNode::is_list
858    #[inline(always)]
859    #[must_use]
860    pub fn measure_list(
861        &mut self,
862        wm: &mut WidgetMeasure,
863        measure: impl Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync,
864        fold_size: impl Fn(PxSize, PxSize) -> PxSize + Sync,
865    ) -> PxSize {
866        self.0.measure_list(wm, &measure, &fold_size)
867    }
868
869    /// Update node layout.
870    ///
871    /// See [`UiNodeImpl::layout`] for more details.
872    #[inline(always)]
873    #[must_use]
874    pub fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
875        self.0.layout(wl)
876    }
877
878    /// If the node [`is_list`] layout each child and combine the size using `fold_size`.
879    ///
880    /// If the node is not a list, simply layout it.
881    ///
882    /// See [`UiNodeImpl::layout_list`] for more details.
883    ///
884    /// [`is_list`]: UiNode::is_list
885    #[inline(always)]
886    #[must_use]
887    pub fn layout_list(
888        &mut self,
889        wl: &mut WidgetLayout,
890        layout: impl Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync,
891        fold_size: impl Fn(PxSize, PxSize) -> PxSize + Sync,
892    ) -> PxSize {
893        self.0.layout_list(wl, &layout, &fold_size)
894    }
895
896    /// Collect render instructions for a new frame.
897    ///
898    /// See [`UiNodeImpl::render`] for more details.
899    #[inline(always)]
900    pub fn render(&mut self, frame: &mut FrameBuilder) {
901        self.0.render(frame)
902    }
903
904    /// If the node [`is_list`] render each child.
905    ///
906    /// If the node is not a list, simply renders it.
907    ///
908    /// See [`UiNodeImpl::render_list`] for more details.
909    ///
910    /// [`is_list`]: UiNode::is_list
911    #[inline(always)]
912    pub fn render_list(&mut self, frame: &mut FrameBuilder, render: impl Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync) {
913        self.0.render_list(frame, &render);
914    }
915
916    /// Collect render patches to apply to the previous frame.
917    ///
918    /// See [`UiNodeImpl::render_update`] for more details.
919    #[inline(always)]
920    pub fn render_update(&mut self, update: &mut FrameUpdate) {
921        self.0.render_update(update);
922    }
923
924    /// If the node [`is_list`] render_update each child.
925    ///
926    /// If the node is not a list, simply render_update it.
927    ///
928    /// See [`UiNodeImpl::render_update_list`] for more details.
929    ///
930    /// [`is_list`]: UiNode::is_list
931    #[inline(always)]
932    pub fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: impl Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync) {
933        self.0.render_update_list(update, &render_update);
934    }
935}
936
937/// Children.
938impl UiNode {
939    /// Number of direct descendants of this node.
940    pub fn children_len(&self) -> usize {
941        self.0.children_len()
942    }
943
944    /// Call `visitor` with a exclusive reference to the child node identified by `index`.
945    ///
946    /// If the `index` is out of bounds the closure is not called and returns `None`.
947    pub fn try_with_child<R>(&mut self, index: usize, visitor: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
948        let mut once = Some(visitor);
949        let mut r = None;
950        self.0.with_child(index, &mut |child| r = Some(once.take().unwrap()(child)));
951        r
952    }
953
954    /// Call `visitor` with a exclusive reference to the child node identified by `index`.
955    ///
956    /// Panics if the `index` is out of bounds.
957    pub fn with_child<R>(&mut self, index: usize, visitor: impl FnOnce(&mut UiNode) -> R) -> R {
958        self.try_with_child(index, visitor).expect("index out of bounds")
959    }
960
961    /// Call `visitor` for each child node of `self`, one at a time.
962    ///
963    /// The closure parameters are the child index and the child.
964    pub fn for_each_child(&mut self, mut visitor: impl FnMut(usize, &mut UiNode)) {
965        self.0.for_each_child(&mut visitor);
966    }
967
968    /// Call `visitor` for each child node of `self`, one at a time, with control flow.
969    ///
970    /// The closure parameters are the child index and the child.
971    pub fn try_for_each_child<B>(&mut self, mut visitor: impl FnMut(usize, &mut UiNode) -> ControlFlow<B>) -> ControlFlow<B>
972    where
973        B: zng_var::VarValue,
974    {
975        self.0
976            .try_for_each_child(&mut move |i, n| visitor(i, n).map_break(BoxAnyVarValue::new))
977            .map_break(|b| b.downcast::<B>().unwrap())
978    }
979
980    /// Calls `visitor` for each child node in parallel.
981    ///
982    /// The closure parameters are the child index and the child.
983    pub fn par_each_child(&mut self, visitor: impl Fn(usize, &mut UiNode) + Sync) {
984        self.0.par_each_child(&visitor);
985    }
986
987    /// Calls `fold` for each child node in parallel, with fold accumulators produced by cloning `identity`, then merges the folded results
988    /// using `reduce` to produce the final value also in parallel.
989    ///
990    /// If the `reduce` closure is [associative], an *append* like operation will produce a result in the same order as the input items.
991    ///
992    /// [associative]: https://en.wikipedia.org/wiki/Associative_property
993    pub fn par_fold_reduce<T: zng_var::VarValue>(
994        &mut self,
995        identity: T,
996        fold: impl Fn(T, usize, &mut UiNode) -> T + Sync,
997        reduce: impl Fn(T, T) -> T + Sync,
998    ) -> T {
999        use zng_var::BoxAnyVarValue as B;
1000        self.0
1001            .par_fold_reduce(
1002                B::new(identity),
1003                &|accumulator, index, node| {
1004                    let r = fold(accumulator.downcast::<T>().unwrap(), index, node);
1005                    B::new(r)
1006                },
1007                &|a, b| {
1008                    let r = reduce(a.downcast::<T>().unwrap(), b.downcast::<T>().unwrap());
1009                    B::new(r)
1010                },
1011            )
1012            .downcast::<T>()
1013            .unwrap()
1014    }
1015}
1016
1017/// Node type.
1018impl UiNode {
1019    /// Returns some reference to implementation of type `U`, if the node instance is of that implementation.
1020    #[inline(always)]
1021    pub fn downcast_ref<U: UiNodeImpl>(&self) -> Option<&U> {
1022        let u: &dyn Any = &*self.0;
1023        u.downcast_ref::<U>()
1024    }
1025
1026    /// Returns some mutable reference to implementation of type `U`, if the node instance is of that implementation.
1027    #[inline(always)]
1028    pub fn downcast_mut<U: UiNodeImpl>(&mut self) -> Option<&mut U> {
1029        let u: &mut dyn Any = &mut *self.0;
1030        u.downcast_mut::<U>()
1031    }
1032
1033    /// Gets if the node is an instance of implementation `U`.
1034    #[inline(always)]
1035    pub fn is<U: UiNodeImpl>(&self) -> bool {
1036        self.downcast_ref::<U>().is_some()
1037    }
1038
1039    /// Exclusive borrow the node implementation directly.
1040    #[inline(always)]
1041    pub fn as_dyn(&mut self) -> &mut dyn UiNodeImpl {
1042        &mut *self.0
1043    }
1044
1045    /// Gets if the node represents a list of other nodes.
1046    ///
1047    /// If `true` the node provides only minimal layout implementations and expects the caller
1048    /// to use [`measure_list`], [`layout_list`] or direct access to the child nodes for layout.
1049    ///
1050    /// [`measure_list`]: Self::measure_list
1051    /// [`layout_list`]: Self::layout_list
1052    #[inline(always)]
1053    pub fn is_list(&self) -> bool {
1054        self.0.is_list()
1055    }
1056
1057    /// Returns a node that [`is_list`].
1058    ///
1059    /// If `self` is a list returns it unchanged.
1060    ///
1061    /// If `self` is nil returns an empty list node.
1062    ///
1063    /// Otherwise returns a new list node with `self` as the single entry.
1064    ///
1065    /// [`is_list`]: Self::is_list
1066    pub fn into_list(self) -> UiNode {
1067        if self.is_list() {
1068            self
1069        } else if self.is_nil() {
1070            ui_vec![].into_node()
1071        } else {
1072            ui_vec![self].into_node()
1073        }
1074    }
1075
1076    /// Gets if is [`nil`].
1077    ///
1078    /// [`nil`]: Self::nil
1079    #[inline(always)]
1080    pub fn is_nil(&self) -> bool {
1081        self.is::<NilUiNode>()
1082    }
1083
1084    /// Access widget node methods, if the node defines a widget context.
1085    #[inline(always)]
1086    pub fn as_widget(&mut self) -> Option<WidgetUiNode<'_>> {
1087        self.0.as_widget().map(WidgetUiNode)
1088    }
1089
1090    /// Returns a node that defines a widget context.
1091    ///
1092    /// If this node already defines a widget just returns it, if not wraps it in a minimal widget implementation.
1093    ///
1094    /// See also [`init_widget`] for a node that awaits until `self` is inited to verify if a new widget really needs to be declared.
1095    ///
1096    /// [`init_widget`]: Self::init_widget
1097    pub fn into_widget(mut self) -> UiNode {
1098        if self.0.as_widget().is_some() {
1099            self
1100        } else {
1101            into_widget!(child = self)
1102        }
1103    }
1104
1105    /// Returns a node that defines a widget context or will begin defining it after [`init`].
1106    ///
1107    /// Also returns a response var that contains or will contain the widget instance ID.
1108    ///
1109    /// If `self` is already an widget node simply returns it and the ID, otherwise returns a node that wraps `self`
1110    /// and checks again if `self` is a widget after init, if `self` is still not a widget after init the wrapper node starts
1111    /// defining a minimal widget context.
1112    ///
1113    /// Some nodes like [`ArcNode::take_on_init`] can only become widgets on init, this helper is an alternative to [`into_widget`]
1114    /// that avoids declaring a second wrapper widget in those cases. Note that because the wrapper node needs to define a widget context
1115    /// after the [`init`] call the wrapped `self` node will need to be reinited inside the new widget.
1116    ///
1117    /// [`init`]: Self::init
1118    /// [`into_widget`]: Self::into_widget
1119    pub fn init_widget(mut self) -> (UiNode, ResponseVar<WidgetId>) {
1120        if let Some(mut wgt) = self.as_widget() {
1121            let id = response_done_var(wgt.id());
1122            (self, id)
1123        } else {
1124            let (r, id) = response_var::<WidgetId>();
1125            let mut first_init = Some(r);
1126            let wgt = match_widget(self, move |c, op| {
1127                if let UiNodeOp::Init = op {
1128                    c.init();
1129
1130                    if let Some(r) = first_init.take() {
1131                        if let Some(mut wgt) = c.node().as_widget() {
1132                            r.respond(wgt.id());
1133                        } else {
1134                            // reinit inside a new widget
1135                            c.deinit();
1136                            let not_wgt = std::mem::replace(c.node(), UiNode::nil());
1137                            *c.node() = into_widget!(child = not_wgt);
1138                            c.init();
1139
1140                            r.respond(c.node().as_widget().unwrap().id());
1141                        }
1142                    }
1143                }
1144            });
1145            (wgt, id)
1146        }
1147    }
1148
1149    /// Wraps this in a node that, before delegating each method, calls a closure with
1150    /// the [`UiNodeMethod`], the closure can return a *span* that is dropped after the method delegation.
1151    ///
1152    /// The tracing node delegates all methods to self, but only traces the [`UiNodeMethod`] methods. If
1153    /// this node is an widget the `enter_mtd` closure will be called (and span dropped) in the context of the widget.
1154    ///
1155    /// You can use the [`tracing`](https://docs.rs/tracing) crate to create the span. You can also use the [`RunOnDrop`]
1156    /// struct to run a closure after the method executes.
1157    ///
1158    /// [`RunOnDrop`]: zng_app_context::RunOnDrop
1159    pub fn trace<E, S>(self, enter_mtd: E) -> UiNode
1160    where
1161        Self: Sized,
1162        E: FnMut(UiNodeMethod) -> S + Send + 'static,
1163    {
1164        UiNode::new(trace::TraceNode::new(self, enter_mtd))
1165    }
1166}
1167
1168/// Extra [`UiNode`] methods for nodes that define a widget instance context.
1169///
1170/// See [`UiNode::as_widget`] for more details.
1171pub struct WidgetUiNode<'u>(&'u mut dyn WidgetUiNodeImpl);
1172
1173impl<'u> WidgetUiNode<'u> {
1174    /// Calls `visitor` with the [`WIDGET`] context of the widget instance defined by the node.
1175    ///
1176    /// If `update_mode` is [`WidgetUpdateMode::Bubble`] the update flags requested for the widget in `visitor` will be copied to the
1177    /// caller widget context, otherwise they are ignored.
1178    #[inline(always)]
1179    pub fn with_context<R>(&mut self, update_mode: WidgetUpdateMode, visitor: impl FnOnce() -> R) -> R {
1180        let mut once = Some(visitor);
1181        let mut r = None;
1182        self.0.with_context(update_mode, &mut || r = Some(once.take().unwrap()()));
1183        r.unwrap()
1184    }
1185
1186    /// Gets the widget instance ID.
1187    pub fn id(&mut self) -> WidgetId {
1188        self.with_context(WidgetUpdateMode::Ignore, || WIDGET.id())
1189    }
1190}
1191
1192/// See [`UiNode::into_widget`]
1193#[expect(non_camel_case_types)]
1194#[widget($crate::widget::node::into_widget)]
1195struct into_widget(crate::widget::base::WidgetBase);
1196#[zng_app_proc_macros::property(CHILD, capture, widget_impl(into_widget))]
1197fn child(child: impl IntoUiNode) {}
1198impl into_widget {
1199    fn widget_intrinsic(&mut self) {
1200        self.widget_builder().push_build_action(|b| {
1201            let child = b.capture_ui_node(crate::property_id!(Self::child)).unwrap();
1202            b.set_child(child);
1203        });
1204    }
1205}
1206
1207struct NilUiNode;
1208impl UiNodeImpl for NilUiNode {
1209    fn measure(&mut self, _: &mut WidgetMeasure) -> PxSize {
1210        PxSize::zero()
1211    }
1212
1213    fn layout(&mut self, _: &mut WidgetLayout) -> PxSize {
1214        PxSize::zero()
1215    }
1216
1217    fn children_len(&self) -> usize {
1218        0
1219    }
1220
1221    fn with_child(&mut self, _: usize, _: &mut dyn FnMut(&mut UiNode)) {}
1222}
1223
1224/// A UI node that fills the available layout space.
1225///
1226/// The space is blank, the node does nothing other then layout to fill.
1227pub struct FillUiNode;
1228impl UiNodeImpl for FillUiNode {
1229    fn children_len(&self) -> usize {
1230        0
1231    }
1232
1233    fn with_child(&mut self, _: usize, _: &mut dyn FnMut(&mut UiNode)) {}
1234
1235    // default impl is fill
1236}
1237
1238/// Wraps `child` in a node that provides a unique [`ContextInitHandle`], refreshed every (re)init.
1239///
1240/// [`ContextInitHandle`]: zng_var::ContextInitHandle
1241pub fn with_new_context_init_id(child: impl IntoUiNode) -> UiNode {
1242    let mut id = None;
1243
1244    match_node(child, move |child, op| {
1245        let is_deinit = matches!(op, UiNodeOp::Deinit);
1246        id.get_or_insert_with(ContextInitHandle::new).with_context(|| child.op(op));
1247
1248        if is_deinit {
1249            id = None;
1250        }
1251    })
1252}