Skip to main content

cursive_tree/model/
tree.rs

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