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