Skip to main content

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            let wgt = self.iter.next()?;
400            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        }
413    }
414}
415impl<I, F> FusedIterator for TreeFilterIter<I, F>
416where
417    I: TreeIterator,
418    F: FnMut(&WidgetInfo) -> TreeFilter,
419{
420}
421impl<I, F> TreeIterator for TreeFilterIter<I, F>
422where
423    I: TreeIterator,
424    F: FnMut(&WidgetInfo) -> TreeFilter,
425{
426}
427
428#[cfg(test)]
429mod tests {
430    use std::sync::Arc;
431
432    use zng_layout::unit::FactorUnits;
433
434    use crate::{
435        APP,
436        widget::{
437            WIDGET, WidgetCtx, WidgetId, WidgetUpdateMode,
438            info::{
439                TreeFilter, WidgetBorderInfo, WidgetBoundsInfo, WidgetInfo, WidgetInfoBuilder, WidgetInfoTree, access::AccessEnabled,
440                iter::TreeIterator,
441            },
442        },
443        window::{WINDOW, WindowId},
444    };
445
446    trait WidgetInfoBuilderExt {
447        fn push_test_widget<F>(&mut self, name: &'static str, inner: F)
448        where
449            F: FnMut(&mut Self);
450    }
451    impl WidgetInfoBuilderExt for WidgetInfoBuilder {
452        fn push_test_widget<F>(&mut self, name: &'static str, inner: F)
453        where
454            F: FnMut(&mut Self),
455        {
456            WINDOW.with_test_context(WidgetUpdateMode::Ignore, || {
457                WIDGET.with_context(&mut WidgetCtx::new(WidgetId::named(name)), WidgetUpdateMode::Ignore, || {
458                    self.push_widget(inner)
459                });
460            });
461        }
462    }
463
464    trait WidgetInfoExt {
465        fn test_name(self) -> &'static str;
466    }
467    impl WidgetInfoExt for WidgetInfo {
468        fn test_name(self) -> &'static str {
469            self.id().name().as_static_str().expect("use with `push_test_widget` only")
470        }
471    }
472
473    fn data() -> WidgetInfoTree {
474        let _scope = APP.minimal();
475        let mut builder = WidgetInfoBuilder::new(
476            Arc::default(),
477            WindowId::named("w"),
478            AccessEnabled::empty(),
479            WidgetId::named("w"),
480            WidgetBoundsInfo::new(),
481            WidgetBorderInfo::new(),
482            1.fct(),
483        );
484        builder.push_test_widget("c-0", |_| {});
485        builder.push_test_widget("c-1", |_| {});
486        builder.push_test_widget("c-2", |_| {});
487        builder.finalize(None, false)
488    }
489
490    #[test]
491    fn descendants() {
492        let tree = data();
493
494        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
495
496        assert_eq!(result, vec!["c-0", "c-1", "c-2"]);
497    }
498
499    #[test]
500    fn descendants_filter_noop() {
501        let tree = data();
502
503        let result: Vec<_> = tree
504            .root()
505            .descendants()
506            .tree_filter(|_| TreeFilter::Include)
507            .map(|w| w.test_name())
508            .collect();
509
510        assert_eq!(result, vec!["c-0", "c-1", "c-2"]);
511    }
512
513    #[test]
514    fn descendants_rev() {
515        let tree = data();
516
517        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
518
519        assert_eq!(result, vec!["c-2", "c-1", "c-0"]);
520    }
521
522    #[test]
523    fn descendants_filter_noop_rev() {
524        let tree = data();
525
526        let result: Vec<_> = tree
527            .root()
528            .descendants()
529            .tree_rev()
530            .tree_filter(|_| TreeFilter::Include)
531            .map(|w| w.test_name())
532            .collect();
533
534        assert_eq!(result, vec!["c-2", "c-1", "c-0"]);
535    }
536
537    #[test]
538    fn self_and_descendants() {
539        let tree = data();
540
541        let result: Vec<_> = tree.root().self_and_descendants().map(|w| w.test_name()).collect();
542
543        assert_eq!(result, vec!["w", "c-0", "c-1", "c-2"]);
544    }
545
546    #[test]
547    fn self_and_descendants_filter_noop() {
548        let tree = data();
549
550        let result: Vec<_> = tree
551            .root()
552            .self_and_descendants()
553            .tree_filter(|_| TreeFilter::Include)
554            .map(|w| w.test_name())
555            .collect();
556
557        assert_eq!(result, vec!["w", "c-0", "c-1", "c-2"]);
558    }
559
560    #[test]
561    fn self_and_descendants_rev() {
562        let tree = data();
563
564        let result: Vec<_> = tree.root().self_and_descendants().tree_rev().map(|w| w.test_name()).collect();
565
566        assert_eq!(result, vec!["w", "c-2", "c-1", "c-0",]);
567    }
568
569    #[test]
570    fn self_and_descendants_filter_noop_rev() {
571        let tree = data();
572
573        let result: Vec<_> = tree
574            .root()
575            .self_and_descendants()
576            .tree_rev()
577            .tree_filter(|_| TreeFilter::Include)
578            .map(|w| w.test_name())
579            .collect();
580
581        assert_eq!(result, vec!["w", "c-2", "c-1", "c-0",]);
582    }
583
584    #[test]
585    fn descendants_double() {
586        let tree = data();
587        let mut iter = tree.root().descendants();
588
589        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
590
591        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
592
593        assert_eq!(result, vec!["c-1", "c-0"]);
594    }
595
596    #[test]
597    fn descendants_double_filter_noop() {
598        let tree = data();
599        let mut iter = tree.root().descendants().tree_rev().tree_filter(|_| TreeFilter::Include);
600
601        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-2"));
602
603        let result: Vec<_> = iter.map(|w| w.test_name()).collect();
604
605        assert_eq!(result, vec!["c-1", "c-0"]);
606    }
607
608    fn data_nested() -> WidgetInfoTree {
609        let _scope = APP.minimal();
610        let mut builder = WidgetInfoBuilder::new(
611            Arc::default(),
612            WindowId::named("w"),
613            AccessEnabled::empty(),
614            WidgetId::named("w"),
615            WidgetBoundsInfo::new(),
616            WidgetBorderInfo::new(),
617            1.fct(),
618        );
619        builder.push_test_widget("c-0", |builder| {
620            builder.push_test_widget("c-0-0", |_| {});
621            builder.push_test_widget("c-0-1", |_| {});
622            builder.push_test_widget("c-0-2", |_| {});
623        });
624        builder.push_test_widget("c-1", |builder| {
625            builder.push_test_widget("c-1-0", |_| {});
626            builder.push_test_widget("c-1-1", |builder| {
627                builder.push_test_widget("c-1-1-0", |_| {});
628                builder.push_test_widget("c-1-1-1", |_| {});
629            });
630        });
631        builder.push_test_widget("c-2", |builder| {
632            builder.push_test_widget("c-2-0", |_| {});
633            builder.push_test_widget("c-2-1", |_| {});
634            builder.push_test_widget("c-2-2", |builder| {
635                builder.push_test_widget("c-2-2-0", |_| {});
636            });
637        });
638        builder.finalize(None, false)
639    }
640
641    #[test]
642    fn descendants_nested() {
643        let tree = data_nested();
644
645        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
646
647        assert_eq!(
648            result,
649            vec![
650                "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",
651                "c-2-2-0",
652            ]
653        );
654    }
655
656    #[test]
657    fn descendants_nested_rev() {
658        let tree = data_nested();
659
660        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
661
662        assert_eq!(
663            result,
664            vec![
665                "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",
666                "c-0-0",
667            ]
668        );
669    }
670
671    #[test]
672    fn self_and_descendants_nested() {
673        let tree = data_nested();
674
675        let result: Vec<_> = tree.root().self_and_descendants().map(|w| w.test_name()).collect();
676
677        assert_eq!(
678            result,
679            vec![
680                "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",
681                "c-2-2-0",
682            ]
683        );
684    }
685
686    #[test]
687    fn self_and_descendants_nested_rev() {
688        let tree = data_nested();
689
690        let result: Vec<_> = tree.root().self_and_descendants().tree_rev().map(|w| w.test_name()).collect();
691        assert_eq!(
692            result,
693            vec![
694                "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",
695                "c-0-0",
696            ]
697        );
698    }
699
700    #[test]
701    fn descendants_double_nested_entering_ok() {
702        let tree = data_nested();
703        let mut iter = tree.root().descendants();
704
705        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
706
707        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
708
709        assert_eq!(
710            result,
711            vec![
712                "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",
713            ]
714        );
715    }
716
717    #[test]
718    fn descendants_double_nested() {
719        let tree = data_nested();
720        let mut iter = tree.root().descendants();
721
722        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0"));
723        assert_eq!(iter.next().map(|w| w.test_name()), Some("c-0-0"));
724
725        let result: Vec<_> = iter.tree_rev().map(|w| w.test_name()).collect();
726
727        assert_eq!(
728            result,
729            vec![
730                "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"
731            ]
732        );
733    }
734
735    fn data_deep() -> WidgetInfoTree {
736        let _scope = APP.minimal();
737        let mut builder = WidgetInfoBuilder::new(
738            Arc::default(),
739            WindowId::named("w"),
740            AccessEnabled::empty(),
741            WidgetId::named("w"),
742            WidgetBoundsInfo::new(),
743            WidgetBorderInfo::new(),
744            1.fct(),
745        );
746        builder.push_test_widget("d-0", |builder| {
747            builder.push_test_widget("d-1", |builder| {
748                builder.push_test_widget("d-2", |builder| {
749                    builder.push_test_widget("d-3", |builder| {
750                        builder.push_test_widget("d-4", |builder| {
751                            builder.push_test_widget("d-5", |_| {});
752                        });
753                    });
754                });
755            });
756        });
757        builder.finalize(None, false)
758    }
759
760    #[test]
761    fn descendants_deep() {
762        let tree = data_deep();
763        let result: Vec<_> = tree.root().descendants().map(|w| w.test_name()).collect();
764
765        assert_eq!(result, vec!["d-0", "d-1", "d-2", "d-3", "d-4", "d-5"])
766    }
767
768    #[test]
769    fn descendants_deep_rev() {
770        let tree = data_deep();
771        let result: Vec<_> = tree.root().descendants().tree_rev().map(|w| w.test_name()).collect();
772
773        assert_eq!(result, vec!["d-0", "d-1", "d-2", "d-3", "d-4", "d-5"])
774    }
775
776    #[test]
777    fn descendants_deep_double() {
778        let tree = data_deep();
779
780        let mut iter = tree.root().descendants().tree_rev().map(|w| w.test_name());
781        iter.next();
782
783        let result: Vec<_> = iter.collect();
784
785        assert_eq!(result, vec!["d-1", "d-2", "d-3", "d-4", "d-5"])
786    }
787
788    #[test]
789    fn descendants_filter_include() {
790        let tree = data_nested();
791
792        let result: Vec<_> = tree
793            .root()
794            .descendants()
795            .tree_filter(|_| TreeFilter::Include)
796            .map(|w| w.test_name())
797            .collect();
798
799        assert_eq!(
800            result,
801            vec![
802                "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",
803                "c-2-2-0",
804            ]
805        );
806    }
807
808    #[test]
809    fn descendants_filter_skip() {
810        let tree = data_nested();
811
812        let result: Vec<_> = tree
813            .root()
814            .descendants()
815            .tree_filter(|w| {
816                if w.id() == WidgetId::named("c-1") {
817                    TreeFilter::Skip
818                } else {
819                    TreeFilter::Include
820                }
821            })
822            .map(|w| w.test_name())
823            .collect();
824
825        assert_eq!(
826            result,
827            vec![
828                "c-0", "c-0-0", "c-0-1", "c-0-2", /* "c-1", */
829                "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",
830            ]
831        );
832    }
833
834    #[test]
835    fn descendants_filter_skip_rev() {
836        let tree = data_nested();
837
838        let result: Vec<_> = tree
839            .root()
840            .descendants()
841            .tree_rev()
842            .tree_filter(|w| {
843                if w.id() == WidgetId::named("c-1") {
844                    TreeFilter::Skip
845                } else {
846                    TreeFilter::Include
847                }
848            })
849            .map(|w| w.test_name())
850            .collect();
851
852        assert_eq!(
853            result,
854            vec![
855                "c-2", "c-2-2", "c-2-2-0", "c-2-1", "c-2-0", /* "c-1", */
856                "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",
857            ]
858        );
859    }
860
861    #[test]
862    fn descendants_filter_skip_all() {
863        let tree = data_nested();
864
865        let result: Vec<_> = tree
866            .root()
867            .descendants()
868            .tree_filter(|w| {
869                if w.id() == WidgetId::named("c-1") {
870                    TreeFilter::SkipAll
871                } else {
872                    TreeFilter::Include
873                }
874            })
875            .map(|w| w.test_name())
876            .collect();
877
878        assert_eq!(
879            result,
880            vec![
881                "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", */
882                "c-2", "c-2-0", "c-2-1", "c-2-2", "c-2-2-0",
883            ]
884        );
885    }
886
887    #[test]
888    fn descendants_filter_skip_all_rev() {
889        let tree = data_nested();
890
891        let result: Vec<_> = tree
892            .root()
893            .descendants()
894            .tree_rev()
895            .tree_filter(|w| {
896                if w.id() == WidgetId::named("c-1") {
897                    TreeFilter::SkipAll
898                } else {
899                    TreeFilter::Include
900                }
901            })
902            .map(|w| w.test_name())
903            .collect();
904
905        assert_eq!(
906            result,
907            vec![
908                "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",
909                "c-0-1", "c-0-0",
910            ]
911        );
912    }
913
914    #[test]
915    fn descendants_filter_skip_desc() {
916        let tree = data_nested();
917
918        let result: Vec<_> = tree
919            .root()
920            .descendants()
921            .tree_filter(|w| {
922                if w.id() == WidgetId::named("c-1") {
923                    TreeFilter::SkipDescendants
924                } else {
925                    TreeFilter::Include
926                }
927            })
928            .map(|w| w.test_name())
929            .collect();
930
931        assert_eq!(
932            result,
933            vec![
934                "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", */
935                "c-2", "c-2-0", "c-2-1", "c-2-2", "c-2-2-0",
936            ]
937        );
938    }
939
940    #[test]
941    fn descendants_filter_skip_desc_rev() {
942        let tree = data_nested();
943
944        let result: Vec<_> = tree
945            .root()
946            .descendants()
947            .tree_rev()
948            .tree_filter(|w| {
949                if w.id() == WidgetId::named("c-1") {
950                    TreeFilter::SkipDescendants
951                } else {
952                    TreeFilter::Include
953                }
954            })
955            .map(|w| w.test_name())
956            .collect();
957
958        assert_eq!(
959            result,
960            vec![
961                "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",
962                "c-0-1", "c-0-0",
963            ]
964        );
965    }
966
967    #[test]
968    fn self_and_next_siblings_in() {
969        let tree = data_nested();
970
971        let root = tree.get("c-1").unwrap();
972        let item = tree.get("c-1-1").unwrap();
973
974        let result: Vec<_> = item.self_and_next_siblings_in(&root).map(|w| w.test_name()).collect();
975        let expected: Vec<_> = root
976            .descendants()
977            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
978            .map(|w| w.test_name())
979            .collect();
980
981        assert_eq!(result, expected);
982    }
983
984    #[test]
985    fn self_and_prev_siblings_in_problem_case() {
986        let tree = data_nested();
987
988        let root = tree.get("c-1").unwrap();
989        let item = tree.get("c-1-1").unwrap();
990
991        let result: Vec<_> = item.self_and_prev_siblings_in(&root).map(|w| w.test_name()).collect();
992        let expected: Vec<_> = root
993            .descendants()
994            .tree_rev()
995            // .skip_while(|w| w.widget_id() != WidgetId::named("c-1-1"))
996            .map(|w| w.test_name())
997            .collect();
998
999        assert_eq!(result, expected);
1000    }
1001
1002    #[test]
1003    fn self_and_next_siblings_in_root() {
1004        let tree = data_nested();
1005
1006        let root = tree.root();
1007        let item = tree.get("c-1-1").unwrap();
1008
1009        let result: Vec<_> = item.self_and_next_siblings_in(&root).map(|w| w.test_name()).collect();
1010        let expected: Vec<_> = root
1011            .descendants()
1012            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
1013            .map(|w| w.test_name())
1014            .collect();
1015
1016        assert_eq!(result, expected);
1017    }
1018
1019    #[test]
1020    fn self_and_prev_siblings_in_root() {
1021        let tree = data_nested();
1022
1023        let root = tree.root();
1024        let item = tree.get("c-1-1").unwrap();
1025
1026        let result: Vec<_> = item.self_and_prev_siblings_in(&root).map(|w| w.test_name()).collect();
1027        let expected: Vec<_> = root
1028            .descendants()
1029            .tree_rev()
1030            .skip_while(|w| w.id() != WidgetId::named("c-1-1"))
1031            .map(|w| w.test_name())
1032            .collect();
1033
1034        assert_eq!(result, expected);
1035    }
1036
1037    #[test]
1038    fn next_siblings_in_root() {
1039        let tree = data_nested();
1040
1041        let root = tree.root();
1042        let item = tree.get("c-1-1-0").unwrap();
1043
1044        let result: Vec<_> = item.next_siblings_in(&root).map(|w| w.test_name()).collect();
1045        let expected: Vec<_> = root
1046            .descendants()
1047            .skip_while(|w| w.id() != WidgetId::named("c-1-1-0"))
1048            .skip(1)
1049            .map(|w| w.test_name())
1050            .collect();
1051
1052        assert_eq!(result, expected);
1053    }
1054
1055    #[test]
1056    fn prev_siblings_in_root() {
1057        let tree = data_nested();
1058
1059        let root = tree.root();
1060        let item = tree.get("c-1-1-0").unwrap();
1061
1062        let result: Vec<_> = item.prev_siblings_in(&root).map(|w| w.test_name()).collect();
1063        let expected: Vec<_> = root
1064            .descendants()
1065            .tree_rev()
1066            .skip_while(|w| w.id() != WidgetId::named("c-1-1-0"))
1067            .skip(1)
1068            .map(|w| w.test_name())
1069            .collect();
1070
1071        assert_eq!(result, expected);
1072    }
1073}