Skip to main content

cursive_tree/model/
node.rs

1use super::{super::backend::*, depth::*, kind::*, list::*, path::*, representation::*, state::*, symbol::*};
2
3use {
4    cursive::*,
5    std::{borrow::*, marker::*},
6};
7
8//
9// Node
10//
11
12/// Tree node.
13pub struct Node<BackendT>
14where
15    BackendT: TreeBackend,
16{
17    /// Depth.
18    pub depth: usize,
19
20    /// Kind.
21    pub kind: NodeKind,
22
23    /// ID.
24    pub id: BackendT::ID,
25
26    /// Representation.
27    pub representation: Representation,
28
29    /// Representation size.
30    ///
31    /// Cached so we only have to calculate it once.
32    ///
33    /// > Note that nodes can ostensibly have heights >1, i.e. they can be multiline, however this
34    /// is *not* currently supported by [TreeView](super::super::TreeView).
35    pub representation_size: Vec2,
36
37    /// State for [Branch](NodeKind::Branch) node.
38    pub branch_state: BranchState,
39
40    /// Children for [Branch](NodeKind::Branch) node.
41    pub children: Option<NodeList<BackendT>>,
42
43    /// Data.
44    pub data: Option<BackendT::Data>,
45
46    backend: PhantomData<BackendT>,
47}
48
49impl<BackendT> Node<BackendT>
50where
51    BackendT: TreeBackend,
52{
53    /// Constructor.
54    pub fn new(depth: usize, kind: NodeKind, id: BackendT::ID, representation: Representation) -> Self {
55        let representation_size = (representation.width(), 1).into();
56        Self {
57            depth,
58            kind,
59            id,
60            representation,
61            representation_size,
62            branch_state: Default::default(),
63            children: None,
64            data: None,
65            backend: Default::default(),
66        }
67    }
68
69    /// Symbol.
70    ///
71    /// Its char count is always 1.
72    pub fn symbol(&self, context: BackendT::Context) -> Symbol<'_> {
73        BackendT::symbol(self, context)
74    }
75
76    /// Get node at path.
77    pub fn at_path(&self, path: NodePath) -> Option<&Self> {
78        if path.is_empty() { Some(self) } else { self.children.as_ref().and_then(|children| children.at_path(path)) }
79    }
80
81    /// Get node at path.
82    pub fn at_path_mut(&mut self, path: NodePath) -> Option<&mut Self> {
83        if path.is_empty() {
84            Some(self)
85        } else {
86            self.children.as_mut().and_then(|children| children.at_path_mut(path))
87        }
88    }
89
90    /// Fill path to node.
91    ///
92    /// Returns true if found.
93    pub fn fill_path(&self, path: &mut NodePath, node: &Self) -> bool {
94        self.children.as_ref().map(|children| children.fill_path(path, node)).unwrap_or_default()
95    }
96
97    /// Fetch the branch's children from backend.
98    ///
99    /// If depth is [None] will populate all depths.
100    ///
101    /// If depth is 0 or not a [Branch](NodeKind::Branch) will do nothing.
102    ///
103    /// Note that populating a node will *not* automatically expand it.
104    pub fn populate(&mut self, mut depth: Option<usize>, context: BackendT::Context) -> Result<(), BackendT::Error>
105    where
106        BackendT::Context: Clone,
107    {
108        if depth.is_zero() || !self.kind.is_branch() {
109            return Ok(());
110        }
111
112        if self.children.is_none() {
113            BackendT::populate(self, context.clone())?;
114        }
115
116        depth.decrease();
117        if !depth.is_zero()
118            && let Some(children) = &mut self.children
119        {
120            for node in children {
121                node.populate(depth, context.clone())?;
122            }
123        }
124
125        Ok(())
126    }
127
128    /// Add a child node.
129    ///
130    /// Will do nothing if not a [Branch](NodeKind::Branch).
131    pub fn add_child(&mut self, kind: NodeKind, id: BackendT::ID, representation: Representation) {
132        if !self.kind.is_branch() {
133            return;
134        }
135
136        if self.children.is_none() {
137            self.children = Some(Default::default());
138        }
139
140        self.children.as_mut().expect("children").add(self.depth + 1, kind, id, representation);
141    }
142
143    /// Inserts a child node.
144    ///
145    /// Will do nothing if not a [Branch](NodeKind::Branch).
146    pub fn insert_child(&mut self, index: usize, kind: NodeKind, id: BackendT::ID, representation: Representation) {
147        if !self.kind.is_branch() {
148            return;
149        }
150
151        if self.children.is_none() {
152            self.children = Some(Default::default());
153        }
154
155        self.children.as_mut().expect("children").insert(index, self.depth + 1, kind, id, representation);
156    }
157
158    /// Expand the branch.
159    ///
160    /// If depth is [None] will expand all depths.
161    ///
162    /// If depth is 0 or not a [Branch](NodeKind::Branch) will do nothing.
163    ///
164    /// Note that this *will* populate expanded nodes from the backend.
165    pub fn expand(&mut self, mut depth: Option<usize>, context: BackendT::Context) -> Result<(), BackendT::Error>
166    where
167        BackendT::Context: Clone,
168    {
169        if depth.is_zero() || !self.kind.is_branch() {
170            return Ok(());
171        }
172
173        if !self.branch_state.is_expanded() {
174            self.populate(Some(1), context.clone())?;
175            self.branch_state = BranchState::Expanded;
176        }
177
178        depth.decrease();
179        if !depth.is_zero()
180            && let Some(children) = &mut self.children
181        {
182            children.expand(depth, context.clone())?;
183        }
184
185        Ok(())
186    }
187
188    /// Collapse the branch.
189    ///
190    /// If depth is [None] will collapse all depths.
191    ///
192    /// If depth is 0 or not a [Branch](NodeKind::Branch) will do nothing.
193    pub fn collapse(&mut self, mut depth: Option<usize>) {
194        if depth.is_zero() || !self.kind.is_branch() {
195            return;
196        }
197
198        if !self.branch_state.is_collapsed() {
199            self.branch_state = BranchState::Collapsed;
200        }
201
202        depth.decrease();
203        if !depth.is_zero()
204            && let Some(children) = &mut self.children
205        {
206            children.collapse(depth);
207        }
208    }
209
210    /// Toggle the branch state.
211    ///
212    /// Expand if collapsed, collapse if expanded.
213    ///
214    /// Will do nothing if not a [Branch](NodeKind::Branch).
215    pub fn toggle_branch_state(&mut self, context: BackendT::Context) -> Result<(), BackendT::Error>
216    where
217        BackendT::Context: Clone,
218    {
219        if !self.kind.is_branch() {
220            return Ok(());
221        }
222
223        _ = match self.branch_state {
224            BranchState::Collapsed => self.expand(Some(1), context)?,
225            BranchState::Expanded => self.collapse(Some(1)),
226        };
227
228        Ok(())
229    }
230
231    /// Data.
232    ///
233    /// If not already cached will fetch it from the backend.
234    pub fn data(&mut self, context: BackendT::Context) -> Result<Option<Cow<'_, BackendT::Data>>, BackendT::Error>
235    where
236        BackendT::Data: Clone,
237    {
238        if self.data.is_none() {
239            if let Some((data, cache)) = BackendT::data(self, context)? {
240                if cache {
241                    self.data = Some(data);
242                } else {
243                    return Ok(Some(Cow::Owned(data)));
244                }
245            }
246        }
247
248        Ok(self.data.as_ref().map(Cow::Borrowed))
249    }
250}