Skip to main content

cursive_tree/backend/
backend.rs

1use super::super::{model::*, view::*};
2
3use cursive::*;
4
5/// Default leaf symbol. Unicode U+25AA.
6pub const DEFAULT_LEAF_SYMBOL: &str = "▪";
7
8/// Default branch expanded symbol. Unicode U+25BC.
9pub const DEFAULT_BRANCH_EXPANDED_SYMBOL: &str = "▼";
10
11/// Default branch collapsed symbol. Unicode U+25B6.
12pub const 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 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 best be cheap. Consider wrapping it
29    /// in 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    /// For associating custom data with nodes.
53    ///
54    /// Node's have a [data](Node::data) function that in turn calls our
55    /// [data](TreeBackend::data) function.
56    ///
57    /// Depending on your needs, the data can be optionally cached in the node's
58    /// [data](Node#structfield.data) field.
59    ///
60    /// If you don't need it, it can be set to `()`.
61    type Data;
62
63    /// Create a tree view with this backend.
64    fn tree_view(context: Self::Context) -> TreeView<Self> {
65        Self::tree_model(context).into()
66    }
67
68    /// Create a tree model with this backend.
69    fn tree_model(context: Self::Context) -> TreeModel<Self> {
70        TreeModel::new(context)
71    }
72
73    /// Get a node's symbol.
74    ///
75    /// Note that its char count *must be 1*.
76    ///
77    /// The default implementation uses the node kind and branch state.
78    #[allow(unused)]
79    fn symbol(node: &Node<Self>, context: Self::Context) -> Symbol<'_> {
80        match (node.kind, node.branch_state) {
81            (NodeKind::Leaf, _) => DEFAULT_LEAF_SYMBOL,
82            (NodeKind::Branch, BranchState::Expanded) => DEFAULT_BRANCH_EXPANDED_SYMBOL,
83            (NodeKind::Branch, BranchState::Collapsed) => DEFAULT_BRANCH_COLLAPSED_SYMBOL,
84        }
85        .into()
86    }
87
88    /// Get the root nodes.
89    ///
90    /// The root nodes must be depth 0 but otherwise can be as pre-populated as you wish. For
91    /// example, you can provide them with children and optional data.
92    ///
93    /// The default implementation returns an empty list.
94    #[allow(unused)]
95    fn roots(context: Self::Context) -> Result<NodeList<Self>, Self::Error> {
96        Ok(Default::default())
97    }
98
99    /// Populate a node's children.
100    ///
101    /// The children *must* have a depth of +1 of the node.
102    ///
103    /// This is called when expanding the node *only* if it's children field is [None]. Setting
104    /// children to [Some], even to an empty list, will ensure that this function won't be called
105    /// again for the node until it is set to [None].
106    ///
107    /// The default implementation does nothing.
108    #[allow(unused)]
109    fn populate(node: &mut Node<Self>, context: Self::Context) -> Result<(), Self::Error> {
110        Ok(())
111    }
112
113    /// Get a node's data.
114    ///
115    /// This is called when data is accessed *only* if the field is [None]. Returning (data, true)
116    /// will store it in the field as [Some]. Returning (data, false) will cause this function to
117    /// be called every time data is accessed.
118    ///
119    /// The default implementation returns [None].
120    #[allow(unused)]
121    fn data(node: &mut Node<Self>, context: Self::Context) -> Result<Option<(Self::Data, bool)>, Self::Error> {
122        Ok(None)
123    }
124
125    /// Called when the selected node changes, including when the selection is set to [None].
126    ///
127    /// Accessing the currently selected node must be done via the tree view, e.g.
128    /// [selected_node](super::super::view::TreeView::selected_node). Thus, you may want to wrap
129    /// the tree view in a [NamedView](cursive::views::NamedView). You can then access it here like
130    /// so:
131    ///
132    /// ```rust
133    /// match cursive.call_on_name("MyTree", |tree: &mut TreeView<MyBackend>| {
134    ///     Ok(match tree.selected_node_mut() {
135    ///         Some(node) => node.data(context)?.map(|data| data.something.clone()),
136    ///         None => None,
137    ///     })
138    /// }) {
139    ///     Some(Ok(Some(something))) => do_something_with(something),
140    ///     Some(Err(error)) => BackendT::handle_error(cursive, error),
141    ///     _ => {},
142    /// }
143    /// ```
144    #[allow(unused)]
145    fn handle_selection_changed(cursive: &mut Cursive, context: Self::Context) {}
146
147    /// Called when other backend functions return [Err].
148    #[allow(unused)]
149    fn handle_error(cursive: &mut Cursive, context: Self::Context, error: Self::Error) {}
150}