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