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    pub representation_size: Vec2,
33
34    /// State for [Branch](NodeKind::Branch) node.
35    pub branch_state: BranchState,
36
37    /// Children for [Branch](NodeKind::Branch) node.
38    pub children: Option<NodeList<BackendT>>,
39
40    /// Data.
41    pub data: Option<BackendT::Data>,
42
43    backend: PhantomData<BackendT>,
44}
45
46impl<BackendT> Node<BackendT>
47where
48    BackendT: TreeBackend,
49{
50    /// Constructor.
51    pub fn new(depth: usize, kind: NodeKind, id: BackendT::ID, representation: Representation) -> Self {
52        let representation_size = (representation.width(), 1).into();
53        Self {
54            depth,
55            kind,
56            id,
57            representation,
58            representation_size,
59            branch_state: Default::default(),
60            children: None,
61            data: None,
62            backend: Default::default(),
63        }
64    }
65
66    /// Symbol.
67    ///
68    /// Its char count is always 1.
69    pub fn symbol(&self, context: BackendT::Context) -> Symbol<'_> {
70        BackendT::symbol(self, context)
71    }
72
73    /// Get node at path.
74    pub fn at_path(&self, path: NodePath) -> Option<&Self> {
75        if path.is_empty() { Some(self) } else { self.children.as_ref().and_then(|children| children.at_path(path)) }
76    }
77
78    /// Get node at path.
79    pub fn at_path_mut(&mut self, path: NodePath) -> Option<&mut Self> {
80        if path.is_empty() {
81            Some(self)
82        } else {
83            self.children.as_mut().and_then(|children| children.at_path_mut(path))
84        }
85    }
86
87    /// Fill path to node.
88    ///
89    /// Returns true if found.
90    pub fn fill_path(&self, path: &mut NodePath, node: &Self) -> bool {
91        self.children.as_ref().map(|children| children.fill_path(path, node)).unwrap_or_default()
92    }
93
94    /// Fetch nodes from backend.
95    ///
96    /// If depth is [None] will populate all depths.
97    ///
98    /// If depth is 0 will do nothing.
99    pub fn populate(&mut self, mut depth: Option<usize>, context: BackendT::Context) -> Result<(), BackendT::Error>
100    where
101        BackendT::Context: Clone,
102    {
103        if depth.is_zero() || !self.kind.is_branch() {
104            return Ok(());
105        }
106
107        if self.children.is_none() {
108            BackendT::populate(self, context.clone())?;
109        }
110
111        depth.decrease();
112        if !depth.is_zero()
113            && let Some(children) = &mut self.children
114        {
115            for node in children {
116                node.populate(depth, context.clone())?;
117            }
118        }
119
120        Ok(())
121    }
122
123    /// Add a child node.
124    pub fn add_child(&mut self, kind: NodeKind, id: BackendT::ID, representation: Representation) {
125        if !self.kind.is_branch() {
126            return;
127        }
128
129        if self.children.is_none() {
130            self.children = Some(Default::default());
131        }
132
133        self.children.as_mut().expect("children").add(self.depth + 1, kind, id, representation);
134    }
135
136    /// Inserts a child node.
137    pub fn insert_child(&mut self, index: usize, kind: NodeKind, id: BackendT::ID, representation: Representation) {
138        if !self.kind.is_branch() {
139            return;
140        }
141
142        if self.children.is_none() {
143            self.children = Some(Default::default());
144        }
145
146        self.children.as_mut().expect("children").insert(index, self.depth + 1, kind, id, representation);
147    }
148
149    /// Expand the branch.
150    ///
151    /// Will return false if not a [Branch](NodeKind::Branch) or already expanded.
152    pub fn expand_branch(&mut self, context: BackendT::Context) -> Result<bool, BackendT::Error>
153    where
154        BackendT::Context: Clone,
155    {
156        if !self.kind.is_branch() || self.branch_state.is_expanded() {
157            return Ok(false);
158        }
159
160        self.populate(Some(1), context)?;
161        self.branch_state = BranchState::Expanded;
162        Ok(true)
163    }
164
165    /// Collapse the branch.
166    ///
167    /// Will return false if not a [Branch](NodeKind::Branch) or already collapsed.
168    pub fn collapse_branch(&mut self) -> bool {
169        if !self.kind.is_branch() || self.branch_state.is_collapsed() {
170            return false;
171        }
172
173        self.branch_state = BranchState::Collapsed;
174        true
175    }
176
177    /// Toggle the branch state.
178    ///
179    /// Expand if collapsed, collapse if expanded.
180    ///
181    /// Will do nothing if not a [Branch](NodeKind::Branch).
182    pub fn toggle_branch_state(&mut self, context: BackendT::Context) -> Result<(), BackendT::Error>
183    where
184        BackendT::Context: Clone,
185    {
186        if !self.kind.is_branch() {
187            return Ok(());
188        }
189
190        match self.branch_state {
191            BranchState::Collapsed => {
192                self.expand_branch(context)?;
193            }
194            BranchState::Expanded => {
195                self.collapse_branch();
196            }
197        }
198
199        Ok(())
200    }
201
202    /// Data.
203    ///
204    /// If not already cached will fetch it from the backend.
205    pub fn data(&mut self, context: BackendT::Context) -> Result<Option<Cow<'_, BackendT::Data>>, BackendT::Error>
206    where
207        BackendT::Data: Clone,
208    {
209        if self.data.is_none() {
210            if let Some((data, cache)) = BackendT::data(self, context)? {
211                if cache {
212                    self.data = Some(data);
213                } else {
214                    return Ok(Some(Cow::Owned(data)));
215                }
216            }
217        }
218
219        Ok(self.data.as_ref().map(Cow::Borrowed))
220    }
221}