1use std::iter::FusedIterator;
3
4use zng_var::impl_from_and_into_var;
5
6use super::*;
7
8#[derive(Clone, Debug, Copy, PartialEq, Eq)]
12pub enum TreeFilter {
13 Include,
15 Skip,
17 SkipAll,
19 SkipDescendants,
21}
22impl_from_and_into_var! {
23 fn from(include: bool) -> TreeFilter {
28 if include { TreeFilter::Include } else { TreeFilter::Skip }
29 }
30}
31
32#[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 pub fn empty() -> Self {
59 Self {
60 front_enter: false,
61 front: None,
62 back_enter: false,
63 back: None,
64 }
65 }
66
67 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
121pub 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
148pub 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
175pub 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
208pub trait TreeIterator: internal::InternalTreeIterator + Iterator<Item = WidgetInfo> + FusedIterator {
210 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 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 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
240pub 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 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
348pub 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
370pub 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-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-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-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-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-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-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 .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}