Skip to main content

cursive_tree/model/
iterator.rs

1use super::{list::*, node::*};
2
3use std::marker::*;
4
5//
6// NodeIterator
7//
8
9/// Tree node iterator.
10///
11/// Iterates the nodes in visual order from top to bottom.
12pub struct NodeIterator<'model, BackendT, ContextT, ErrorT, IdT, DataT> {
13    current_node_list: &'model NodeList<BackendT, ContextT, ErrorT, IdT, DataT>,
14    next_index: usize,
15    only_expanded: bool,
16    stack: Vec<(&'model NodeList<BackendT, ContextT, ErrorT, IdT, DataT>, usize)>,
17    error: PhantomData<ErrorT>,
18}
19
20impl<'model, BackendT, ContextT, ErrorT, IdT, DataT> NodeIterator<'model, BackendT, ContextT, ErrorT, IdT, DataT> {
21    /// Constructor.
22    ///
23    /// When only_expanded is true will skip the children of collapsed branches.
24    pub fn new(roots: &'model NodeList<BackendT, ContextT, ErrorT, IdT, DataT>, only_expanded: bool) -> Self {
25        Self {
26            current_node_list: roots,
27            next_index: 0,
28            only_expanded,
29            stack: Default::default(),
30            error: Default::default(),
31        }
32    }
33}
34
35impl<'model, BackendT, ContextT, ErrorT, IdT, DataT> Iterator
36    for NodeIterator<'model, BackendT, ContextT, ErrorT, IdT, DataT>
37where
38    DataT: 'static,
39{
40    type Item = &'model Node<BackendT, ContextT, ErrorT, IdT, DataT>;
41
42    fn next(&mut self) -> Option<Self::Item> {
43        match self.current_node_list.0.get(self.next_index) {
44            Some(node) => {
45                self.next_index += 1;
46
47                if (!self.only_expanded || (node.kind.is_branch() && node.branch_state.is_expanded()))
48                    && let Some(children) = &node.children
49                {
50                    // Remember our place for later
51                    self.stack.push((self.current_node_list, self.next_index));
52
53                    // Continue into children
54                    self.current_node_list = children;
55                    self.next_index = 0;
56                }
57
58                Some(node)
59            }
60
61            None => match self.stack.pop() {
62                Some((current_nodes, next_index)) => {
63                    // Go back to where we were before
64                    self.current_node_list = current_nodes;
65                    self.next_index = next_index;
66                    self.next()
67                }
68
69                None => None,
70            },
71        }
72    }
73}