Skip to main content

cursive_tree/model/
tree.rs

1use super::{super::backend::*, depth::*, iterator::*, kind::*, list::*, node::*, path::*, representation::*};
2
3use {cursive::*, std::cmp::*};
4
5//
6// TreeModel
7//
8
9/// Tree model.
10pub struct TreeModel<BackendT>
11where
12    BackendT: TreeBackend,
13{
14    /// Roots.
15    pub roots: NodeList<BackendT>,
16
17    /// Context.
18    pub context: BackendT::Context,
19}
20
21impl<BackendT> TreeModel<BackendT>
22where
23    BackendT: TreeBackend,
24{
25    /// Constructor.
26    pub fn new(context: BackendT::Context) -> Self {
27        Self { roots: Default::default(), context }
28    }
29
30    /// Whether we have no nodes.
31    pub fn is_empty(&self) -> bool {
32        self.roots.0.is_empty()
33    }
34
35    /// Iterate nodes in visual order from top to bottom.
36    ///
37    /// When only_expanded is true will skip the children of collapsed branches.
38    pub fn iter(&self, only_expanded: bool) -> NodeIterator<'_, BackendT> {
39        self.roots.iter(only_expanded)
40    }
41
42    /// Get node at path.
43    pub fn at_path(&self, path: NodePath) -> Option<&Node<BackendT>> {
44        self.roots.at_path(path)
45    }
46
47    /// Get node at path.
48    pub fn at_path_mut(&mut self, path: NodePath) -> Option<&mut Node<BackendT>> {
49        self.roots.at_path_mut(path)
50    }
51
52    /// Get node at row.
53    pub fn at_row(&self, row: usize) -> Option<&Node<BackendT>> {
54        let mut iterator = self.iter(true);
55        let mut current_row: usize = 0;
56        while let Some(node) = iterator.next() {
57            let next_row = current_row + node.representation_size.y;
58            if (row >= current_row) && (row < next_row) {
59                return Some(node);
60            }
61            current_row = next_row;
62        }
63        None
64    }
65
66    /// Find path to node.
67    pub fn path(&self, node: &Node<BackendT>) -> Option<NodePath> {
68        let mut path = Default::default();
69        if self.roots.fill_path(&mut path, node) { Some(path) } else { None }
70    }
71
72    /// Full extents for drawing.
73    pub fn extents(&self) -> Vec2 {
74        let mut extents = Vec2::default();
75        let mut iterator = self.iter(true);
76        while let Some(node) = iterator.next() {
77            extents.x = max(extents.x, node.depth * 2 + 2 + node.representation_size.x);
78            extents.y += node.representation_size.y;
79        }
80        extents
81    }
82
83    /// Add a root node.
84    pub fn add_root(&mut self, kind: NodeKind, id: BackendT::ID, representation: Representation) {
85        self.roots.add(0, kind, id, representation);
86    }
87
88    /// Insert a root node.
89    pub fn insert_root(&mut self, index: usize, kind: NodeKind, id: BackendT::ID, representation: Representation) {
90        self.roots.insert(index, 0, kind, id, representation);
91    }
92
93    /// Expand branch nodes.
94    ///
95    /// If depth is [None] will expand the entire tree.
96    ///
97    /// If depth is 0 will do nothing.
98    pub fn expand(&mut self, depth: Option<usize>) -> Result<(), BackendT::Error>
99    where
100        BackendT::Context: Clone,
101    {
102        self.roots.expand(depth, self.context.clone())
103    }
104
105    /// Collapse branch nodes.
106    ///
107    /// If depth is [None] will collapse the entire tree.
108    ///
109    /// If depth is 0 will do nothing.
110    pub fn collapse(&mut self, depth: Option<usize>) {
111        self.roots.collapse(depth);
112    }
113
114    /// Fetch roots and possibly their children from backend.
115    ///
116    /// If depth is [None] will populate the entire tree.
117    ///
118    /// If depth is 1 will only populate the roots.
119    ///
120    /// If depth is 0 will do nothing.
121    ///
122    /// Note that populating a branch node will *not* automatically expand it.
123    pub fn populate(&mut self, mut depth: Option<usize>) -> Result<(), BackendT::Error>
124    where
125        BackendT::Context: Clone,
126    {
127        if depth.is_zero() {
128            return Ok(());
129        }
130
131        self.roots = BackendT::roots(self.context.clone())?;
132
133        depth.decrease();
134        if !depth.is_zero() {
135            for node in &mut self.roots {
136                node.populate(depth, self.context.clone())?;
137            }
138        }
139
140        Ok(())
141    }
142
143    /// Remove all nodes.
144    pub fn clear(&mut self) {
145        self.roots.0.clear();
146    }
147}