zng_app/widget/info/
iter.rs

1//! Widget info tree iterators.
2use std::iter::FusedIterator;
3
4use zng_var::impl_from_and_into_var;
5
6use super::*;
7
8/// Widget tree filter selected for a widget in the tree.
9///
10/// This `enum` is used by the [`TreeIterator::tree_filter`] method.
11#[derive(Clone, Debug, Copy, PartialEq, Eq)]
12pub enum TreeFilter {
13    /// Include the descendant and continue filtering its descendants.
14    Include,
15    /// Skip the descendant but continue filtering its descendants.
16    Skip,
17    /// Skip the descendant and its descendants.
18    SkipAll,
19    /// Include the descendant but skips its descendants.
20    SkipDescendants,
21}
22impl_from_and_into_var! {
23    /// Returns [`Include`] for `true` and [`Skip`] for `false`.
24    ///
25    /// [`Include`]: TreeFilter::Include
26    /// [`Skip`]: TreeFilter::Skip
27    fn from(include: bool) -> TreeFilter {
28        if include { TreeFilter::Include } else { TreeFilter::Skip }
29    }
30}
31
32/// Iterator over all children of a widget.
33///
34/// This `struct` is created by the [`children`] and [`self_and_children`] methods in [`WidgetInfo`].
35///
36/// [`children`]: WidgetInfo::children
37/// [`self_and_children`]: WidgetInfo::self_and_children
38#[derive(Debug)]
39pub struct Children {
40    front_enter: bool,
41    front: Option<WidgetInfo>,
42
43    back_enter: bool,
44    back: Option<WidgetInfo>,
45}
46impl Children {
47    pub(super) fn new(parent: WidgetInfo) -> Self {
48        Self {
49            front_enter: true,
50            front: Some(parent.clone()),
51
52            back_enter: true,
53            back: Some(parent),
54        }
55    }
56
57    /// New empty iterator.
58    pub fn empty() -> Self {
59        Self {
60            front_enter: false,
61            front: None,
62            back_enter: false,
63            back: None,
64        }
65    }
66
67    /// New with a children selection.
68    pub fn new_range(front: WidgetInfo, back: WidgetInfo) -> Self {
69        assert_eq!(
70            front.node().parent().unwrap().id(),
71            back.node().parent().unwrap().id(),
72            "front and back not siblings"
73        );
74        Self {
75            front_enter: false,
76            front: Some(front),
77            back_enter: false,
78            back: Some(back),
79        }
80    }
81}
82impl Iterator for Children {
83    type Item = WidgetInfo;
84
85    fn next(&mut self) -> Option<Self::Item> {
86        if mem::take(&mut self.front_enter) {
87            let next = self.front.take().unwrap();
88            self.front = next.first_child();
89            Some(next)
90        } else if self.front == self.back {
91            let next = self.front.take();
92            self.back = None;
93            next
94        } else if let Some(next) = self.front.take() {
95            self.front = next.next_sibling();
96            Some(next)
97        } else {
98            None
99        }
100    }
101}
102impl DoubleEndedIterator for Children {
103    fn next_back(&mut self) -> Option<Self::Item> {
104        if mem::take(&mut self.back_enter) {
105            let next = self.back.take().unwrap();
106            self.back = next.last_child();
107            Some(next)
108        } else if self.front == self.back {
109            let next = self.back.take();
110            self.front = None;
111            next
112        } else if let Some(next) = self.back.take() {
113            self.back = next.prev_sibling();
114            Some(next)
115        } else {
116            None
117        }
118    }
119}
120
121/// Iterator over all next siblings of a widget.
122///
123/// This `struct` is created by the [`prev_siblings`] and [`self_and_prev_siblings`] methods in [`WidgetInfo`].
124///
125/// [`prev_siblings`]: WidgetInfo::prev_siblings
126/// [`self_and_prev_siblings`]: WidgetInfo::self_and_prev_siblings
127pub struct PrevSiblings {
128    node: Option<WidgetInfo>,
129}
130impl PrevSiblings {
131    pub(super) fn new(node: WidgetInfo) -> Self {
132        Self { node: Some(node) }
133    }
134}
135impl Iterator for PrevSiblings {
136    type Item = WidgetInfo;
137
138    fn next(&mut self) -> Option<Self::Item> {
139        if let Some(n) = self.node.take() {
140            self.node = n.prev_sibling();
141            Some(n)
142        } else {
143            None
144        }
145    }
146}
147
148/// Iterator over all next siblings of a widget.
149///
150/// This `struct` is created by the [`next_siblings`] and [`self_and_next_siblings`] methods in [`WidgetInfo`].
151///
152/// [`next_siblings`]: WidgetInfo::next_siblings
153/// [`self_and_next_siblings`]: WidgetInfo::self_and_next_siblings
154pub struct NextSiblings {
155    node: Option<WidgetInfo>,
156}
157impl NextSiblings {
158    pub(super) fn new(node: WidgetInfo) -> Self {
159        Self { node: Some(node) }
160    }
161}
162impl Iterator for NextSiblings {
163    type Item = WidgetInfo;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        if let Some(n) = self.node.take() {
167            self.node = n.next_sibling();
168            Some(n)
169        } else {
170            None
171        }
172    }
173}
174
175/// Iterator over all ancestors of a widget.
176///
177/// This `struct` is created by the [`ancestors`] and [`self_and_ancestors`] methods in [`WidgetInfo`].
178///
179/// [`ancestors`]: WidgetInfo::ancestors
180/// [`self_and_ancestors`]: WidgetInfo::self_and_ancestors
181pub struct Ancestors {
182    node: Option<WidgetInfo>,
183}
184impl Ancestors {
185    pub(super) fn new(node: WidgetInfo) -> Self {
186        Ancestors { node: Some(node) }
187    }
188}
189impl Iterator for Ancestors {
190    type Item = WidgetInfo;
191
192    fn next(&mut self) -> Option<Self::Item> {
193        if let Some(n) = self.node.take() {
194            self.node = n.parent();
195            Some(n)
196        } else {
197            None
198        }
199    }
200}
201
202mod internal {
203    pub trait InternalTreeIterator {
204        fn skip_all(&mut self, widget: &super::WidgetInfo);
205    }
206}
207
208/// Iterator that traverses the branches of a widget tree.
209pub trait TreeIterator: internal::InternalTreeIterator + Iterator<Item = WidgetInfo> + FusedIterator {
210    /// Creates an iterator which uses a closure to filter items or branches at a time.
211    ///
212    /// See [`TreeFilter`] for details.
213    fn tree_filter<F>(self, filter: F) -> TreeFilterIter<Self, F>
214    where
215        Self: Sized,
216        F: FnMut(&WidgetInfo) -> TreeFilter,
217    {
218        TreeFilterIter { iter: self, filter }
219    }
220
221    /// Gets the first item not filtered out by a [`TreeFilter`] closure.
222    fn tree_find<F>(self, filter: F) -> Option<WidgetInfo>
223    where
224        Self: Sized,
225        F: FnMut(&WidgetInfo) -> TreeFilter,
226    {
227        self.tree_filter(filter).next()
228    }
229
230    /// Check if any item is not filtered out by a [`TreeFilter`] closure.
231    fn tree_any<F>(self, filter: F) -> bool
232    where
233        Self: Sized,
234        F: FnMut(&WidgetInfo) -> TreeFilter,
235    {
236        self.tree_find(filter).is_some()
237    }
238}
239
240/// Primary implementer of [`TreeIterator`].
241pub struct TreeIter {
242    tree: WidgetInfoTree,
243    iter: tree::TreeIter,
244}
245impl TreeIter {
246    pub(super) fn self_and_descendants(wgt: WidgetInfo) -> Self {
247        Self {
248            tree: wgt.tree().clone(),
249            iter: wgt.node().self_and_descendants(),
250        }
251    }
252
253    pub(super) fn self_and_prev_siblings_in(wgt: WidgetInfo, ancestor: WidgetInfo) -> RevTreeIter {
254        let tree = &wgt.tree.0.tree;
255        let mut iter = ancestor.node().self_and_descendants().rev(tree);
256        iter.skip_to(tree, wgt.node_id);
257
258        RevTreeIter { tree: wgt.tree, iter }
259    }
260    pub(super) fn prev_siblings_in(wgt: WidgetInfo, ancestor: WidgetInfo) -> RevTreeIter {
261        if let Some(wgt) = wgt.prev_sibling() {
262            return Self::self_and_prev_siblings_in(wgt, ancestor);
263        } else if let Some(parent) = wgt.parent()
264            && parent != ancestor
265            && wgt.tree == ancestor.tree
266        {
267            return Self::prev_siblings_in(parent, ancestor);
268        }
269        RevTreeIter {
270            tree: wgt.tree,
271            iter: tree::RevTreeIter::empty(),
272        }
273    }
274
275    pub(super) fn self_and_next_siblings_in(wgt: WidgetInfo, ancestor: WidgetInfo) -> Self {
276        if wgt.tree != ancestor.tree {
277            return TreeIter {
278                tree: wgt.tree,
279                iter: tree::TreeIter::empty(),
280            };
281        }
282
283        let mut iter = ancestor.node().self_and_descendants();
284        iter.skip_to(wgt.node_id);
285        Self {
286            tree: wgt.tree().clone(),
287            iter,
288        }
289    }
290    pub(super) fn next_siblings_in(wgt: WidgetInfo, ancestor: WidgetInfo) -> Self {
291        if let Some(wgt) = wgt.next_sibling() {
292            return Self::self_and_next_siblings_in(wgt, ancestor);
293        } else if let Some(parent) = wgt.parent()
294            && parent != ancestor
295            && wgt.tree == ancestor.tree
296        {
297            return Self::next_siblings_in(parent, ancestor);
298        }
299        TreeIter {
300            tree: wgt.tree,
301            iter: tree::TreeIter::empty(),
302        }
303    }
304
305    /// Creates a reverse tree iterator.
306    ///
307    /// Yields widgets in the `parent -> last_child -> prev_sibling` order. The reverse iterator is pre-advanced by the same count
308    /// of widgets already yielded by this iterator. In practice this is best used immediately after getting the iterator from
309    /// [`self_and_descendants`] or [`descendants`], with the intention of skipping to the last child from the starting widget.
310    ///
311    /// [`self_and_descendants`]: WidgetInfo::self_and_descendants
312    /// [`descendants`]: WidgetInfo::descendants
313    pub fn tree_rev(self) -> RevTreeIter
314    where
315        Self: Sized,
316    {
317        RevTreeIter {
318            iter: self.iter.rev(&self.tree.0.tree),
319            tree: self.tree,
320        }
321    }
322}
323impl internal::InternalTreeIterator for TreeIter {
324    fn skip_all(&mut self, widget: &WidgetInfo) {
325        self.iter.close(&self.tree.0.tree, widget.node_id)
326    }
327}
328impl Iterator for TreeIter {
329    type Item = WidgetInfo;
330
331    fn next(&mut self) -> Option<Self::Item> {
332        self.iter.next().map(|id| WidgetInfo::new(self.tree.clone(), id))
333    }
334
335    fn size_hint(&self) -> (usize, Option<usize>) {
336        let len = self.iter.len();
337        (len, Some(len))
338    }
339}
340impl ExactSizeIterator for TreeIter {
341    fn len(&self) -> usize {
342        self.iter.len()
343    }
344}
345impl FusedIterator for TreeIter {}
346impl TreeIterator for TreeIter {}
347
348/// Reversing tree iterator.
349///
350/// This struct is created by the [`TreeIter::tree_rev`] method.
351pub struct RevTreeIter {
352    tree: WidgetInfoTree,
353    iter: tree::RevTreeIter,
354}
355impl internal::InternalTreeIterator for RevTreeIter {
356    fn skip_all(&mut self, widget: &WidgetInfo) {
357        self.iter.close(&self.tree.0.tree, widget.node_id);
358    }
359}
360impl Iterator for RevTreeIter {
361    type Item = WidgetInfo;
362
363    fn next(&mut self) -> Option<Self::Item> {
364        self.iter.next(&self.tree.0.tree).map(|id| WidgetInfo::new(self.tree.clone(), id))
365    }
366}
367impl FusedIterator for RevTreeIter {}
368impl TreeIterator for RevTreeIter {}
369
370/// Filtering tree iterator.
371///
372/// This struct is created by the [`TreeIterator::tree_filter`] method.
373pub struct TreeFilterIter<I, F>
374where
375    I: TreeIterator,
376    F: FnMut(&WidgetInfo) -> TreeFilter,
377{
378    iter: I,
379    filter: F,
380}
381impl<I, F> internal::InternalTreeIterator for TreeFilterIter<I, F>
382where
383    I: TreeIterator,
384    F: FnMut(&WidgetInfo) -> TreeFilter,
385{
386    fn skip_all(&mut self, widget: &WidgetInfo) {
387        self.iter.skip_all(widget)
388    }
389}
390impl<I, F> Iterator for TreeFilterIter<I, F>
391where
392    I: TreeIterator,
393    F: FnMut(&WidgetInfo) -> TreeFilter,
394{
395    type Item = WidgetInfo;
396
397    fn next(&mut self) -> Option<Self::Item> {
398        loop {
399            match self.iter.next() {
400                Some(wgt) => match (self.filter)(&wgt) {
401                    TreeFilter::Include => return Some(wgt),
402                    TreeFilter::Skip => continue,
403                    TreeFilter::SkipAll => {
404                        self.iter.skip_all(&wgt);
405                        continue;
406                    }
407                    TreeFilter::SkipDescendants => {
408                        self.iter.skip_all(&wgt);
409                        return Some(wgt);
410                    }
411                },
412                None => return None,
413            }
414        }
415    }
416}
417impl<I, F> FusedIterator for TreeFilterIter<I, F>
418where
419    I: TreeIterator,
420    F: FnMut(&WidgetInfo) -> TreeFilter,
421{
422}
423impl<I, F> TreeIterator for TreeFilterIter<I, F>
424where
425    I: TreeIterator,
426    F: FnMut(&WidgetInfo) -> TreeFilter,
427{
428}
429
430#[cfg(test)]
431mod tests {
432    use std::sync::Arc;
433
434    use zng_layout::unit::FactorUnits;
435
436    use crate::{
437        APP,
438        widget::{
439            WIDGET, WidgetCtx, WidgetId, WidgetUpdateMode,
440            info::{
441                TreeFilter, WidgetBorderInfo, WidgetBoundsInfo, WidgetInfo, WidgetInfoBuilder, WidgetInfoTree, access::AccessEnabled,
442                iter::TreeIterator,
443            },
444        },
445        window::{WINDOW, WindowId},
446    };
447
448    trait WidgetInfoBuilderExt {
449        fn push_test_widget<F>(&mut self, name: &'static str, inner: F)
450        where
451            F: FnMut(&mut Self);
452    }
453    impl WidgetInfoBuilderExt for WidgetInfoBuilder {
454        fn push_test_widget<F>(&mut self, name: &'static str, inner: F)
455        where
456            F: FnMut(&mut Self),
457        {
458            WINDOW.with_test_context(WidgetUpdateMode::Ignore, || {
459                WIDGET.with_context(&mut WidgetCtx::new(WidgetId::named(name)), WidgetUpdateMode::Ignore, || {
460                    self.push_widget(inner)
461                });
462            });
463        }
464    }
465
466    trait WidgetInfoExt {
467        fn test_name(self) -> &'static str;
468    }
469    impl WidgetInfoExt for WidgetInfo {
470        fn test_name(self) -> &'static str {
471            self.id().name().as_static_str().expect("use with `push_test_widget` only")
472        }
473    }
474
475    fn data() -> WidgetInfoTree {
476        let _scope = APP.minimal();
477        let mut builder = WidgetInfoBuilder::new(
478            Arc::default(),
479            WindowId::named("w"),
480            AccessEnabled::empty(),
481            WidgetId::named("w"),
482            WidgetBoundsInfo::new(),
483            WidgetBorderInfo::new(),
484            1.fct(),
485        );
486        builder.push_test_widget("c-0", |_| {});
487        builder.push_test_widget("c-1", |_| {});
488        builder.push_test_widget("c-2", |_| {});
489        builder.finalize(None, false)
490    }
491
492    #[test]
493    fn descendants() {
494        let tree = data();
495
496        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
497
498        assert_eq!(result, vec!["c-0", "c-1", "c-2"]);
499    }
500
501    #[test]
502    fn descendants_filter_noop() {
503        let tree = data();
504
505        let result: Vec<_> = tree
506            .root()
507            .descendants()
508            .tree_filter(|_| TreeFilter::Include)
509            .map(|w| w.test_name())
510            .collect();
511
512        assert_eq!(result, vec!["c-0", "c-1", "c-2"]);
513    }
514
515    #[test]
516    fn descendants_rev() {
517        let tree = data();
518
519        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
520
521        assert_eq!(result, vec!["c-2", "c-1", "c-0"]);
522    }
523
524    #[test]
525    fn descendants_filter_noop_rev() {
526        let tree = data();
527
528        let result: Vec<_> = tree
529            .root()
530            .descendants()
531            .tree_rev()
532            .tree_filter(|_| TreeFilter::Include)
533            .map(|w| w.test_name())
534            .collect();
535
536        assert_eq!(result, vec!["c-2", "c-1", "c-0"]);
537    }
538
539    #[test]
540    fn self_and_descendants() {
541        let tree = data();
542
543        let result: Vec<_> = tree.root().self_and_descendants().map(|w| w.test_name()).collect();
544
545        assert_eq!(result, vec!["w", "c-0", "c-1", "c-2"]);
546    }
547
548    #[test]
549    fn self_and_descendants_filter_noop() {
550        let tree = data();
551
552        let result: Vec<_> = tree
553            .root()
554            .self_and_descendants()
555            .tree_filter(|_| TreeFilter::Include)
556            .map(|w| w.test_name())
557            .collect();
558
559        assert_eq!(result, vec!["w", "c-0", "c-1", "c-2"]);
560    }
561
562    #[test]
563    fn self_and_descendants_rev() {
564        let tree = data();
565
566        let result: Vec<_> = tree.root().self_and_descendants().tree_rev().map(|w| w.test_name()).collect();
567
568        assert_eq!(result, vec!["w", "c-2", "c-1", "c-0",]);
569    }
570
571    #[test]
572    fn self_and_descendants_filter_noop_rev() {
573        let tree = data();
574
575        let result: Vec<_> = tree
576            .root()
577            .self_and_descendants()
578            .tree_rev()
579            .tree_filter(|_| TreeFilter::Include)
580            .map(|w| w.test_name())
581            .collect();
582
583        assert_eq!(result, vec!["w", "c-2", "c-1", "c-0",]);
584    }
585
586    #[test]
587    fn descendants_double() {
588        let tree = data();
589        let mut iter = tree.root().descendants();
590
591        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
592
593        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
594
595        assert_eq!(result, vec!["c-1", "c-0"]);
596    }
597
598    #[test]
599    fn descendants_double_filter_noop() {
600        let tree = data();
601        let mut iter = tree.root().descendants().tree_rev().tree_filter(|_| TreeFilter::Include);
602
603        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-2"));
604
605        let result: Vec<_> = iter.map(|w| w.test_name()).collect();
606
607        assert_eq!(result, vec!["c-1", "c-0"]);
608    }
609
610    fn data_nested() -> WidgetInfoTree {
611        let _scope = APP.minimal();
612        let mut builder = WidgetInfoBuilder::new(
613            Arc::default(),
614            WindowId::named("w"),
615            AccessEnabled::empty(),
616            WidgetId::named("w"),
617            WidgetBoundsInfo::new(),
618            WidgetBorderInfo::new(),
619            1.fct(),
620        );
621        builder.push_test_widget("c-0", |builder| {
622            builder.push_test_widget("c-0-0", |_| {});
623            builder.push_test_widget("c-0-1", |_| {});
624            builder.push_test_widget("c-0-2", |_| {});
625        });
626        builder.push_test_widget("c-1", |builder| {
627            builder.push_test_widget("c-1-0", |_| {});
628            builder.push_test_widget("c-1-1", |builder| {
629                builder.push_test_widget("c-1-1-0", |_| {});
630                builder.push_test_widget("c-1-1-1", |_| {});
631            });
632        });
633        builder.push_test_widget("c-2", |builder| {
634            builder.push_test_widget("c-2-0", |_| {});
635            builder.push_test_widget("c-2-1", |_| {});
636            builder.push_test_widget("c-2-2", |builder| {
637                builder.push_test_widget("c-2-2-0", |_| {});
638            });
639        });
640        builder.finalize(None, false)
641    }
642
643    #[test]
644    fn descendants_nested() {
645        let tree = data_nested();
646
647        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
648
649        assert_eq!(
650            result,
651            vec![
652                "c-0", "c-0-0", "c-0-1", "c-0-2", "c-1", "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", "c-2", "c-2-0", "c-2-1", "c-2-2",
653                "c-2-2-0",
654            ]
655        );
656    }
657
658    #[test]
659    fn descendants_nested_rev() {
660        let tree = data_nested();
661
662        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
663
664        assert_eq!(
665            result,
666            vec![
667                "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", "c-1", "c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", "c-0", "c-0-2", "c-0-1",
668                "c-0-0",
669            ]
670        );
671    }
672
673    #[test]
674    fn self_and_descendants_nested() {
675        let tree = data_nested();
676
677        let result: Vec<_> = tree.root().self_and_descendants().map(|w| w.test_name()).collect();
678
679        assert_eq!(
680            result,
681            vec![
682                "w", "c-0", "c-0-0", "c-0-1", "c-0-2", "c-1", "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", "c-2", "c-2-0", "c-2-1", "c-2-2",
683                "c-2-2-0",
684            ]
685        );
686    }
687
688    #[test]
689    fn self_and_descendants_nested_rev() {
690        let tree = data_nested();
691
692        let result: Vec<_> = tree.root().self_and_descendants().tree_rev().map(|w| w.test_name()).collect();
693        assert_eq!(
694            result,
695            vec![
696                "w", "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", "c-1", "c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", "c-0", "c-0-2", "c-0-1",
697                "c-0-0",
698            ]
699        );
700    }
701
702    #[test]
703    fn descendants_double_nested_entering_ok() {
704        let tree = data_nested();
705        let mut iter = tree.root().descendants();
706
707        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
708
709        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
710
711        assert_eq!(
712            result,
713            vec![
714                "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", "c-1", "c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", "c-0", "c-0-2", "c-0-1", "c-0-0",
715            ]
716        );
717    }
718
719    #[test]
720    fn descendants_double_nested() {
721        let tree = data_nested();
722        let mut iter = tree.root().descendants();
723
724        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
725        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0-0"));
726
727        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
728
729        assert_eq!(
730            result,
731            vec![
732                "c-2-2-0", "c-2-1", "c-2-0", "c-1", "c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", "c-0", "c-0-2", "c-0-1", "c-0-0"
733            ]
734        );
735    }
736
737    fn data_deep() -> WidgetInfoTree {
738        let _scope = APP.minimal();
739        let mut builder = WidgetInfoBuilder::new(
740            Arc::default(),
741            WindowId::named("w"),
742            AccessEnabled::empty(),
743            WidgetId::named("w"),
744            WidgetBoundsInfo::new(),
745            WidgetBorderInfo::new(),
746            1.fct(),
747        );
748        builder.push_test_widget("d-0", |builder| {
749            builder.push_test_widget("d-1", |builder| {
750                builder.push_test_widget("d-2", |builder| {
751                    builder.push_test_widget("d-3", |builder| {
752                        builder.push_test_widget("d-4", |builder| {
753                            builder.push_test_widget("d-5", |_| {});
754                        });
755                    });
756                });
757            });
758        });
759        builder.finalize(None, false)
760    }
761
762    #[test]
763    fn descendants_deep() {
764        let tree = data_deep();
765        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
766
767        assert_eq!(result, vec!["d-0", "d-1", "d-2", "d-3", "d-4", "d-5"])
768    }
769
770    #[test]
771    fn descendants_deep_rev() {
772        let tree = data_deep();
773        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
774
775        assert_eq!(result, vec!["d-0", "d-1", "d-2", "d-3", "d-4", "d-5"])
776    }
777
778    #[test]
779    fn descendants_deep_double() {
780        let tree = data_deep();
781
782        let mut iter = tree.root().descendants().tree_rev().map(|w| w.test_name());
783        iter.next();
784
785        let result: Vec<_> = iter.collect();
786
787        assert_eq!(result, vec!["d-1", "d-2", "d-3", "d-4", "d-5"])
788    }
789
790    #[test]
791    fn descendants_filter_include() {
792        let tree = data_nested();
793
794        let result: Vec<_> = tree
795            .root()
796            .descendants()
797            .tree_filter(|_| TreeFilter::Include)
798            .map(|w| w.test_name())
799            .collect();
800
801        assert_eq!(
802            result,
803            vec![
804                "c-0", "c-0-0", "c-0-1", "c-0-2", "c-1", "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", "c-2", "c-2-0", "c-2-1", "c-2-2",
805                "c-2-2-0",
806            ]
807        );
808    }
809
810    #[test]
811    fn descendants_filter_skip() {
812        let tree = data_nested();
813
814        let result: Vec<_> = tree
815            .root()
816            .descendants()
817            .tree_filter(|w| {
818                if w.id() == WidgetId::named("c-1") {
819                    TreeFilter::Skip
820                } else {
821                    TreeFilter::Include
822                }
823            })
824            .map(|w| w.test_name())
825            .collect();
826
827        assert_eq!(
828            result,
829            vec![
830                "c-0", "c-0-0", "c-0-1", "c-0-2", /* "c-1", */
831                "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", "c-2", "c-2-0", "c-2-1", "c-2-2", "c-2-2-0",
832            ]
833        );
834    }
835
836    #[test]
837    fn descendants_filter_skip_rev() {
838        let tree = data_nested();
839
840        let result: Vec<_> = tree
841            .root()
842            .descendants()
843            .tree_rev()
844            .tree_filter(|w| {
845                if w.id() == WidgetId::named("c-1") {
846                    TreeFilter::Skip
847                } else {
848                    TreeFilter::Include
849                }
850            })
851            .map(|w| w.test_name())
852            .collect();
853
854        assert_eq!(
855            result,
856            vec![
857                "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", /* "c-1", */
858                "c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", "c-0", "c-0-2", "c-0-1", "c-0-0",
859            ]
860        );
861    }
862
863    #[test]
864    fn descendants_filter_skip_all() {
865        let tree = data_nested();
866
867        let result: Vec<_> = tree
868            .root()
869            .descendants()
870            .tree_filter(|w| {
871                if w.id() == WidgetId::named("c-1") {
872                    TreeFilter::SkipAll
873                } else {
874                    TreeFilter::Include
875                }
876            })
877            .map(|w| w.test_name())
878            .collect();
879
880        assert_eq!(
881            result,
882            vec![
883                "c-0", "c-0-0", "c-0-1", "c-0-2", /* "c-1", "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", */
884                "c-2", "c-2-0", "c-2-1", "c-2-2", "c-2-2-0",
885            ]
886        );
887    }
888
889    #[test]
890    fn descendants_filter_skip_all_rev() {
891        let tree = data_nested();
892
893        let result: Vec<_> = tree
894            .root()
895            .descendants()
896            .tree_rev()
897            .tree_filter(|w| {
898                if w.id() == WidgetId::named("c-1") {
899                    TreeFilter::SkipAll
900                } else {
901                    TreeFilter::Include
902                }
903            })
904            .map(|w| w.test_name())
905            .collect();
906
907        assert_eq!(
908            result,
909            vec![
910                "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", /* "c-1, c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", */ "c-0", "c-0-2",
911                "c-0-1", "c-0-0",
912            ]
913        );
914    }
915
916    #[test]
917    fn descendants_filter_skip_desc() {
918        let tree = data_nested();
919
920        let result: Vec<_> = tree
921            .root()
922            .descendants()
923            .tree_filter(|w| {
924                if w.id() == WidgetId::named("c-1") {
925                    TreeFilter::SkipDescendants
926                } else {
927                    TreeFilter::Include
928                }
929            })
930            .map(|w| w.test_name())
931            .collect();
932
933        assert_eq!(
934            result,
935            vec![
936                "c-0", "c-0-0", "c-0-1", "c-0-2", "c-1", /* "c-1-0", "c-1-1", "c-1-1-0", "c-1-1-1", */
937                "c-2", "c-2-0", "c-2-1", "c-2-2", "c-2-2-0",
938            ]
939        );
940    }
941
942    #[test]
943    fn descendants_filter_skip_desc_rev() {
944        let tree = data_nested();
945
946        let result: Vec<_> = tree
947            .root()
948            .descendants()
949            .tree_rev()
950            .tree_filter(|w| {
951                if w.id() == WidgetId::named("c-1") {
952                    TreeFilter::SkipDescendants
953                } else {
954                    TreeFilter::Include
955                }
956            })
957            .map(|w| w.test_name())
958            .collect();
959
960        assert_eq!(
961            result,
962            vec![
963                "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", "c-1", /* c-1-1", "c-1-1-1", "c-1-1-0", "c-1-0", */ "c-0", "c-0-2",
964                "c-0-1", "c-0-0",
965            ]
966        );
967    }
968
969    #[test]
970    fn self_and_next_siblings_in() {
971        let tree = data_nested();
972
973        let root = tree.get("c-1").unwrap();
974        let item = tree.get("c-1-1").unwrap();
975
976        let result: Vec<_> = item.self_and_next_siblings_in(&root).map(|w| w.test_name()).collect();
977        let expected: Vec<_> = root
978            .descendants()
979            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
980            .map(|w| w.test_name())
981            .collect();
982
983        assert_eq!(result, expected);
984    }
985
986    #[test]
987    fn self_and_prev_siblings_in_problem_case() {
988        let tree = data_nested();
989
990        let root = tree.get("c-1").unwrap();
991        let item = tree.get("c-1-1").unwrap();
992
993        let result: Vec<_> = item.self_and_prev_siblings_in(&root).map(|w| w.test_name()).collect();
994        let expected: Vec<_> = root
995            .descendants()
996            .tree_rev()
997            // .skip_while(|w| w.widget_id() != WidgetId::named("c-1-1"))
998            .map(|w| w.test_name())
999            .collect();
1000
1001        assert_eq!(result, expected);
1002    }
1003
1004    #[test]
1005    fn self_and_next_siblings_in_root() {
1006        let tree = data_nested();
1007
1008        let root = tree.root();
1009        let item = tree.get("c-1-1").unwrap();
1010
1011        let result: Vec<_> = item.self_and_next_siblings_in(&root).map(|w| w.test_name()).collect();
1012        let expected: Vec<_> = root
1013            .descendants()
1014            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
1015            .map(|w| w.test_name())
1016            .collect();
1017
1018        assert_eq!(result, expected);
1019    }
1020
1021    #[test]
1022    fn self_and_prev_siblings_in_root() {
1023        let tree = data_nested();
1024
1025        let root = tree.root();
1026        let item = tree.get("c-1-1").unwrap();
1027
1028        let result: Vec<_> = item.self_and_prev_siblings_in(&root).map(|w| w.test_name()).collect();
1029        let expected: Vec<_> = root
1030            .descendants()
1031            .tree_rev()
1032            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
1033            .map(|w| w.test_name())
1034            .collect();
1035
1036        assert_eq!(result, expected);
1037    }
1038
1039    #[test]
1040    fn next_siblings_in_root() {
1041        let tree = data_nested();
1042
1043        let root = tree.root();
1044        let item = tree.get("c-1-1-0").unwrap();
1045
1046        let result: Vec<_> = item.next_siblings_in(&root).map(|w| w.test_name()).collect();
1047        let expected: Vec<_> = root
1048            .descendants()
1049            .skip_while(|w| w.id() != WidgetId::named("c-1-1-0"))
1050            .skip(1)
1051            .map(|w| w.test_name())
1052            .collect();
1053
1054        assert_eq!(result, expected);
1055    }
1056
1057    #[test]
1058    fn prev_siblings_in_root() {
1059        let tree = data_nested();
1060
1061        let root = tree.root();
1062        let item = tree.get("c-1-1-0").unwrap();
1063
1064        let result: Vec<_> = item.prev_siblings_in(&root).map(|w| w.test_name()).collect();
1065        let expected: Vec<_> = root
1066            .descendants()
1067            .tree_rev()
1068            .skip_while(|w| w.id() != WidgetId::named("c-1-1-0"))
1069            .skip(1)
1070            .map(|w| w.test_name())
1071            .collect();
1072
1073        assert_eq!(result, expected);
1074    }
1075}