Skip to main content

cursive_tree/backend/
backend.rs

1use super::super::{model::*, view::*};
2
3use cursive::*;
4
5/// Default leaf symbol.
6const DEFAULT_LEAF_SYMBOL: &str = "•";
7
8/// Default branch expanded symbol.
9const DEFAULT_BRANCH_EXPANDED_SYMBOL: &str = "▼";
10
11/// Default branch collapsed symbol.
12const DEFAULT_BRANCH_COLLAPSED_SYMBOL: &str = "▶";
13
14//
15// TreeBackend
16//
17
18/// Tree view backend.
19///
20/// Also see [SimpleTreeBackend](super::SimpleTreeBackend).
21pub trait TreeBackend: Sized {
22    /// A context is provided as an argument to some of the trait functions.
23    ///
24    /// It is intended to be used to access node data. For example, it can be a database connection
25    /// or a work directory.
26    ///
27    /// The context is stored in the [context](TreeModel::context) field of the model. A clone of
28    /// it will be produced for every call, thus cloning should be cheap. Consider wrapping it in
29    /// an [Arc](std::sync::Arc).
30    ///
31    /// If you don't need it, it can be set to `()`.
32    type Context;
33
34    /// Returned as the [Err] of some of the trait functions.
35    ///
36    /// You can implement [handle_error](TreeBackend::handle_error) to display an error message to
37    /// the user, log it, etc.
38    ///
39    /// If you don't need it, it can be set to `()`.
40    type Error;
41
42    /// Each node has an [id](Node::id) field of this type.
43    ///
44    /// It can be used by the backend to identify the node in order to retrieve its data, e.g. in
45    /// [populate](TreeBackend::populate) and [data](TreeBackend::data).
46    ///
47    /// It is not otherwise used by the model and does *not* have to be unique.
48    ///
49    /// If you don't need it, it can be set to `()`.
50    type ID;
51
52    /// Each node has an optional [data](Node#structfield.data) field of this type for custom data.
53    ///
54    /// If you don't need it, it can be set to `()`.
55    type Data;
56
57    /// Create a tree view with this backend.
58    fn tree_view(context: Self::Context) -> TreeView<Self> {
59        Self::tree_model(context).into()
60    }
61
62    /// Create a tree model with this backend.
63    fn tree_model(context: Self::Context) -> TreeModel<Self> {
64        TreeModel::new(context)
65    }
66
67    /// Get a node's symbol.
68    ///
69    /// Note that its char count *must be 1*.
70    ///
71    /// The default implementation uses the node kind and branch state.
72    #[allow(unused)]
73    fn symbol(node: &Node<Self>, context: Self::Context) -> Symbol<'_> {
74        Symbol::String(match (node.kind, node.branch_state) {
75            (NodeKind::Leaf, _) => DEFAULT_LEAF_SYMBOL,
76            (NodeKind::Branch, BranchState::Expanded) => DEFAULT_BRANCH_EXPANDED_SYMBOL,
77            (NodeKind::Branch, BranchState::Collapsed) => DEFAULT_BRANCH_COLLAPSED_SYMBOL,
78        })
79    }
80
81    /// Get the root nodes.
82    ///
83    /// The root nodes must be depth 0 but otherwise can be as pre-populated as you wish. For
84    /// example, you can provide them with children and optional data.
85    ///
86    /// The default implementation returns an empty list.
87    #[allow(unused)]
88    fn roots(context: Self::Context) -> Result<NodeList<Self>, Self::Error> {
89        Ok(Default::default())
90    }
91
92    /// Populate a node's children.
93    ///
94    /// The children *must* have a depth of +1 of the node.
95    ///
96    /// This is called when expanding the node *only* if it's children field is [None]. Setting
97    /// children to [Some], even to an empty list, will ensure that this function won't be called
98    /// again for the node until it is set to [None].
99    ///
100    /// The default implementation does nothing.
101    #[allow(unused)]
102    fn populate(node: &mut Node<Self>, context: Self::Context) -> Result<(), Self::Error> {
103        Ok(())
104    }
105
106    /// Get a node's data.
107    ///
108    /// This is called when data is accessed *only* if the field is [None]. Returning (data, true)
109    /// will store it in the field as [Some]. Returning (data, false) will cause this function to
110    /// be called every time data is accessed.
111    ///
112    /// The default implementation returns [None].
113    #[allow(unused)]
114    fn data(node: &mut Node<Self>, context: Self::Context) -> Result<Option<(Self::Data, bool)>, Self::Error> {
115        Ok(None)
116    }
117
118    /// Called when the selected node changes, including when the selection is set to [None].
119    ///
120    /// Accessing the currently selected node must be done via the tree view, e.g.
121    /// [selected_node](super::super::view::TreeView::selected_node). Thus, you may want to wrap
122    /// the tree view in a [NamedView](cursive::views::NamedView). You can then access it here like
123    /// so:
124    ///
125    /// ```rust
126    /// match cursive.call_on_name("MyTree", |tree: &mut TreeView<MyBackend>| {
127    ///     Ok(match tree.selected_node_mut() {
128    ///         Some(node) => node.data(context)?.map(|data| data.something.clone()),
129    ///         None => None,
130    ///     })
131    /// }) {
132    ///     Some(Ok(Some(something))) => do_something_with(something),
133    ///     Some(Err(error)) => BackendT::handle_error(cursive, error),
134    ///     _ => {},
135    /// }
136    /// ```
137    #[allow(unused)]
138    fn handle_selection_changed(cursive: &mut Cursive) {}
139
140    /// Called when other backend functions return [Err].
141    #[allow(unused)]
142    fn handle_error(cursive: &mut Cursive, error: Self::Error) {}
143}