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