zng_app/widget/node/
list.rs

1use std::{
2    cmp::Ordering,
3    fmt, mem,
4    ops::{self, ControlFlow},
5    sync::{
6        Arc,
7        atomic::{AtomicBool, Ordering::Relaxed},
8    },
9};
10
11use crate::{
12    render::{FrameBuilder, FrameUpdate, FrameValueKey},
13    update::{EventUpdate, UPDATES, WidgetUpdates},
14    widget::{
15        WIDGET, WidgetUpdateMode,
16        base::{PARALLEL_VAR, Parallel},
17        info::{WidgetInfo, WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
18    },
19};
20use parking_lot::Mutex;
21use task::ParallelIteratorExt;
22use zng_app_context::context_local;
23use zng_layout::unit::{Factor, PxSize, PxTransform, PxVector};
24use zng_state_map::StateId;
25use zng_task::{self as task, rayon::prelude::*};
26use zng_unique_id::static_id;
27use zng_var::{animation::Transitionable, impl_from_and_into_var};
28
29use super::*;
30
31/// Creates an [`UiVec`] containing the arguments.
32///  
33/// Note that the items can be any type that converts to nodes, `ui_vec!` automatically calls [`IntoUiNode::into_node`] for each item.
34///
35/// # Examples
36///
37/// Create a vec containing a list of nodes/widgets:
38///
39/// ```
40/// # use zng_app::widget::node::*;
41/// # use zng_app::widget::base::*;
42/// # macro_rules! Text { ($($tt:tt)*) => { UiNode::nil() } }
43/// let widgets = ui_vec![Text!("Hello"), Text!("World!")];
44/// ```
45///
46/// Create a vec containing the node repeated **n** times:
47///
48/// ```
49/// # use zng_app::widget::node::*;
50/// # use zng_app::widget::base::*;
51/// # macro_rules! Text { ($($tt:tt)*) => { UiNode::nil() } }
52/// let widgets = ui_vec![Text!(" . "); 10];
53/// ```
54///
55/// Note that this is different from `vec![item; n]`, the node is not cloned, the expression is called **n** times to
56/// generate the nodes.
57#[macro_export]
58macro_rules! ui_vec {
59    () => { $crate::widget::node::UiVec::new() };
60    ($node:expr; $n:expr) => {
61        {
62            let mut n: usize = $n;
63            let mut vec = $crate::widget::node::UiVec::with_capacity(n);
64            while n > 0 {
65                vec.push($node);
66                n -= 1;
67            }
68            vec
69        }
70    };
71    ($($nodes:tt)+) => {
72        $crate::ui_vec_items! {
73            match { $($nodes)+ }
74            result { }
75        }
76    };
77}
78#[doc(inline)]
79pub use crate::ui_vec;
80
81// macro to support `#[cfg(_)]` in items, Rust does not allow a match to `$(#[$meta:meta])* $node:expr`.
82#[macro_export]
83#[doc(hidden)]
84macro_rules! ui_vec_items {
85    // match attribute
86    (
87        match { #[$meta:meta] $($tt:tt)* }
88        result { $($r:tt)* }
89    ) => {
90        $crate::ui_vec_items! {
91            match { $($tt)* }
92            result { $($r)* #[$meta] }
93        }
94    };
95    // match node expr followed by comma
96    (
97        match { $node:expr, $($tt:tt)* }
98        result { $($r:tt)* }
99    ) => {
100        $crate::ui_vec_items! {
101            match { $($tt)* }
102            result { $($r)* $crate::widget::node::IntoUiNode::into_node($node), }
103        }
104    };
105    // match last node expr, no trailing comma
106    (
107        match { $node:expr }
108        result { $($r:tt)* }
109    ) => {
110        $crate::ui_vec_items! {
111            match { }
112            result { $($r)* $crate::widget::node::IntoUiNode::into_node($node) }
113        }
114    };
115    // finished
116    (
117        match { }
118        result { $($r:tt)* }
119    ) => {
120        $crate::widget::node::UiVec::from(std::vec![
121            $($r)*
122        ])
123    };
124}
125
126/// Vec of boxed UI nodes.
127///
128/// This is a thin wrapper around `Vec<UiNode>` that adds helper methods for pushing widgets without needing to box.
129#[derive(Default)]
130pub struct UiVec(Vec<UiNode>);
131impl UiVec {
132    /// New default.
133    pub fn new() -> Self {
134        Self::default()
135    }
136
137    /// New [`with_capacity`].
138    ///
139    /// [`with_capacity`]: Vec::with_capacity
140    pub fn with_capacity(capacity: usize) -> Self {
141        Self(Vec::with_capacity(capacity))
142    }
143
144    /// Box and [`push`] the node.
145    ///
146    /// [`push`]: Vec::push
147    pub fn push(&mut self, node: impl IntoUiNode) {
148        self.0.push(node.into_node())
149    }
150
151    /// Box and [`insert`] the node.
152    ///
153    /// [`insert`]: Vec::insert
154    pub fn insert(&mut self, index: usize, node: impl IntoUiNode) {
155        self.0.insert(index, node.into_node())
156    }
157
158    /// Create a list chain node.
159    ///
160    /// See [`UiNode::chain`] for more details.
161    pub fn chain(self, other: impl IntoUiNode) -> UiNode {
162        UiNode::new(self).chain(other)
163    }
164}
165impl ops::Deref for UiVec {
166    type Target = Vec<UiNode>;
167
168    fn deref(&self) -> &Self::Target {
169        &self.0
170    }
171}
172impl ops::DerefMut for UiVec {
173    fn deref_mut(&mut self) -> &mut Self::Target {
174        &mut self.0
175    }
176}
177impl From<Vec<UiNode>> for UiVec {
178    fn from(vec: Vec<UiNode>) -> Self {
179        Self(vec)
180    }
181}
182impl From<UiVec> for Vec<UiNode> {
183    fn from(vec: UiVec) -> Self {
184        vec.0
185    }
186}
187impl<U: IntoUiNode> FromIterator<U> for UiVec {
188    fn from_iter<T: IntoIterator<Item = U>>(iter: T) -> Self {
189        Self(Vec::from_iter(iter.into_iter().map(IntoUiNode::into_node)))
190    }
191}
192impl IntoIterator for UiVec {
193    type Item = UiNode;
194
195    type IntoIter = std::vec::IntoIter<UiNode>;
196
197    fn into_iter(self) -> Self::IntoIter {
198        self.0.into_iter()
199    }
200}
201impl IntoUiNode for Vec<UiNode> {
202    fn into_node(self) -> UiNode {
203        UiNode::new(UiVec(self))
204    }
205}
206impl IntoUiNode for Box<[UiNode]> {
207    fn into_node(self) -> UiNode {
208        UiNode::new(UiVec(self.into()))
209    }
210}
211impl UiNodeImpl for UiVec {
212    fn children_len(&self) -> usize {
213        self.len()
214    }
215
216    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
217        if index < self.len() {
218            visitor(&mut self[index])
219        }
220    }
221
222    fn is_list(&self) -> bool {
223        true
224    }
225
226    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
227        for (i, n) in self.0.iter_mut().enumerate() {
228            visitor(i, n)
229        }
230    }
231
232    fn try_for_each_child(
233        &mut self,
234        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
235    ) -> ControlFlow<BoxAnyVarValue> {
236        for (i, n) in self.0.iter_mut().enumerate() {
237            visitor(i, n)?;
238        }
239        ControlFlow::Continue(())
240    }
241
242    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
243        if self.len() >= MIN_PARALLEL {
244            self.par_iter_mut().enumerate().with_ctx().for_each(|(i, n)| visitor(i, n))
245        } else {
246            self.iter_mut().enumerate().for_each(|(i, n)| visitor(i, n))
247        }
248    }
249
250    fn par_fold_reduce(
251        &mut self,
252        identity: BoxAnyVarValue,
253        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
254        reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
255    ) -> BoxAnyVarValue {
256        self.par_iter_mut()
257            .enumerate()
258            .with_ctx()
259            .fold(|| identity.clone(), move |a, (i, n)| fold(a, i, n))
260            .reduce(|| identity.clone(), reduce)
261    }
262
263    fn init(&mut self) {
264        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::INIT) {
265            self.par_iter_mut().with_ctx().for_each(|n| n.init());
266        } else {
267            self.iter_mut().for_each(|n| n.init());
268        }
269    }
270
271    fn deinit(&mut self) {
272        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::DEINIT) {
273            self.par_iter_mut().with_ctx().for_each(|n| n.deinit());
274        } else {
275            self.iter_mut().for_each(|n| n.deinit());
276        }
277    }
278
279    fn info(&mut self, info: &mut WidgetInfoBuilder) {
280        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::INFO) {
281            let b = self
282                .par_iter_mut()
283                .with_ctx()
284                .fold(
285                    || info.parallel_split(),
286                    |mut info, c| {
287                        c.info(&mut info);
288                        info
289                    },
290                )
291                .reduce(
292                    || info.parallel_split(),
293                    |mut a, b| {
294                        a.parallel_fold(b);
295                        a
296                    },
297                );
298            info.parallel_fold(b);
299        } else {
300            self.iter_mut().for_each(|n| n.info(info));
301        }
302    }
303
304    fn event(&mut self, update: &EventUpdate) {
305        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::EVENT) {
306            self.par_iter_mut().with_ctx().for_each(|n| n.event(update));
307        } else {
308            self.iter_mut().for_each(|n| n.event(update));
309        }
310    }
311
312    fn update(&mut self, updates: &WidgetUpdates) {
313        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::UPDATE) {
314            self.par_iter_mut().with_ctx().for_each(|n| n.update(updates));
315        } else {
316            self.iter_mut().for_each(|n| n.update(updates));
317        }
318    }
319    fn update_list(&mut self, updates: &WidgetUpdates, _: &mut dyn UiNodeListObserver) {
320        self.update(updates);
321    }
322
323    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
324        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
325            let (b, desired_size) = self
326                .par_iter_mut()
327                .with_ctx()
328                .fold(
329                    || (wm.parallel_split(), PxSize::zero()),
330                    |(mut wm, desired_size), n| {
331                        let n_ds = n.measure(&mut wm);
332                        (wm, desired_size.max(n_ds))
333                    },
334                )
335                .reduce(
336                    || (wm.parallel_split(), PxSize::zero()),
337                    |(mut wm, desired_size), (b_wm, b_ds)| {
338                        wm.parallel_fold(b_wm);
339                        (wm, desired_size.max(b_ds))
340                    },
341                );
342            wm.parallel_fold(b);
343            desired_size
344        } else {
345            let mut desired_size = PxSize::zero();
346            self.iter_mut().for_each(|n| desired_size = desired_size.max(n.measure(wm)));
347            desired_size
348        }
349    }
350
351    fn measure_list(
352        &mut self,
353        wm: &mut WidgetMeasure,
354        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
355        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
356    ) -> PxSize {
357        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
358            let (b, desired_size) = self
359                .par_iter_mut()
360                .enumerate()
361                .with_ctx()
362                .fold(
363                    || (wm.parallel_split(), PxSize::zero()),
364                    |(mut wm, desired_size), (i, n)| {
365                        let n_ds = measure(i, n, &mut wm);
366                        (wm, fold_size(desired_size, n_ds))
367                    },
368                )
369                .reduce(
370                    || (wm.parallel_split(), PxSize::zero()),
371                    |(mut wm, desired_size), (b_wm, b_ds)| {
372                        wm.parallel_fold(b_wm);
373                        (wm, fold_size(desired_size, b_ds))
374                    },
375                );
376            wm.parallel_fold(b);
377            desired_size
378        } else {
379            let mut desired_size = PxSize::zero();
380            self.iter_mut()
381                .enumerate()
382                .for_each(|(i, n)| desired_size = fold_size(desired_size, measure(i, n, wm)));
383            desired_size
384        }
385    }
386
387    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
388        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
389            let (b, final_size) = self
390                .par_iter_mut()
391                .with_ctx()
392                .fold(
393                    || (wl.parallel_split(), PxSize::zero()),
394                    |(mut wl, final_size), n| {
395                        let n_ds = n.layout(&mut wl);
396                        (wl, final_size.max(n_ds))
397                    },
398                )
399                .reduce(
400                    || (wl.parallel_split(), PxSize::zero()),
401                    |(mut wl, desired_size), (b_wl, b_ds)| {
402                        wl.parallel_fold(b_wl);
403                        (wl, desired_size.max(b_ds))
404                    },
405                );
406            wl.parallel_fold(b);
407            final_size
408        } else {
409            let mut final_size = PxSize::zero();
410            self.iter_mut().for_each(|n| final_size = final_size.max(n.layout(wl)));
411            final_size
412        }
413    }
414
415    fn layout_list(
416        &mut self,
417        wl: &mut WidgetLayout,
418        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
419        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
420    ) -> PxSize {
421        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
422            let (b, desired_size) = self
423                .par_iter_mut()
424                .enumerate()
425                .with_ctx()
426                .fold(
427                    || (wl.parallel_split(), PxSize::zero()),
428                    |(mut wl, desired_size), (i, n)| {
429                        let n_ds = layout(i, n, &mut wl);
430                        (wl, fold_size(desired_size, n_ds))
431                    },
432                )
433                .reduce(
434                    || (wl.parallel_split(), PxSize::zero()),
435                    |(mut wl, desired_size), (b_wm, b_ds)| {
436                        wl.parallel_fold(b_wm);
437                        (wl, fold_size(desired_size, b_ds))
438                    },
439                );
440            wl.parallel_fold(b);
441            desired_size
442        } else {
443            let mut desired_size = PxSize::zero();
444            self.iter_mut()
445                .enumerate()
446                .for_each(|(i, n)| desired_size = fold_size(desired_size, layout(i, n, wl)));
447            desired_size
448        }
449    }
450
451    fn render(&mut self, frame: &mut FrameBuilder) {
452        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::RENDER) {
453            let mut par_start = 0;
454            while frame.is_outer() && par_start < self.len() {
455                // complete current widget first
456                self[par_start].render(frame);
457                par_start += 1;
458            }
459            let b = self[par_start..]
460                .par_iter_mut()
461                .with_ctx()
462                .fold(
463                    || frame.parallel_split(),
464                    |mut frame, c| {
465                        c.render(&mut frame);
466                        frame
467                    },
468                )
469                .reduce(
470                    || frame.parallel_split(),
471                    |mut a, b| {
472                        a.parallel_fold(b);
473                        a
474                    },
475                );
476            frame.parallel_fold(b);
477        } else {
478            self.iter_mut().for_each(|n| n.render(frame));
479        }
480    }
481
482    fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
483        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::RENDER) {
484            let mut par_start = 0;
485            while frame.is_outer() && par_start < self.len() {
486                // complete current widget first
487                self[par_start].render(frame);
488                par_start += 1;
489            }
490            let b = self[par_start..]
491                .par_iter_mut()
492                .enumerate()
493                .with_ctx()
494                .fold(
495                    || frame.parallel_split(),
496                    |mut frame, (i, c)| {
497                        render(i, c, &mut frame);
498                        frame
499                    },
500                )
501                .reduce(
502                    || frame.parallel_split(),
503                    |mut a, b| {
504                        a.parallel_fold(b);
505                        a
506                    },
507                );
508            frame.parallel_fold(b);
509        } else {
510            self.iter_mut().enumerate().for_each(|(i, n)| render(i, n, frame));
511        }
512    }
513
514    fn render_update(&mut self, update: &mut FrameUpdate) {
515        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::RENDER) {
516            let mut par_start = 0;
517            while update.is_outer() && par_start < self.len() {
518                // complete current widget first
519                self[par_start].render_update(update);
520                par_start += 1;
521            }
522            let b = self[par_start..]
523                .par_iter_mut()
524                .with_ctx()
525                .fold(
526                    || update.parallel_split(),
527                    |mut update, c| {
528                        c.render_update(&mut update);
529                        update
530                    },
531                )
532                .reduce(
533                    || update.parallel_split(),
534                    |mut a, b| {
535                        a.parallel_fold(b);
536                        a
537                    },
538                );
539            update.parallel_fold(b);
540        } else {
541            self.iter_mut().for_each(|n| n.render_update(update));
542        }
543    }
544
545    fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
546        if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::RENDER) {
547            let mut par_start = 0;
548            while update.is_outer() && par_start < self.len() {
549                // complete current widget first
550                self[par_start].render_update(update);
551                par_start += 1;
552            }
553            let b = self[par_start..]
554                .par_iter_mut()
555                .enumerate()
556                .with_ctx()
557                .fold(
558                    || update.parallel_split(),
559                    |mut update, (i, c)| {
560                        render_update(i, c, &mut update);
561                        update
562                    },
563                )
564                .reduce(
565                    || update.parallel_split(),
566                    |mut a, b| {
567                        a.parallel_fold(b);
568                        a
569                    },
570                );
571            update.parallel_fold(b);
572        } else {
573            self.iter_mut().enumerate().for_each(|(i, n)| render_update(i, n, update));
574        }
575    }
576
577    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
578        None
579    }
580}
581
582/// List methods.
583impl UiNode {
584    /// Create a list node that has `self` followed by `other`.
585    ///
586    /// If `self` or `other` are already lists returns a list view that flattens the children when iterating.
587    ///
588    /// This method returns an optimized list view, it will reuse chain lists when possible,
589    /// ignore nil and other tricks, if you need the inner lists to be a predictable arrangement use [`ChainList`] directly.
590    pub fn chain(self, other: impl IntoUiNode) -> UiNode {
591        self.chain_impl(other.into_node())
592    }
593    fn chain_impl(mut self, mut other: UiNode) -> UiNode {
594        if self.is_nil() {
595            return other;
596        }
597        if other.is_nil() {
598            return self;
599        }
600
601        if let Some(chain) = self.downcast_mut::<ChainList>() {
602            if let Some(other_too) = other.downcast_mut::<ChainList>() {
603                chain.0.append(&mut other_too.0);
604            } else {
605                chain.0.push(other);
606            }
607            self
608        } else {
609            ChainList(ui_vec![self, other]).into_node()
610        }
611    }
612
613    /// Create a sorting list view for this node into list.
614    ///
615    /// The list items are not moved, they are sorted only for layout and render, see [`SortingList`] for more details.
616    ///
617    /// If this node is already a sorting list just replaces the `sort`.
618    pub fn sorting_by(mut self, sort: impl Fn(&mut UiNode, &mut UiNode) -> Ordering + Send + 'static) -> UiNode {
619        if let Some(already) = self.downcast_mut::<SortingList>() {
620            already.sort = Box::new(sort);
621            already.invalidate_sort();
622            self
623        } else {
624            SortingList::new(self, sort).into_node()
625        }
626    }
627}
628
629/// UI node list implementation that flattens child lists.
630pub struct ChainList(pub UiVec);
631impl ChainList {
632    /// Append another list chain node.
633    ///
634    /// See [`UiNode::chain`] for more details.
635    pub fn chain(self, other: impl IntoUiNode) -> UiNode {
636        self.into_node().chain(other)
637    }
638}
639impl UiNodeImpl for ChainList {
640    fn children_len(&self) -> usize {
641        let mut len = 0;
642        for c in self.0.iter() {
643            if c.is_list() {
644                len += c.children_len();
645            } else {
646                len += 1;
647            }
648        }
649        len
650    }
651
652    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
653        let mut offset = 0;
654        for c in self.0.iter_mut() {
655            let next_offset = offset + if c.is_list() { c.children_len() } else { 1 };
656            if next_offset > index {
657                c.with_child(index - offset, visitor);
658                break;
659            }
660            offset = next_offset;
661        }
662    }
663
664    fn is_list(&self) -> bool {
665        true
666    }
667
668    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
669        let mut offset = 0;
670        for c in self.0.iter_mut() {
671            if c.is_list() {
672                c.for_each_child(|i, n| visitor(offset + i, n));
673                offset += c.children_len();
674            } else {
675                visitor(offset, c);
676                offset += 1;
677            }
678        }
679    }
680
681    fn try_for_each_child(
682        &mut self,
683        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
684    ) -> ControlFlow<BoxAnyVarValue> {
685        let mut offset = 0;
686        for c in self.0.iter_mut() {
687            if c.is_list() {
688                let mut cf = ControlFlow::Continue(());
689                c.for_each_child(|i, n| cf = visitor(offset + i, n));
690                cf?;
691                offset += c.children_len();
692            } else {
693                visitor(offset, c)?;
694                offset += 1;
695            }
696        }
697        ControlFlow::Continue(())
698    }
699
700    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
701        let mut offset = 0;
702        for c in self.0.iter_mut() {
703            if c.is_list() {
704                c.par_each_child(|i, n| visitor(offset + i, n));
705                offset += c.children_len();
706            } else {
707                visitor(offset, c);
708                offset += 1;
709            }
710        }
711    }
712
713    fn par_fold_reduce(
714        &mut self,
715        identity: BoxAnyVarValue,
716        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
717        reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
718    ) -> BoxAnyVarValue {
719        let mut offset = 0;
720        let mut accumulator = identity.clone();
721        for c in self.0.iter_mut() {
722            if c.is_list() {
723                accumulator = c.0.par_fold_reduce(identity.clone(), &|acc, i, n| fold(acc, offset + i, n), reduce);
724                offset += c.children_len();
725            } else {
726                accumulator = fold(accumulator, offset, c);
727                offset += 1;
728            }
729        }
730        accumulator
731    }
732
733    fn init(&mut self) {
734        self.0.init();
735    }
736
737    fn deinit(&mut self) {
738        self.0.deinit();
739    }
740
741    fn info(&mut self, info: &mut WidgetInfoBuilder) {
742        self.0.info(info);
743    }
744
745    fn event(&mut self, update: &EventUpdate) {
746        self.0.event(update);
747    }
748
749    fn update(&mut self, updates: &WidgetUpdates) {
750        self.0.update(updates);
751    }
752
753    fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
754        if observer.is_reset_only() {
755            if (self as &mut dyn UiNodeImpl).parallelize_hint() && PARALLEL_VAR.get().contains(Parallel::UPDATE) {
756                let changed = self
757                    .0
758                    .par_iter_mut()
759                    .with_ctx()
760                    .map(|n| {
761                        let mut changed = false;
762                        n.update_list(updates, &mut changed);
763                        changed
764                    })
765                    .reduce(|| false, |a, b| a || b);
766                if changed {
767                    observer.reset();
768                }
769            } else {
770                let mut changed = false;
771                for c in self.0.iter_mut() {
772                    c.update_list(updates, &mut changed);
773                }
774                if changed {
775                    observer.reset();
776                }
777            }
778        } else {
779            let mut offset = 0;
780            for c in self.0.iter_mut() {
781                if c.is_list() {
782                    c.0.update_list(updates, &mut OffsetUiListObserver(offset, observer));
783                    offset += c.children_len();
784                } else {
785                    c.update(updates);
786                    offset += 1;
787                }
788            }
789        }
790    }
791
792    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
793        self.0.measure(wm)
794    }
795
796    fn measure_list(
797        &mut self,
798        wm: &mut WidgetMeasure,
799        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
800        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
801    ) -> PxSize {
802        let mut offset = 0;
803        let mut accumulator = PxSize::zero();
804        for c in self.0.iter_mut() {
805            if c.is_list() {
806                let s = c.0.measure_list(wm, &|i, n, wm| measure(offset + i, n, wm), fold_size);
807                accumulator = fold_size(accumulator, s);
808                offset += c.children_len();
809            } else {
810                let s = measure(offset, c, wm);
811                accumulator = fold_size(accumulator, s);
812                offset += 1;
813            }
814        }
815        accumulator
816    }
817
818    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
819        self.0.layout(wl)
820    }
821
822    fn layout_list(
823        &mut self,
824        wl: &mut WidgetLayout,
825        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
826        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
827    ) -> PxSize {
828        let mut offset = 0;
829        let mut accumulator = PxSize::zero();
830        for c in self.0.iter_mut() {
831            if c.is_list() {
832                let s = c.0.layout_list(wl, &|i, n, wl| layout(offset + i, n, wl), fold_size);
833                accumulator = fold_size(accumulator, s);
834                offset += c.children_len();
835            } else {
836                let s = layout(offset, c, wl);
837                accumulator = fold_size(accumulator, s);
838                offset += 1;
839            }
840        }
841        accumulator
842    }
843
844    fn render(&mut self, frame: &mut FrameBuilder) {
845        self.0.render(frame);
846    }
847
848    fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
849        let mut offset = 0;
850        for c in self.0.iter_mut() {
851            if c.is_list() {
852                c.0.render_list(frame, &|i, n, frame| render(offset + i, n, frame));
853                offset += c.children_len();
854            } else {
855                render(offset, c, frame);
856                offset += 1;
857            }
858        }
859    }
860
861    fn render_update(&mut self, update: &mut FrameUpdate) {
862        self.0.render_update(update);
863    }
864
865    fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
866        let mut offset = 0;
867        for c in self.0.iter_mut() {
868            if c.is_list() {
869                c.0.render_update_list(update, &|i, n, update| render_update(offset + i, n, update));
870                offset += c.children_len();
871            } else {
872                render_update(offset, c, update);
873                offset += 1;
874            }
875        }
876    }
877
878    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
879        None
880    }
881}
882
883/// Represents the contextual parent [`SortingList`] during an update.
884#[expect(non_camel_case_types)]
885pub struct SORTING_LIST;
886impl SORTING_LIST {
887    /// If the current call has a parent sorting list.
888    pub fn is_inside_list(&self) -> bool {
889        !SORTING_LIST_PARENT.is_default()
890    }
891
892    /// Calls [`SortingList::invalidate_sort`] on the parent list.
893    pub fn invalidate_sort(&self) {
894        SORTING_LIST_PARENT.get().store(true, Relaxed)
895    }
896
897    fn with<R>(&self, action: impl FnOnce() -> R) -> (R, bool) {
898        SORTING_LIST_PARENT.with_context(&mut Some(Arc::new(AtomicBool::new(false))), || {
899            let r = action();
900            (r, SORTING_LIST_PARENT.get().load(Relaxed))
901        })
902    }
903}
904context_local! {
905    static SORTING_LIST_PARENT: AtomicBool = AtomicBool::new(false);
906}
907
908/// Represents a sorted view into an [`UiNode::is_list`].
909///
910/// The underlying list is not changed, a sorted index map is used to iterate the underlying list.
911///
912/// The sorting is lazy and gets invalidated on every init and every time there are changes observed in [`update_list`].
913///
914/// Methods `measure_list`, `layout_list`, `render`, `for_each_child` and `par_each_child` are the **only that iterate sorted**. Method
915/// `with_child` uses the sort index. Method `update_list` notifies a reset if there is any change in the list or sorting.
916/// Other methods delegate to the unsorted list.
917///
918/// [`update_list`]: UiNode::update_list
919pub struct SortingList {
920    list: UiNode,
921
922    map: Vec<usize>,
923    sort: Box<dyn Fn(&mut UiNode, &mut UiNode) -> Ordering + Send + 'static>,
924}
925impl SortingList {
926    /// New from list and sort function.
927    pub fn new(list: impl IntoUiNode, sort: impl Fn(&mut UiNode, &mut UiNode) -> Ordering + Send + 'static) -> Self {
928        Self {
929            list: list.into_node().into_list(),
930            map: vec![],
931            sort: Box::new(sort),
932        }
933    }
934
935    fn update_map(&mut self) {
936        let map = &mut self.map;
937        let len = self.list.children_len();
938
939        if len == 0 {
940            map.clear();
941        } else if map.len() != len {
942            map.clear();
943            map.extend(0..len);
944            let mut taken_a = UiNode::nil();
945            map.sort_by(|&a, &b| {
946                self.list.with_child(a, |a| mem::swap(a, &mut taken_a));
947                let result = self.list.with_child(b, |b| (self.sort)(&mut taken_a, b));
948                self.list.with_child(a, |a| mem::swap(a, &mut taken_a));
949
950                result
951            })
952        }
953    }
954    /// Mutable borrow the inner list.
955    ///
956    /// You must call [`invalidate_sort`] if any modification is done to the list.
957    ///
958    /// [`invalidate_sort`]: Self::invalidate_sort
959    pub fn list(&mut self) -> &mut UiNode {
960        &mut self.list
961    }
962
963    /// Invalidate the sort, the list will resort on the nest time the sorted positions are needed.
964    ///
965    /// Note that you can also invalidate sort from the inside using [`SORTING_LIST::invalidate_sort`].
966    pub fn invalidate_sort(&mut self) {
967        self.map.clear()
968    }
969
970    fn with_map<R>(&mut self, f: impl FnOnce(&[usize], &mut UiNode) -> R) -> R {
971        self.update_map();
972
973        let (r, resort) = SORTING_LIST.with(|| f(&self.map, &mut self.list));
974
975        if resort {
976            self.invalidate_sort();
977        }
978
979        r
980    }
981
982    /// Create a list chain node.
983    ///
984    /// See [`UiNode::chain`] for more details.
985    pub fn chain(self, other: impl IntoUiNode) -> UiNode {
986        self.into_node().chain(other)
987    }
988}
989impl UiNodeImpl for SortingList {
990    fn children_len(&self) -> usize {
991        self.list.children_len()
992    }
993
994    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
995        self.with_map(|map, list| {
996            if let Some(index) = map.get(index) {
997                list.0.with_child(*index, visitor)
998            }
999        })
1000    }
1001
1002    fn is_list(&self) -> bool {
1003        true
1004    }
1005
1006    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
1007        self.with_map(|map, list| {
1008            for (i, &actual_i) in map.iter().enumerate() {
1009                list.with_child(actual_i, |n| visitor(i, n));
1010            }
1011        })
1012    }
1013
1014    fn try_for_each_child(
1015        &mut self,
1016        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
1017    ) -> ControlFlow<BoxAnyVarValue> {
1018        self.with_map(|map, list| {
1019            for (i, &actual_i) in map.iter().enumerate() {
1020                let mut cf = ControlFlow::Continue(());
1021                list.with_child(actual_i, |n| cf = visitor(i, n));
1022                cf?;
1023            }
1024            ControlFlow::Continue(())
1025        })
1026    }
1027
1028    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
1029        self.for_each_child(&mut |i, n| visitor(i, n));
1030    }
1031
1032    fn par_fold_reduce(
1033        &mut self,
1034        identity: BoxAnyVarValue,
1035        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
1036        _: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
1037    ) -> BoxAnyVarValue {
1038        let mut acc = Some(identity);
1039        self.for_each_child(&mut |i, n| {
1040            acc = Some(fold(acc.take().unwrap(), i, n));
1041        });
1042        acc.unwrap()
1043    }
1044
1045    fn init(&mut self) {
1046        let _ = SORTING_LIST.with(|| self.list.0.init());
1047        self.invalidate_sort();
1048    }
1049
1050    fn deinit(&mut self) {
1051        let _ = SORTING_LIST.with(|| self.list.0.deinit());
1052        self.invalidate_sort();
1053    }
1054
1055    fn info(&mut self, info: &mut WidgetInfoBuilder) {
1056        self.list.0.info(info);
1057    }
1058
1059    fn event(&mut self, update: &EventUpdate) {
1060        self.list.0.event(update);
1061    }
1062
1063    fn update(&mut self, updates: &WidgetUpdates) {
1064        self.list.0.update(updates);
1065    }
1066
1067    fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1068        let mut changed = false;
1069        let (_, resort) = SORTING_LIST.with(|| self.list.0.update_list(updates, &mut changed));
1070        if changed || resort {
1071            self.invalidate_sort();
1072            observer.reset();
1073        }
1074    }
1075
1076    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1077        self.list.0.measure(wm)
1078    }
1079
1080    fn measure_list(
1081        &mut self,
1082        wm: &mut WidgetMeasure,
1083        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
1084        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1085    ) -> PxSize {
1086        let mut acc = PxSize::zero();
1087        self.for_each_child(&mut |i, n| {
1088            let s = measure(i, n, wm);
1089            acc = fold_size(acc, s);
1090        });
1091        acc
1092    }
1093
1094    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1095        self.list.0.layout(wl)
1096    }
1097
1098    fn layout_list(
1099        &mut self,
1100        wl: &mut WidgetLayout,
1101        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
1102        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1103    ) -> PxSize {
1104        let mut acc = PxSize::zero();
1105        self.for_each_child(&mut |i, n| {
1106            let s = layout(i, n, wl);
1107            acc = fold_size(acc, s);
1108        });
1109        acc
1110    }
1111
1112    fn render(&mut self, frame: &mut FrameBuilder) {
1113        self.for_each_child(&mut |_, n| n.render(frame));
1114    }
1115
1116    fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
1117        self.for_each_child(&mut |i, n| render(i, n, frame));
1118    }
1119
1120    fn render_update(&mut self, update: &mut FrameUpdate) {
1121        self.list.0.render_update(update);
1122    }
1123
1124    fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
1125        self.list.0.render_update_list(update, render_update);
1126    }
1127
1128    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
1129        None
1130    }
1131}
1132
1133/// Represents an [`UiNode::update_list`] observer that can be used to monitor widget insertion, removal and re-order.
1134///
1135/// All indexes are in the context of the previous changes, if you are maintaining a *mirror* vector simply using the
1136/// [`Vec::insert`] and [`Vec::remove`] commands in the same order as they are received should keep the vector in sync.
1137///
1138/// This trait is implemented for `()`, to not observe simply pass on a `&mut ()`.
1139///
1140/// This trait is implemented for [`bool`], if any change happens the flag is set to `true`.
1141pub trait UiNodeListObserver {
1142    /// Called when a node is inserted at `index`.
1143    fn inserted(&mut self, index: usize);
1144    /// Called when a node is removed from `index`.
1145    fn removed(&mut self, index: usize);
1146    /// Called when a node is removed from `removed_index` and re-inserted at `inserted_index`.
1147    fn moved(&mut self, removed_index: usize, inserted_index: usize);
1148    /// Called when large or unspecified changes happen to the list.
1149    fn reset(&mut self);
1150
1151    /// Returns true if this observer does not use the item indexes.
1152    ///
1153    /// When true you can use [`reset`] to notify any changes.
1154    ///
1155    /// This flag can be used by list implementers to enable parallel processing in more contexts, for example, chain lists cannot
1156    /// parallelize because indexes of subsequent lists are dependent on indexes of previous lists, but if the observer only needs
1157    /// to known that some change happened the chain list can still parallelize.
1158    ///
1159    /// [`reset`]: Self::reset
1160    fn is_reset_only(&self) -> bool;
1161}
1162/// Does nothing.
1163impl UiNodeListObserver for () {
1164    fn is_reset_only(&self) -> bool {
1165        true
1166    }
1167
1168    fn reset(&mut self) {}
1169
1170    fn inserted(&mut self, _: usize) {}
1171
1172    fn removed(&mut self, _: usize) {}
1173
1174    fn moved(&mut self, _: usize, _: usize) {}
1175}
1176/// Sets to `true` for any change.
1177impl UiNodeListObserver for bool {
1178    fn is_reset_only(&self) -> bool {
1179        true
1180    }
1181
1182    fn reset(&mut self) {
1183        *self = true;
1184    }
1185
1186    fn inserted(&mut self, _: usize) {
1187        *self = true;
1188    }
1189
1190    fn removed(&mut self, _: usize) {
1191        *self = true;
1192    }
1193
1194    fn moved(&mut self, _: usize, _: usize) {
1195        *self = true;
1196    }
1197}
1198
1199/// Represents an [`UiNodeListObserver`] that applies an offset to all indexes.
1200///
1201/// This type is useful for implementing node lists that are composed of other lists.
1202pub struct OffsetUiListObserver<'o>(pub usize, pub &'o mut dyn UiNodeListObserver);
1203impl UiNodeListObserver for OffsetUiListObserver<'_> {
1204    fn is_reset_only(&self) -> bool {
1205        self.1.is_reset_only()
1206    }
1207
1208    fn reset(&mut self) {
1209        self.1.reset()
1210    }
1211
1212    fn inserted(&mut self, index: usize) {
1213        self.1.inserted(index + self.0)
1214    }
1215
1216    fn removed(&mut self, index: usize) {
1217        self.1.removed(index + self.0)
1218    }
1219
1220    fn moved(&mut self, removed_index: usize, inserted_index: usize) {
1221        self.1.moved(removed_index + self.0, inserted_index + self.0)
1222    }
1223}
1224
1225impl UiNodeListObserver for (&mut dyn UiNodeListObserver, &mut dyn UiNodeListObserver) {
1226    fn is_reset_only(&self) -> bool {
1227        self.0.is_reset_only() && self.1.is_reset_only()
1228    }
1229
1230    fn reset(&mut self) {
1231        self.0.reset();
1232        self.1.reset();
1233    }
1234
1235    fn inserted(&mut self, index: usize) {
1236        self.0.inserted(index);
1237        self.1.inserted(index);
1238    }
1239
1240    fn removed(&mut self, index: usize) {
1241        self.0.removed(index);
1242        self.1.removed(index);
1243    }
1244
1245    fn moved(&mut self, removed_index: usize, inserted_index: usize) {
1246        self.0.moved(removed_index, inserted_index);
1247        self.1.moved(removed_index, inserted_index);
1248    }
1249}
1250
1251/// Represents an [`UiVec`] that can be modified using a connected sender.
1252pub struct EditableUiVec {
1253    vec: UiVec,
1254    ctrl: EditableUiVecRef,
1255}
1256impl Default for EditableUiVec {
1257    fn default() -> Self {
1258        Self {
1259            vec: ui_vec![],
1260            ctrl: EditableUiVecRef::new(true),
1261        }
1262    }
1263}
1264impl Drop for EditableUiVec {
1265    fn drop(&mut self) {
1266        self.ctrl.0.lock().alive = false;
1267    }
1268}
1269impl EditableUiVec {
1270    /// New default empty.
1271    pub fn new() -> Self {
1272        Self::default()
1273    }
1274
1275    /// New from an already allocated vec.
1276    pub fn from_vec(vec: impl Into<UiVec>) -> Self {
1277        let mut s = Self::new();
1278        s.vec = vec.into();
1279        s
1280    }
1281
1282    /// Create a sender that can edit this list.
1283    pub fn reference(&self) -> EditableUiVecRef {
1284        self.ctrl.clone()
1285    }
1286
1287    /// Create a list chain node.
1288    ///
1289    /// See [`UiNode::chain`] for more details.
1290    pub fn chain(self, other: impl IntoUiNode) -> UiNode {
1291        self.into_node().chain(other)
1292    }
1293
1294    fn fulfill_requests(&mut self, observer: &mut dyn UiNodeListObserver) {
1295        if let Some(r) = self.ctrl.take_requests() {
1296            if r.clear {
1297                // if reset
1298                self.clear();
1299                observer.reset();
1300
1301                for (i, mut wgt) in r.insert {
1302                    wgt.init();
1303                    WIDGET.update_info();
1304                    if i < self.len() {
1305                        self.insert(i, wgt);
1306                    } else {
1307                        self.push(wgt);
1308                    }
1309                }
1310                for mut wgt in r.push {
1311                    wgt.init();
1312                    WIDGET.update_info();
1313                    self.push(wgt);
1314                }
1315                for (r, i) in r.move_index {
1316                    if r < self.len() {
1317                        let wgt = self.vec.remove(r);
1318
1319                        if i < self.len() {
1320                            self.vec.insert(i, wgt);
1321                        } else {
1322                            self.vec.push(wgt);
1323                        }
1324
1325                        WIDGET.update_info();
1326                    }
1327                }
1328                for (id, to) in r.move_id {
1329                    if let Some(r) = self.vec.iter_mut().position(|n| n.as_widget().map(|mut w| w.id()) == Some(id)) {
1330                        let i = to(r, self.len());
1331
1332                        if r != i {
1333                            let wgt = self.vec.remove(r);
1334
1335                            if i < self.len() {
1336                                self.vec.insert(i, wgt);
1337                            } else {
1338                                self.vec.push(wgt);
1339                            }
1340
1341                            WIDGET.update_info();
1342                        }
1343                    }
1344                }
1345            } else {
1346                let mut removed = false;
1347                for mut retain in r.retain {
1348                    let mut i = 0;
1349                    self.vec.retain_mut(|n| {
1350                        let r = retain(n);
1351                        if !r {
1352                            n.deinit();
1353                            removed = true;
1354                            observer.removed(i);
1355                        } else {
1356                            i += 1;
1357                        }
1358                        r
1359                    });
1360                }
1361                if removed {
1362                    WIDGET.update_info();
1363                }
1364
1365                for (i, mut wgt) in r.insert {
1366                    wgt.init();
1367                    WIDGET.update_info();
1368
1369                    if i < self.len() {
1370                        self.insert(i, wgt);
1371                        observer.inserted(i);
1372                    } else {
1373                        observer.inserted(self.len());
1374                        self.push(wgt);
1375                    }
1376                }
1377
1378                for mut wgt in r.push {
1379                    wgt.init();
1380                    WIDGET.update_info();
1381
1382                    observer.inserted(self.len());
1383                    self.push(wgt);
1384                }
1385
1386                for (r, i) in r.move_index {
1387                    if r < self.len() {
1388                        let wgt = self.vec.remove(r);
1389
1390                        if i < self.len() {
1391                            self.vec.insert(i, wgt);
1392
1393                            observer.moved(r, i);
1394                        } else {
1395                            let i = self.vec.len();
1396
1397                            self.vec.push(wgt);
1398
1399                            observer.moved(r, i);
1400                        }
1401
1402                        WIDGET.update_info();
1403                    }
1404                }
1405
1406                for (id, to) in r.move_id {
1407                    if let Some(r) = self.vec.iter_mut().position(|n| n.as_widget().map(|mut w| w.id()) == Some(id)) {
1408                        let i = to(r, self.len());
1409
1410                        if r != i {
1411                            let wgt = self.vec.remove(r);
1412
1413                            if i < self.len() {
1414                                self.vec.insert(i, wgt);
1415                                observer.moved(r, i);
1416                            } else {
1417                                let i = self.vec.len();
1418                                self.vec.push(wgt);
1419                                observer.moved(r, i);
1420                            }
1421
1422                            WIDGET.update_info();
1423                        }
1424                    }
1425                }
1426            }
1427        }
1428    }
1429}
1430impl ops::Deref for EditableUiVec {
1431    type Target = UiVec;
1432
1433    fn deref(&self) -> &Self::Target {
1434        &self.vec
1435    }
1436}
1437impl ops::DerefMut for EditableUiVec {
1438    fn deref_mut(&mut self) -> &mut Self::Target {
1439        &mut self.vec
1440    }
1441}
1442impl UiNodeImpl for EditableUiVec {
1443    fn children_len(&self) -> usize {
1444        self.vec.children_len()
1445    }
1446
1447    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
1448        self.vec.with_child(index, visitor);
1449    }
1450
1451    fn is_list(&self) -> bool {
1452        true
1453    }
1454
1455    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
1456        self.vec.for_each_child(visitor);
1457    }
1458
1459    fn try_for_each_child(
1460        &mut self,
1461        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
1462    ) -> ControlFlow<BoxAnyVarValue> {
1463        self.vec.try_for_each_child(visitor)
1464    }
1465
1466    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
1467        self.vec.par_each_child(visitor);
1468    }
1469
1470    fn par_fold_reduce(
1471        &mut self,
1472        identity: BoxAnyVarValue,
1473        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
1474        reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
1475    ) -> BoxAnyVarValue {
1476        self.vec.par_fold_reduce(identity, fold, reduce)
1477    }
1478
1479    fn init(&mut self) {
1480        self.ctrl.0.lock().target = Some(WIDGET.id());
1481        self.vec.init();
1482    }
1483
1484    fn deinit(&mut self) {
1485        self.ctrl.0.lock().target = None;
1486        self.vec.deinit();
1487    }
1488
1489    fn info(&mut self, info: &mut WidgetInfoBuilder) {
1490        self.vec.info(info);
1491    }
1492
1493    fn event(&mut self, update: &EventUpdate) {
1494        self.vec.event(update);
1495    }
1496
1497    fn update(&mut self, updates: &WidgetUpdates) {
1498        self.vec.update(updates);
1499        self.fulfill_requests(&mut ());
1500    }
1501
1502    fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1503        self.vec.update(updates);
1504        self.fulfill_requests(observer);
1505    }
1506
1507    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1508        self.vec.measure(wm)
1509    }
1510
1511    fn measure_list(
1512        &mut self,
1513        wm: &mut WidgetMeasure,
1514        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
1515        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1516    ) -> PxSize {
1517        self.vec.measure_list(wm, measure, fold_size)
1518    }
1519
1520    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1521        self.vec.layout(wl)
1522    }
1523
1524    fn layout_list(
1525        &mut self,
1526        wl: &mut WidgetLayout,
1527        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
1528        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1529    ) -> PxSize {
1530        self.vec.layout_list(wl, layout, fold_size)
1531    }
1532
1533    fn render(&mut self, frame: &mut FrameBuilder) {
1534        self.vec.render(frame);
1535    }
1536
1537    fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
1538        self.vec.render_list(frame, render);
1539    }
1540
1541    fn render_update(&mut self, update: &mut FrameUpdate) {
1542        self.vec.render_update(update);
1543    }
1544
1545    fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
1546        self.vec.render_update_list(update, render_update);
1547    }
1548
1549    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
1550        None
1551    }
1552}
1553
1554/// See [`EditableUiVecRef::move_to`] for more details
1555type NodeMoveToFn = fn(usize, usize) -> usize;
1556
1557/// Represents a sender to an [`EditableUiVec`].
1558#[derive(Clone, Debug)]
1559pub struct EditableUiVecRef(Arc<Mutex<EditRequests>>);
1560struct EditRequests {
1561    target: Option<WidgetId>,
1562    insert: Vec<(usize, UiNode)>,
1563    push: Vec<UiNode>,
1564    retain: Vec<Box<dyn FnMut(&mut UiNode) -> bool + Send>>,
1565    move_index: Vec<(usize, usize)>,
1566    move_id: Vec<(WidgetId, NodeMoveToFn)>,
1567    clear: bool,
1568
1569    alive: bool,
1570}
1571impl fmt::Debug for EditRequests {
1572    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1573        f.debug_struct("EditRequests")
1574            .field("target", &self.target)
1575            .field("insert.len", &self.insert.len())
1576            .field("push.len", &self.push.len())
1577            .field("retain.len", &self.retain.len())
1578            .field("move_index", &self.move_index)
1579            .field("move_id", &self.move_id)
1580            .field("clear", &self.clear)
1581            .field("alive", &self.alive)
1582            .finish()
1583    }
1584}
1585impl EditableUiVecRef {
1586    fn new(alive: bool) -> Self {
1587        Self(Arc::new(Mutex::new(EditRequests {
1588            target: None,
1589            insert: vec![],
1590            push: vec![],
1591            retain: vec![],
1592            move_index: vec![],
1593            move_id: vec![],
1594            clear: false,
1595            alive,
1596        })))
1597    }
1598
1599    /// New reference to no list.
1600    ///
1601    /// [`alive`] is always false for the returned list.
1602    ///
1603    /// [`alive`]: Self::alive
1604    pub fn dummy() -> Self {
1605        Self::new(false)
1606    }
1607
1608    /// Returns `true` if the [`EditableUiVec`] still exists.
1609    pub fn alive(&self) -> bool {
1610        self.0.lock().alive
1611    }
1612
1613    /// Request an update for the insertion of the `widget`.
1614    ///
1615    /// The `index` is resolved after all [`remove`] requests, if it is out-of-bounds the widget is pushed.
1616    ///
1617    /// The `widget` will be inserted, inited and the info tree updated.
1618    ///
1619    /// [`remove`]: Self::remove
1620    pub fn insert(&self, index: usize, widget: impl IntoUiNode) {
1621        self.insert_impl(index, widget.into_node());
1622    }
1623    fn insert_impl(&self, index: usize, widget: UiNode) {
1624        let mut s = self.0.lock();
1625        if !s.alive {
1626            return;
1627        }
1628        s.insert.push((index, widget));
1629        UPDATES.update(s.target);
1630    }
1631
1632    /// Request an update for the insertion of the `widget` at the end of the list.
1633    ///
1634    /// The widget will be pushed after all [`insert`] requests.
1635    ///
1636    /// The `widget` will be inserted, inited and the info tree updated.
1637    ///
1638    /// [`insert`]: Self::insert
1639    pub fn push(&self, widget: impl IntoUiNode) {
1640        self.push_impl(widget.into_node());
1641    }
1642    fn push_impl(&self, widget: UiNode) {
1643        let mut s = self.0.lock();
1644        if !s.alive {
1645            return;
1646        }
1647        s.push.push(widget);
1648        UPDATES.update(s.target);
1649    }
1650
1651    /// Request an update for the removal of the widget identified by `id`.
1652    ///
1653    /// The widget will be deinited, dropped and the info tree will update. Nothing happens
1654    /// if the widget is not found.
1655    pub fn remove(&self, id: impl Into<WidgetId>) {
1656        fn rmv_retain(id: WidgetId) -> impl FnMut(&mut UiNode) -> bool + Send + 'static {
1657            move |node| {
1658                match node.as_widget() {
1659                    Some(mut wgt) => wgt.id() != id,
1660                    None => true, // retain
1661                }
1662            }
1663        }
1664        self.retain(rmv_retain(id.into()))
1665    }
1666
1667    /// Request a filtered mass removal of nodes in the list.
1668    ///
1669    /// Each node not retained will be deinited, dropped and the info tree will update if any was removed.
1670    ///
1671    /// Note that the `predicate` may be called on the same node multiple times or called in any order.
1672    pub fn retain(&self, predicate: impl FnMut(&mut UiNode) -> bool + Send + 'static) {
1673        let mut s = self.0.lock();
1674        if !s.alive {
1675            return;
1676        }
1677        s.retain.push(Box::new(predicate));
1678        UPDATES.update(s.target);
1679    }
1680
1681    /// Request a widget remove and re-insert.
1682    ///
1683    /// If the `remove_index` is out of bounds nothing happens, if the `insert_index` is out-of-bounds
1684    /// the widget is pushed to the end of the vector, if `remove_index` and `insert_index` are equal nothing happens.
1685    ///
1686    /// Move requests happen after all other requests.
1687    pub fn move_index(&self, remove_index: usize, insert_index: usize) {
1688        if remove_index != insert_index {
1689            let mut s = self.0.lock();
1690            if !s.alive {
1691                return;
1692            }
1693            s.move_index.push((remove_index, insert_index));
1694            UPDATES.update(s.target);
1695        }
1696    }
1697
1698    /// Request a widget move, the widget is searched by `id`, if found `get_move_to` id called with the index of the widget and length
1699    /// of the vector, it must return the index the widget is inserted after it is removed.
1700    ///
1701    /// If the widget is not found nothing happens, if the returned index is the same nothing happens, if the returned index
1702    /// is out-of-bounds the widget if pushed to the end of the vector.
1703    ///
1704    /// Move requests happen after all other requests.
1705    ///
1706    /// # Examples
1707    ///
1708    /// If the widget vectors is layout as a vertical stack to move the widget *up* by one stopping at the top:
1709    ///
1710    /// ```
1711    /// # fn demo(items: zng_app::widget::node::EditableUiVecRef) {
1712    /// items.move_id("my-widget", |i, _len| i.saturating_sub(1));
1713    /// # }
1714    /// ```
1715    ///
1716    /// And to move *down* stopping at the bottom:
1717    ///
1718    /// ```
1719    /// # fn demo(items: zng_app::widget::node::EditableUiVecRef) {
1720    /// items.move_id("my-widget", |i, _len| i.saturating_add(1));
1721    /// # }
1722    /// ```
1723    ///
1724    /// Note that if the returned index overflows the length the widget is
1725    /// pushed as the last item.
1726    ///
1727    /// The length can be used for implementing wrapping move *down*:
1728    ///
1729    /// ```
1730    /// # fn demo(items: zng_app::widget::node::EditableUiVecRef) {
1731    /// items.move_id("my-widget", |i, len| {
1732    ///     let next = i + 1;
1733    ///     if next < len { next } else { 0 }
1734    /// });
1735    /// # }
1736    /// ```
1737    pub fn move_id(&self, id: impl Into<WidgetId>, get_move_to: NodeMoveToFn) {
1738        let mut s = self.0.lock();
1739        if !s.alive {
1740            return;
1741        }
1742        s.move_id.push((id.into(), get_move_to));
1743        UPDATES.update(s.target);
1744    }
1745
1746    /// Request a removal of all current widgets.
1747    ///
1748    /// All other requests will happen after the clear.
1749    pub fn clear(&self) {
1750        let mut s = self.0.lock();
1751        s.clear = true;
1752        UPDATES.update(s.target);
1753    }
1754
1755    fn take_requests(&self) -> Option<EditRequests> {
1756        let mut s = self.0.lock();
1757
1758        if s.clear
1759            || !s.insert.is_empty()
1760            || !s.push.is_empty()
1761            || !s.retain.is_empty()
1762            || !s.move_index.is_empty()
1763            || !s.move_id.is_empty()
1764        {
1765            let empty = EditRequests {
1766                target: s.target,
1767                alive: s.alive,
1768
1769                insert: vec![],
1770                push: vec![],
1771                retain: vec![],
1772                move_index: vec![],
1773                move_id: vec![],
1774                clear: false,
1775            };
1776            Some(mem::replace(&mut *s, empty))
1777        } else {
1778            None
1779        }
1780    }
1781}
1782
1783static_id! {
1784    static ref Z_INDEX_ID: StateId<ZIndex>;
1785}
1786
1787/// Position of a widget inside an UI node list render operation.
1788///
1789/// When two widgets have the same index their logical position defines the render order.
1790///
1791/// # Examples
1792///
1793/// Create a Z-index that causes the widget to render in front of all siblings that don't set Z-index.
1794///
1795/// ```
1796/// # use zng_app::widget::node::ZIndex;
1797/// #
1798/// let highlight_z = ZIndex::DEFAULT + 1;
1799/// ```
1800#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Transitionable)]
1801pub struct ZIndex(u32);
1802impl ZIndex {
1803    /// Widget is rendered first causing all overlapping siblings to render on top of it.
1804    ///
1805    /// The value is `0`.
1806    pub const BACK: ZIndex = ZIndex(0);
1807
1808    /// Z-index of widgets that don't set the index.
1809    ///
1810    /// The value is `u32::MAX / 2`.
1811    pub const DEFAULT: ZIndex = ZIndex(u32::MAX / 2);
1812
1813    /// Widget is rendered after all siblings causing it to render on top.
1814    pub const FRONT: ZIndex = ZIndex(u32::MAX);
1815
1816    /// Computes `other` above `self`, caps at [`FRONT`].
1817    ///
1818    /// This is the default ZIndex addition, equivalent to `self + other`.
1819    ///
1820    /// [`FRONT`]: Self::FRONT
1821    pub fn saturating_add(self, other: impl Into<Self>) -> Self {
1822        ZIndex(self.0.saturating_add(other.into().0))
1823    }
1824
1825    /// Computes `other` below `self`, stops at [`BACK`].
1826    ///
1827    /// This is the default ZIndex subtraction, equivalent to `self - other`.
1828    ///
1829    /// [`BACK`]: Self::BACK
1830    pub fn saturating_sub(self, other: impl Into<Self>) -> Self {
1831        ZIndex(self.0.saturating_sub(other.into().0))
1832    }
1833}
1834impl Default for ZIndex {
1835    fn default() -> Self {
1836        ZIndex::DEFAULT
1837    }
1838}
1839impl<Z: Into<ZIndex>> ops::Add<Z> for ZIndex {
1840    type Output = Self;
1841
1842    fn add(self, rhs: Z) -> Self::Output {
1843        self.saturating_add(rhs)
1844    }
1845}
1846impl<Z: Into<ZIndex>> ops::AddAssign<Z> for ZIndex {
1847    fn add_assign(&mut self, rhs: Z) {
1848        *self = *self + rhs;
1849    }
1850}
1851impl<Z: Into<ZIndex>> ops::Sub<Z> for ZIndex {
1852    type Output = Self;
1853
1854    fn sub(self, rhs: Z) -> Self::Output {
1855        self.saturating_sub(rhs)
1856    }
1857}
1858impl<Z: Into<ZIndex>> ops::SubAssign<Z> for ZIndex {
1859    fn sub_assign(&mut self, rhs: Z) {
1860        *self = *self - rhs;
1861    }
1862}
1863impl ops::Mul<Factor> for ZIndex {
1864    type Output = Self;
1865
1866    fn mul(self, rhs: Factor) -> Self::Output {
1867        ZIndex(self.0 * rhs)
1868    }
1869}
1870impl ops::Div<Factor> for ZIndex {
1871    type Output = Self;
1872
1873    fn div(self, rhs: Factor) -> Self::Output {
1874        ZIndex(self.0 / rhs)
1875    }
1876}
1877impl ops::MulAssign<Factor> for ZIndex {
1878    fn mul_assign(&mut self, rhs: Factor) {
1879        self.0 *= rhs;
1880    }
1881}
1882impl ops::DivAssign<Factor> for ZIndex {
1883    fn div_assign(&mut self, rhs: Factor) {
1884        self.0 /= rhs;
1885    }
1886}
1887impl fmt::Debug for ZIndex {
1888    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1889        let z = *self;
1890        if f.alternate() {
1891            write!(f, "ZIndex::")?;
1892        }
1893
1894        if z == Self::DEFAULT {
1895            write!(f, "DEFAULT")
1896        } else if z == Self::BACK {
1897            write!(f, "BACK")
1898        } else if z == Self::FRONT {
1899            write!(f, "FRONT")
1900        } else if z > Self::DEFAULT {
1901            if z > Self::FRONT - 10000 {
1902                write!(f, "FRONT-{}", Self::FRONT.0 - z.0)
1903            } else {
1904                write!(f, "DEFAULT+{}", z.0 - Self::DEFAULT.0)
1905            }
1906        } else if z < Self::BACK + 10000 {
1907            write!(f, "BACK+{}", z.0 - Self::BACK.0)
1908        } else {
1909            write!(f, "DEFAULT-{}", Self::DEFAULT.0 - z.0)
1910        }
1911    }
1912}
1913impl_from_and_into_var! {
1914    fn from(index: u32) -> ZIndex {
1915        ZIndex(index)
1916    }
1917    fn from(index: ZIndex) -> u32 {
1918        index.0
1919    }
1920    fn from(index: ZIndex) -> Option<ZIndex>;
1921}
1922#[derive(Default, Debug)]
1923struct ZIndexCtx {
1924    // used in `z_index` to validate that it will have an effect.
1925    panel_id: Option<WidgetId>,
1926    // set by `z_index` to signal a z-resort is needed.
1927    resort: AtomicBool,
1928}
1929context_local! {
1930    static Z_INDEX_CTX: ZIndexCtx = ZIndexCtx::default();
1931}
1932/// Access to widget z-index in a parent [`PanelList`].
1933#[expect(non_camel_case_types)]
1934pub struct Z_INDEX;
1935impl Z_INDEX {
1936    fn with(&self, panel_id: WidgetId, action: impl FnOnce()) -> bool {
1937        let ctx = ZIndexCtx {
1938            panel_id: Some(panel_id),
1939            resort: AtomicBool::new(false),
1940        };
1941        Z_INDEX_CTX.with_context(&mut Some(Arc::new(ctx)), || {
1942            action();
1943            Z_INDEX_CTX.get().resort.load(Relaxed)
1944        })
1945    }
1946
1947    /// Gets the index set on the [`WIDGET`].
1948    ///
1949    /// Returns `DEFAULT` if the node is not a widget.
1950    pub fn get(&self) -> ZIndex {
1951        WIDGET.get_state(*Z_INDEX_ID).unwrap_or_default()
1952    }
1953
1954    /// Gets the index set on the `widget`.
1955    ///
1956    /// Returns `DEFAULT` if the node is not a widget.
1957    pub fn get_wgt(&self, widget: &mut UiNode) -> ZIndex {
1958        match widget.as_widget() {
1959            Some(mut w) => w.with_context(WidgetUpdateMode::Ignore, || self.get()),
1960            None => ZIndex::DEFAULT,
1961        }
1962    }
1963
1964    /// Try set the z-index in the current [`WIDGET`].
1965    ///
1966    /// Returns if z-index can be set on the widget, this is only `true` if the current [`WIDGET`]
1967    /// is a direct child of a panel widget that supports z-index.
1968    ///
1969    /// This must be called on node init and update only, always returns `false` if called during
1970    /// other node operations.
1971    pub fn set(&self, index: ZIndex) -> bool {
1972        let z_ctx = Z_INDEX_CTX.get();
1973        let valid = z_ctx.panel_id == WIDGET.parent_id() && z_ctx.panel_id.is_some();
1974        if valid {
1975            z_ctx.resort.store(true, Relaxed);
1976            WIDGET.set_state(*Z_INDEX_ID, index);
1977        }
1978        valid
1979    }
1980}
1981
1982/// First and last child widget in a [`PanelList`].
1983#[derive(Debug, Clone)]
1984pub struct PanelListRange {
1985    // none is empty
1986    range: Option<(WidgetId, WidgetId)>,
1987    version: u8,
1988}
1989impl PanelListRange {
1990    /// Gets the panel children if it may have changed since `last_version`.
1991    ///
1992    /// The [`PanelList`] requests an update for each child after info rebuild if it has changed,
1993    /// the item properties can used this method on update to react.
1994    pub fn update(
1995        parent: &WidgetInfo,
1996        panel_id: impl Into<StateId<Self>>,
1997        last_version: &mut Option<u8>,
1998    ) -> Option<crate::widget::info::iter::Children> {
1999        let range = parent.meta().get_clone(panel_id);
2000        if let Some(Self { range, version }) = range {
2001            let version = Some(version);
2002            if *last_version != version {
2003                *last_version = version;
2004
2005                if let Some((s, e)) = range {
2006                    let tree = parent.tree();
2007                    if let Some(s) = tree.get(s)
2008                        && let Some(e) = tree.get(e)
2009                    {
2010                        let parent = Some(parent);
2011                        if s.parent().as_ref() == parent && e.parent().as_ref() == parent {
2012                            return Some(crate::widget::info::iter::Children::new_range(s, e));
2013                        }
2014                    }
2015                }
2016            }
2017        }
2018        None
2019    }
2020
2021    /// Gets the panel children if the `parent` contains the `panel_id`.
2022    pub fn get(parent: &WidgetInfo, panel_id: impl Into<StateId<Self>>) -> Option<crate::widget::info::iter::Children> {
2023        let range = parent.meta().get_clone(panel_id);
2024        if let Some(Self { range: Some((s, e)), .. }) = range {
2025            let tree = parent.tree();
2026            if let Some(s) = tree.get(s)
2027                && let Some(e) = tree.get(e)
2028            {
2029                let parent = Some(parent);
2030                if s.parent().as_ref() == parent && e.parent().as_ref() == parent {
2031                    return Some(crate::widget::info::iter::Children::new_range(s, e));
2032                }
2033            }
2034        }
2035        None
2036    }
2037}
2038
2039/// Represents the final UI list in a panel layout node.
2040///
2041/// Panel widgets should wrap their children node on this type to support Z-index sorting and to easily track associated
2042/// item data.
2043///
2044/// By default the associated item data is a [`DefaultPanelListData`] that represents the offset of each item inside the panel,
2045/// but it can be any type that implements [`PanelListData`]. The panel list default render implementation uses this data
2046/// to position the children widgets. Note that you must [`commit_data`] changes to this data at the end of a layout pass.
2047///
2048/// Panel widgets can also mark the list using [`track_info_range`] to implement getter properties such as `is_odd` or
2049/// `is_even`.
2050///
2051/// [`track_info_range`]: Self::track_info_range
2052/// [`commit_data`]: Self::commit_data
2053pub struct PanelList<D = DefaultPanelListData>
2054where
2055    D: PanelListData,
2056{
2057    list: UiNode,
2058    data: Vec<Mutex<D>>, // Mutex to implement `par_each_mut`.
2059
2060    offset_key: FrameValueKey<PxTransform>,
2061    info_id: Option<(StateId<PanelListRange>, u8, bool)>,
2062
2063    z_map: Vec<u64>,
2064    z_naturally_sorted: bool,
2065}
2066impl PanelList<DefaultPanelListData> {
2067    /// New from `list` and default data.
2068    pub fn new(list: impl IntoUiNode) -> Self {
2069        Self::new_custom(list)
2070    }
2071}
2072
2073impl<D> PanelList<D>
2074where
2075    D: PanelListData,
2076{
2077    /// New from `list` and custom data type.
2078    pub fn new_custom(list: impl IntoUiNode) -> Self {
2079        Self::new_custom_impl(list.into_node())
2080    }
2081    fn new_custom_impl(list: UiNode) -> Self {
2082        let list = list.into_list();
2083        Self {
2084            data: {
2085                let mut d = vec![];
2086                d.resize_with(list.children_len(), Default::default);
2087                d
2088            },
2089            list,
2090            offset_key: FrameValueKey::new_unique(),
2091            info_id: None,
2092            z_map: vec![],
2093            z_naturally_sorted: false,
2094        }
2095    }
2096
2097    /// Enable tracking the first and last child in the parent widget info.
2098    ///
2099    /// The info is set in the `info_id`, it can be used to identify the children widgets
2100    /// that are the panel children as the info tree may track extra widgets as children
2101    /// when they are set by other properties, like background.
2102    pub fn track_info_range(mut self, info_id: impl Into<StateId<PanelListRange>>) -> Self {
2103        self.info_id = Some((info_id.into(), 0, true));
2104        self
2105    }
2106
2107    /// Into list and associated data.
2108    pub fn into_parts(self) -> (UiNode, Vec<Mutex<D>>, FrameValueKey<PxTransform>, Option<StateId<PanelListRange>>) {
2109        (self.list, self.data, self.offset_key, self.info_id.map(|t| t.0))
2110    }
2111
2112    /// New from list and associated data.
2113    ///
2114    /// # Panics
2115    ///
2116    /// Panics if the `list` and `data` don't have the same length.
2117    pub fn from_parts(
2118        list: UiNode,
2119        data: Vec<Mutex<D>>,
2120        offset_key: FrameValueKey<PxTransform>,
2121        info_id: Option<StateId<PanelListRange>>,
2122    ) -> Self {
2123        assert!(list.is_list());
2124        assert_eq!(list.children_len(), data.len());
2125        Self {
2126            list,
2127            data,
2128            offset_key,
2129            info_id: info_id.map(|i| (i, 0, true)),
2130            z_map: vec![],
2131            z_naturally_sorted: false,
2132        }
2133    }
2134
2135    /// Gets the ID set on the parent widget info if [`track_info_range`] was enabled.
2136    ///
2137    /// [`track_info_range`]: Self::track_info_range
2138    pub fn info_id(&self) -> Option<StateId<PanelListRange>> {
2139        self.info_id.as_ref().map(|t| t.0)
2140    }
2141
2142    /// Call `visitor` with a exclusive reference to the child node and associated data identified by `index`.
2143    ///
2144    /// Panics if the `index` is out of bounds.
2145    pub fn with_child<R>(&mut self, index: usize, visitor: impl FnOnce(&mut UiNode, &mut D) -> R) -> R {
2146        let data = self.data[index].get_mut();
2147        self.list.with_child(index, |u| visitor(u, data))
2148    }
2149
2150    /// Call `visitor` for each child node of `self`, one at a time.
2151    ///
2152    /// The closure parameters are the child index, the child and the associated data.
2153    pub fn for_each_child(&mut self, mut visitor: impl FnMut(usize, &mut UiNode, &mut D)) {
2154        let data = &mut self.data;
2155        self.list.for_each_child(|i, u| visitor(i, u, data[i].get_mut()));
2156    }
2157
2158    /// Call `visitor` for each child node of `self`, one at a time, with control flow.
2159    ///
2160    /// The closure parameters are the child index, the child and the associated data.
2161    pub fn try_for_each_child<B: zng_var::VarValue>(
2162        &mut self,
2163        visitor: &mut dyn FnMut(usize, &mut UiNode, &mut D) -> ControlFlow<B>,
2164    ) -> ControlFlow<B> {
2165        let data = &mut self.data;
2166        self.list.try_for_each_child(|i, u| visitor(i, u, data[i].get_mut()))
2167    }
2168
2169    /// Calls `visitor` for each child node in parallel.
2170    ///
2171    /// The closure parameters are the child index, the child and the associated data.
2172    pub fn par_each_child(&mut self, visitor: impl Fn(usize, &mut UiNode, &mut D) + Sync)
2173    where
2174        D: Sync,
2175    {
2176        let data = &self.data;
2177        self.list.par_each_child(|i, u| {
2178            visitor(
2179                i,
2180                u,
2181                &mut *data[i].try_lock().expect("par_each_child called visitor twice on same index"),
2182            )
2183        });
2184    }
2185
2186    /// Calls `fold` for each child node with associated data in parallel, with fold accumulators produced by cloning
2187    /// `identity`, then merges the folded results using `reduce` to produce the final value also in parallel.
2188    ///
2189    /// The `reduce` call is [associative], the order is preserved in the result.
2190    ///
2191    /// [associative]: https://en.wikipedia.org/wiki/Associative_property
2192    pub fn par_fold_reduce<T>(
2193        &mut self,
2194        identity: T,
2195        fold: impl Fn(T, usize, &mut UiNode, &mut D) -> T + Sync,
2196        reduce: impl Fn(T, T) -> T + Send + Sync,
2197    ) -> T
2198    where
2199        T: zng_var::VarValue,
2200    {
2201        let data = &self.data;
2202        self.list.par_fold_reduce(
2203            identity,
2204            |acc, i, n| {
2205                fold(
2206                    acc,
2207                    i,
2208                    n,
2209                    &mut *data[i].try_lock().expect("par_fold_reduce called visitor twice on same index"),
2210                )
2211            },
2212            reduce,
2213        )
2214    }
2215
2216    /// Call `measure` for each node with associated data and combines the final size using `fold_size`.
2217    pub fn measure_list(
2218        &mut self,
2219        wm: &mut WidgetMeasure,
2220        measure: impl Fn(usize, &mut UiNode, &mut D, &mut WidgetMeasure) -> PxSize + Sync,
2221        fold_size: impl Fn(PxSize, PxSize) -> PxSize + Sync,
2222    ) -> PxSize {
2223        let data = &self.data;
2224        self.list.measure_list(
2225            wm,
2226            |i, n, wm| {
2227                measure(
2228                    i,
2229                    n,
2230                    &mut *data[i].try_lock().expect("measure_list called visitor twice on same index"),
2231                    wm,
2232                )
2233            },
2234            fold_size,
2235        )
2236    }
2237
2238    /// Call `layout` for each node with associated data and combines the final size using `fold_size`.
2239    pub fn layout_list(
2240        &mut self,
2241        wl: &mut WidgetLayout,
2242        layout: impl Fn(usize, &mut UiNode, &mut D, &mut WidgetLayout) -> PxSize + Sync,
2243        fold_size: impl Fn(PxSize, PxSize) -> PxSize + Sync,
2244    ) -> PxSize {
2245        let data = &self.data;
2246        self.list.layout_list(
2247            wl,
2248            |i, n, wl| {
2249                layout(
2250                    i,
2251                    n,
2252                    &mut *data[i].try_lock().expect("layout_list called visitor twice on same index"),
2253                    wl,
2254                )
2255            },
2256            fold_size,
2257        )
2258    }
2259
2260    /// Call `render` for each node with associated data.
2261    ///
2262    /// Note that the [`PanelListData`] child offset and reference frame are already pushed when `render` is called.
2263    pub fn render_list(&mut self, frame: &mut FrameBuilder, render: impl Fn(usize, &mut UiNode, &mut D, &mut FrameBuilder) + Sync) {
2264        let offset_key = self.offset_key;
2265
2266        if self.z_naturally_sorted {
2267            let data = &self.data;
2268            self.list.render_list(frame, |i, child, frame| {
2269                let mut data = data[i].try_lock().expect("render_list called visitor twice on same index");
2270                let offset = data.child_offset();
2271                if data.define_reference_frame() {
2272                    frame.push_reference_frame(
2273                        (offset_key, i as u32).into(),
2274                        offset_key.bind_child(i as u32, offset.into(), false),
2275                        true,
2276                        true,
2277                        |frame| render(i, child, &mut *data, frame),
2278                    );
2279                } else {
2280                    frame.push_child(offset, |frame| render(i, child, &mut *data, frame));
2281                }
2282            });
2283        } else {
2284            self.for_each_z_sorted(|i, child, data| {
2285                let offset = data.child_offset();
2286                if data.define_reference_frame() {
2287                    frame.push_reference_frame(
2288                        (offset_key, i as u32).into(),
2289                        offset_key.bind_child(i as u32, offset.into(), false),
2290                        true,
2291                        true,
2292                        |frame| render(i, child, data, frame),
2293                    );
2294                } else {
2295                    frame.push_child(offset, |frame| render(i, child, data, frame));
2296                }
2297            });
2298        }
2299    }
2300
2301    /// Call `render_update` for each node with associated data.
2302    ///
2303    /// Note that the [`PanelListData`] child offset and reference frame are already pushed when `render_update` is called.
2304    pub fn render_update_list(
2305        &mut self,
2306        update: &mut FrameUpdate,
2307        render_update: impl Fn(usize, &mut UiNode, &mut D, &mut FrameUpdate) + Sync,
2308    ) {
2309        let offset_key = self.offset_key;
2310        let data = &self.data;
2311        self.list.render_update_list(update, |i, n, update| {
2312            let mut data = data[i].try_lock().expect("render_update_list called visitor twice on same index");
2313
2314            let offset = data.child_offset();
2315            if data.define_reference_frame() {
2316                update.with_transform(offset_key.update_child(i as u32, offset.into(), false), true, |update| {
2317                    render_update(i, n, &mut *data, update);
2318                });
2319            } else {
2320                update.with_child(offset, |update| {
2321                    render_update(i, n, &mut *data, update);
2322                });
2323            }
2324        });
2325    }
2326
2327    /// Iterate over the list in the Z order.
2328    pub fn for_each_z_sorted(&mut self, mut visitor: impl FnMut(usize, &mut UiNode, &mut D)) {
2329        if self.z_naturally_sorted {
2330            self.for_each_child(visitor)
2331        } else {
2332            if self.z_map.len() != self.list.children_len() {
2333                self.z_sort();
2334            }
2335
2336            if self.z_naturally_sorted {
2337                self.for_each_child(visitor);
2338            } else {
2339                for &index in self.z_map.iter() {
2340                    let index = index as usize;
2341                    let data = self.data[index].get_mut();
2342                    self.list.with_child(index, |node| visitor(index, node, data));
2343                }
2344            }
2345        }
2346    }
2347
2348    fn z_sort(&mut self) {
2349        // We pack *z* and *i* as u32s in one u64 then create the sorted lookup table if
2350        // observed `[I].Z < [I-1].Z`, also records if any `Z != DEFAULT`:
2351        //
2352        // Advantages:
2353        //
2354        // - Makes `sort_unstable` stable.
2355        // - Only one alloc needed, just mask out Z after sorting.
2356        //
2357        // Disadvantages:
2358        //
2359        // - Only supports u32::MAX widgets.
2360        // - Uses 64-bit indexes in 32-bit builds.
2361
2362        let len = self.list.children_len();
2363        assert!(len <= u32::MAX as usize);
2364
2365        let mut prev_z = ZIndex::BACK;
2366        let mut need_map = false;
2367        let mut z_and_i = Vec::with_capacity(len);
2368        let mut has_non_default_zs = false;
2369
2370        self.list.for_each_child(|i, node| {
2371            let z = Z_INDEX.get_wgt(node);
2372            z_and_i.push(((z.0 as u64) << 32) | i as u64);
2373
2374            need_map |= z < prev_z;
2375            has_non_default_zs |= z != ZIndex::DEFAULT;
2376            prev_z = z;
2377        });
2378
2379        self.z_naturally_sorted = !need_map;
2380
2381        if need_map {
2382            z_and_i.sort_unstable();
2383
2384            for z in &mut z_and_i {
2385                *z &= u32::MAX as u64;
2386            }
2387
2388            self.z_map = z_and_i;
2389        } else {
2390            self.z_map.clear();
2391        }
2392    }
2393
2394    /// Gets the `index` sorted in the `list`.
2395    pub fn z_map(&mut self, index: usize) -> usize {
2396        if self.z_naturally_sorted {
2397            return index;
2398        }
2399
2400        if self.z_map.len() != self.list.children_len() {
2401            self.z_sort();
2402        }
2403
2404        if self.z_naturally_sorted {
2405            return index;
2406        }
2407
2408        self.z_map[index] as usize
2409    }
2410
2411    /// Reference the associated data.
2412    pub fn data(&mut self, index: usize) -> &mut D {
2413        self.data[index].get_mut()
2414    }
2415
2416    /// Calls [`commit`] for each child data, aggregate changes.
2417    ///
2418    /// This must be called after the last update to the children data in a layout pass. Note that
2419    /// you can call [`commit`] directly in a `for_each` iteration if that iteration is the
2420    /// last in the layout pass.
2421    ///
2422    /// [`commit`]: PanelListData::commit
2423    pub fn commit_data(&mut self) -> PanelListDataChanges {
2424        let mut changes = PanelListDataChanges::empty();
2425        for data in self.data.iter_mut() {
2426            changes |= data.get_mut().commit();
2427        }
2428        changes
2429    }
2430
2431    /// Key used to define reference frames for each item.
2432    ///
2433    /// The default implementation of `render_all` uses this key and the item index.
2434    pub fn offset_key(&self) -> FrameValueKey<PxTransform> {
2435        self.offset_key
2436    }
2437}
2438impl<D> UiNodeImpl for PanelList<D>
2439where
2440    D: PanelListData,
2441{
2442    fn children_len(&self) -> usize {
2443        self.list.0.children_len()
2444    }
2445
2446    fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2447        self.list.0.with_child(index, visitor)
2448    }
2449
2450    fn is_list(&self) -> bool {
2451        true
2452    }
2453
2454    fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2455        self.list.0.for_each_child(visitor);
2456    }
2457
2458    fn try_for_each_child(
2459        &mut self,
2460        visitor: &mut dyn FnMut(usize, &mut UiNode) -> ControlFlow<BoxAnyVarValue>,
2461    ) -> ControlFlow<BoxAnyVarValue> {
2462        self.list.0.try_for_each_child(visitor)
2463    }
2464
2465    fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2466        self.list.0.par_each_child(visitor);
2467    }
2468
2469    fn par_fold_reduce(
2470        &mut self,
2471        identity: BoxAnyVarValue,
2472        fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2473        reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2474    ) -> BoxAnyVarValue {
2475        self.list.0.par_fold_reduce(identity, fold, reduce)
2476    }
2477
2478    fn init(&mut self) {
2479        self.z_map.clear();
2480        let resort = Z_INDEX.with(WIDGET.id(), || self.list.0.init());
2481        self.z_naturally_sorted = !resort;
2482        self.data.resize_with(self.list.0.children_len(), Default::default);
2483    }
2484
2485    fn deinit(&mut self) {
2486        self.list.deinit();
2487    }
2488
2489    fn info(&mut self, info: &mut WidgetInfoBuilder) {
2490        let len = self.list.0.children_len();
2491        if len == 0 {
2492            return;
2493        }
2494
2495        self.list.0.info(info);
2496
2497        if let Some((id, version, pump_update)) = &mut self.info_id {
2498            let start = self.list.with_child(0, |c| c.as_widget().map(|mut w| w.id()));
2499            let end = self.list.with_child(len - 1, |c| c.as_widget().map(|mut w| w.id()));
2500            let range = match (start, end) {
2501                (Some(s), Some(e)) => Some((s, e)),
2502                _ => None,
2503            };
2504            info.set_meta(*id, PanelListRange { range, version: *version });
2505
2506            if mem::take(pump_update) {
2507                self.list.for_each_child(|_, c| {
2508                    if let Some(mut w) = c.as_widget() {
2509                        w.with_context(WidgetUpdateMode::Bubble, || WIDGET.update());
2510                    }
2511                });
2512            }
2513        }
2514    }
2515
2516    fn event(&mut self, update: &EventUpdate) {
2517        self.list.event(update);
2518    }
2519
2520    fn update(&mut self, updates: &WidgetUpdates) {
2521        self.update_list(updates, &mut ());
2522    }
2523
2524    fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2525        let mut observer = PanelObserver {
2526            changed: false,
2527            data: &mut self.data,
2528            observer,
2529        };
2530        let resort = Z_INDEX.with(WIDGET.id(), || self.list.update_list(updates, &mut observer));
2531        let observer_changed = observer.changed;
2532        if resort || (observer.changed && self.z_naturally_sorted) {
2533            self.z_map.clear();
2534            self.z_naturally_sorted = false;
2535            WIDGET.render();
2536        }
2537        self.data.resize_with(self.list.children_len(), Default::default);
2538
2539        if observer_changed && let Some((_, v, u)) = &mut self.info_id {
2540            if !*u {
2541                *v = v.wrapping_add(1);
2542                *u = true;
2543            }
2544            WIDGET.info();
2545        }
2546    }
2547
2548    fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
2549        self.list.measure(wm)
2550    }
2551
2552    fn measure_list(
2553        &mut self,
2554        wm: &mut WidgetMeasure,
2555        measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
2556        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2557    ) -> PxSize {
2558        self.list.measure_list(wm, measure, fold_size)
2559    }
2560
2561    fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
2562        self.list.layout(wl)
2563    }
2564
2565    fn layout_list(
2566        &mut self,
2567        wl: &mut WidgetLayout,
2568        layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
2569        fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2570    ) -> PxSize {
2571        self.list.layout_list(wl, layout, fold_size)
2572    }
2573
2574    fn render(&mut self, frame: &mut FrameBuilder) {
2575        self.render_list(frame, |_, n, _, frame| n.render(frame));
2576    }
2577
2578    fn render_update(&mut self, update: &mut FrameUpdate) {
2579        self.render_update_list(update, |_, n, _, update| n.render_update(update));
2580    }
2581
2582    fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2583        self.list.0.as_widget()
2584    }
2585}
2586
2587bitflags::bitflags! {
2588    /// Identifies changes in [`PanelListData`] since last layout.
2589    #[must_use = "|= with other item changes, call request_render"]
2590    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
2591    #[serde(transparent)]
2592    pub struct PanelListDataChanges: u8 {
2593        /// The [`PanelListData::child_offset`] changed since last layout.
2594        const CHILD_OFFSET = 0b01;
2595        /// The [`PanelListData::define_reference_frame`] changed since last layout.
2596        const DEFINE_REFERENCE_FRAME = 0b10;
2597    }
2598}
2599impl PanelListDataChanges {
2600    /// Request render or render update if there are any changes.
2601    pub fn request_render(self) {
2602        if self.contains(Self::DEFINE_REFERENCE_FRAME) {
2603            WIDGET.render();
2604        } else if self.contains(Self::CHILD_OFFSET) {
2605            WIDGET.render_update();
2606        }
2607    }
2608}
2609
2610/// Default [`PanelList`] associated data.
2611#[derive(Clone, Debug, Default)]
2612pub struct DefaultPanelListData {
2613    /// Child offset to be used in the default `render_all` and `render_update_all` implementations.
2614    pub child_offset: PxVector,
2615    /// If a new reference frame should be created for the item during render.
2616    pub define_reference_frame: bool,
2617
2618    prev_child_offset: PxVector,
2619    prev_define_reference_frame: bool,
2620}
2621impl PanelListData for DefaultPanelListData {
2622    fn child_offset(&self) -> PxVector {
2623        self.child_offset
2624    }
2625
2626    fn define_reference_frame(&self) -> bool {
2627        self.define_reference_frame
2628    }
2629
2630    fn commit(&mut self) -> PanelListDataChanges {
2631        let mut changes = PanelListDataChanges::empty();
2632        if self.define_reference_frame != self.prev_define_reference_frame {
2633            changes |= PanelListDataChanges::DEFINE_REFERENCE_FRAME;
2634        }
2635        if self.child_offset != self.prev_child_offset {
2636            changes |= PanelListDataChanges::CHILD_OFFSET;
2637        }
2638        self.prev_define_reference_frame = self.define_reference_frame;
2639        self.prev_child_offset = self.child_offset;
2640        changes
2641    }
2642}
2643
2644/// Represents an item's associated data in a [`PanelList`].
2645pub trait PanelListData: Default + Send + Any {
2646    /// Gets the child offset to be used in the default `render_all` and `render_update_all` implementations.
2647    fn child_offset(&self) -> PxVector;
2648
2649    /// If a new reference frame should be created for the item during render.
2650    fn define_reference_frame(&self) -> bool;
2651
2652    /// Commit `child_offset` and `define_reference_frame` changes.
2653    ///
2654    /// Returns flags that indicate what values changed.
2655    fn commit(&mut self) -> PanelListDataChanges;
2656}
2657impl PanelListData for () {
2658    fn child_offset(&self) -> PxVector {
2659        PxVector::zero()
2660    }
2661
2662    fn define_reference_frame(&self) -> bool {
2663        false
2664    }
2665
2666    fn commit(&mut self) -> PanelListDataChanges {
2667        PanelListDataChanges::empty()
2668    }
2669}
2670
2671struct PanelObserver<'d, D>
2672where
2673    D: PanelListData,
2674{
2675    changed: bool,
2676    data: &'d mut Vec<Mutex<D>>,
2677    observer: &'d mut dyn UiNodeListObserver,
2678}
2679impl<D> UiNodeListObserver for PanelObserver<'_, D>
2680where
2681    D: PanelListData,
2682{
2683    fn is_reset_only(&self) -> bool {
2684        false
2685    }
2686
2687    fn reset(&mut self) {
2688        self.changed = true;
2689        self.data.clear();
2690        self.observer.reset();
2691    }
2692
2693    fn inserted(&mut self, index: usize) {
2694        self.changed = true;
2695        self.data.insert(index, Default::default());
2696        self.observer.inserted(index);
2697    }
2698
2699    fn removed(&mut self, index: usize) {
2700        self.changed = true;
2701        self.data.remove(index);
2702        self.observer.removed(index);
2703    }
2704
2705    fn moved(&mut self, removed_index: usize, inserted_index: usize) {
2706        self.changed = true;
2707        let item = self.data.remove(removed_index);
2708        self.data.insert(inserted_index, item);
2709        self.observer.moved(removed_index, inserted_index);
2710    }
2711}