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