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    ///
99    /// Note that this *will* populate expanded nodes from the backend.
100    pub fn expand(&mut self, depth: Option<usize>) -> Result<(), BackendT::Error>
101    where
102        BackendT::Context: Clone,
103    {
104        self.roots.expand(depth, self.context.clone())
105    }
106
107    /// Collapse branch nodes.
108    ///
109    /// If depth is [None] will collapse the entire tree.
110    ///
111    /// If depth is 0 will do nothing.
112    pub fn collapse(&mut self, depth: Option<usize>) {
113        self.roots.collapse(depth);
114    }
115
116    /// Fetch roots and possibly their children from backend.
117    ///
118    /// If depth is [None] will populate the entire tree.
119    ///
120    /// If depth is 1 will only populate the roots.
121    ///
122    /// If depth is 0 will do nothing.
123    ///
124    /// Note that populating a branch node will *not* automatically expand it.
125    pub fn populate(&mut self, mut depth: Option<usize>) -> Result<(), BackendT::Error>
126    where
127        BackendT::Context: Clone,
128    {
129        if depth.is_zero() {
130            return Ok(());
131        }
132
133        self.roots = BackendT::roots(self.context.clone())?;
134
135        depth.decrease();
136        if !depth.is_zero() {
137            for node in &mut self.roots {
138                node.populate(depth, self.context.clone())?;
139            }
140        }
141
142        Ok(())
143    }
144
145    /// Remove all nodes.
146    pub fn clear(&mut self) {
147        self.roots.0.clear();
148    }
149}