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}