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}