Skip to main content

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