Skip to main content

TreeBackend

Trait TreeBackend 

Source
pub trait TreeBackend<ContextT, ErrorT, IdT, DataT>: Sized {
    // Provided methods
    fn tree_view(
        context: ContextT,
    ) -> TreeView<Self, ContextT, ErrorT, IdT, DataT> { ... }
    fn tree_model(
        context: ContextT,
    ) -> TreeModel<Self, ContextT, ErrorT, IdT, DataT> { ... }
    fn symbol(
        node: &Node<Self, ContextT, ErrorT, IdT, DataT>,
        context: ContextT,
    ) -> Symbol<'_> { ... }
    fn roots(
        context: ContextT,
    ) -> Result<NodeList<Self, ContextT, ErrorT, IdT, DataT>, ErrorT> { ... }
    fn populate(
        node: &mut Node<Self, ContextT, ErrorT, IdT, DataT>,
        context: ContextT,
    ) -> Result<(), ErrorT> { ... }
    fn data(
        node: &mut Node<Self, ContextT, ErrorT, IdT, DataT>,
        context: ContextT,
    ) -> Result<Option<(DataT, bool)>, ErrorT> { ... }
    fn handle_selection_changed(cursive: &mut Cursive) { ... }
    fn handle_error(cursive: &mut Cursive, error: ErrorT) { ... }
}
Expand description

Tree view backend.

A ContextT is provided to some of the trait functions. It is intended to be used to access node data. For example, it can be a database connection or a work directory. The context is stored in the model and a clone of it will be produced for every call. Thus, cloning should be cheap. Consider wrapping it in an Arc. If you don’t need it, it can be set to ().

ErrorT is returned as the Err for some of the trait functions. You can implement handle_error to display an error message to the user, log it, etc. If you don’t need special error handling, it can be set to ().

Each node has an IdT field. It can be used by the backend to identify the node in order to retrieve its data, e.g. in populate] and data]. It is not otherwise used by the model and does not have to be unique. If you don’t need it, it can be set to ().

Finally, each node has an optional DataT field for custom data. If you don’t need it, it can be set to ().

Also see SimpleTreeBackend.

Provided Methods§

Source

fn tree_view(context: ContextT) -> TreeView<Self, ContextT, ErrorT, IdT, DataT>

Create a tree view with this backend.

Examples found in repository?
examples/file_browser.rs (line 17)
13fn main() {
14    let mut cursive = Cursive::default();
15
16    let current_dir = current_dir().unwrap();
17    let mut tree = FileBackend::tree_view(current_dir.into());
18
19    // Populate the first level (just the roots)
20    tree.model.populate(Some(1)).unwrap();
21
22    let mut browser = LinearLayout::horizontal();
23    browser.add_child(tree.with_name("tree").scrollable().full_screen());
24    browser.add_child(TextView::new("").with_name("details").scrollable().full_screen());
25
26    cursive.add_fullscreen_layer(browser);
27    cursive.add_global_callback('q', |cursive| cursive.quit());
28
29    cursive.run();
30}
More examples
Hide additional examples
examples/simple.rs (line 11)
8fn main() {
9    let mut cursive = Cursive::default();
10
11    let mut tree = SimpleTreeBackend::tree_view(());
12
13    // A few roots
14
15    tree.model.add_root(NodeKind::Leaf, (), "Hello".into());
16    tree.model.add_root(NodeKind::Branch, (), "World".into());
17
18    // Add 10 children to "World"
19    // and expand it
20
21    let world = tree.model.at_path_mut([1].into()).unwrap();
22    for i in 0..10 {
23        world.add_child(NodeKind::Leaf, (), format!("Child #{}", i + 1).into());
24    }
25    world.expand_branch(()).unwrap();
26
27    // Add 10 grandchildren each to "Child #5" to "Child #10"
28    // Note that we change then to a branch in order to support having children
29
30    for c in 4..10 {
31        let child = tree.model.at_path_mut([1, c].into()).unwrap();
32        child.kind = NodeKind::Branch;
33        for gc in 0..10 {
34            child.add_child(NodeKind::Leaf, (), format!("Grandchild #{}", gc + 1).into());
35        }
36    }
37
38    cursive.add_fullscreen_layer(tree.scrollable());
39    cursive.add_global_callback('q', |cursive| cursive.quit());
40
41    cursive.run();
42}
Source

fn tree_model( context: ContextT, ) -> TreeModel<Self, ContextT, ErrorT, IdT, DataT>

Create a tree model with this backend.

Source

fn symbol( node: &Node<Self, ContextT, ErrorT, IdT, DataT>, context: ContextT, ) -> Symbol<'_>

Get a node’s symbol.

Note that its char count must be 1.

The default implementation uses the node kind and branch state.

Source

fn roots( context: ContextT, ) -> Result<NodeList<Self, ContextT, ErrorT, IdT, DataT>, ErrorT>

Get the root nodes.

The root nodes must be depth 0 but otherwise can be as pre-populated as you wish. For example, you can provide them with children and optional data.

The default implementation returns an empty list.

Source

fn populate( node: &mut Node<Self, ContextT, ErrorT, IdT, DataT>, context: ContextT, ) -> Result<(), ErrorT>

Populate a node’s children.

The children must have a depth of +1 of the node.

This is called when expanding the node only if it’s children field is None. Setting children to Some, even to an empty list, will ensure that this function won’t be called again for the node until it is set to None.

The default implementation does nothing.

Source

fn data( node: &mut Node<Self, ContextT, ErrorT, IdT, DataT>, context: ContextT, ) -> Result<Option<(DataT, bool)>, ErrorT>

Get a node’s data.

This is called when data is accessed only if the field is None. Returning (data, true) will store it in the field as Some. Returning (data, false) will cause this function to be called every time data is accessed.

The default implementation returns None.

Source

fn handle_selection_changed(cursive: &mut Cursive)

Called when the selected node changes, including when the selection is set to None.

Accessing the currently selected node must be done via the tree view, e.g. TreeView::selected_node. Thus, you may want to wrap the tree view in a NamedView. You can then access it here like so:

match cursive.call_on_name("MyTree", |tree: &mut TreeView<MyBackend, MyContext, MyError, MyId, MyData>| {
    Ok(match tree.selected_node_mut() {
        Some(node) => node.data(context)?.map(|data| data.something.clone()),
        None => None,
    })
}) {
    Some(Ok(Some(something))) => do_something_with(something),
    Some(Err(error)) => BackendT::handle_error(cursive, error),
    _ => {},
}
Source

fn handle_error(cursive: &mut Cursive, error: ErrorT)

Called when other backend functions return Err.

Examples found in repository?
examples/file_browser.rs (line 82)
66    fn handle_selection_changed(cursive: &mut Cursive) {
67        let content = match cursive.call_on_name(
68            "tree",
69            |tree: &mut TreeView<Self, Arc<PathBuf>, io::Error, PathBuf, Metadata>| {
70                // Although we're not using the context in data() but we still need to provide it
71                let base_directory = tree.model.context.clone();
72                Ok(match tree.selected_node_mut() {
73                    Some(node) => match node.data(base_directory)? {
74                        Some(metadata) => Some(format_metadata(&metadata)?),
75                        None => None,
76                    },
77                    None => None,
78                })
79            },
80        ) {
81            Some(Ok(Some(text))) => text,
82            Some(Err(error)) => return Self::handle_error(cursive, error),
83            _ => "".into(),
84        };
85
86        cursive.call_on_name("details", |details: &mut TextView| {
87            details.set_content(content);
88        });
89    }

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§