zng_app/widget/node/
list.rs

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