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