Skip to main content

TreeBackend

Trait TreeBackend 

Source
pub trait TreeBackend: Sized {
    type Context;
    type Error;
    type ID;
    type Data;

    // Provided methods
    fn tree_view(context: Self::Context) -> TreeView<Self> { ... }
    fn tree_model(context: Self::Context) -> TreeModel<Self> { ... }
    fn symbol(node: &Node<Self>, context: Self::Context) -> Symbol<'_> { ... }
    fn roots(context: Self::Context) -> Result<NodeList<Self>, Self::Error> { ... }
    fn populate(
        node: &mut Node<Self>,
        context: Self::Context,
    ) -> Result<(), Self::Error> { ... }
    fn data(
        node: &mut Node<Self>,
        context: Self::Context,
    ) -> Result<Option<(Self::Data, bool)>, Self::Error> { ... }
    fn handle_selection_changed(cursive: &mut Cursive) { ... }
    fn handle_error(cursive: &mut Cursive, error: Self::Error) { ... }
}
Expand description

Tree view backend.

Also see SimpleTreeBackend.

Required Associated Types§

Source

type Context

A context is provided as an argument 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 context field of the model. A clone of it will be produced for every call, thus cloning should best be cheap. Consider wrapping it in an Arc.

If you don’t need it, it can be set to ().

Source

type Error

Returned as the Err of 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 it, it can be set to ().

Source

type ID

Each node has an id field of this type.

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 ().

Source

type Data

For associating custom data with nodes.

Node’s have a data function that in turn calls our data function.

Depending on your needs, the data can be optionally cached in the node’s data field.

If you don’t need it, it can be set to ().

Provided Methods§

Source

fn tree_view(context: Self::Context) -> TreeView<Self>

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(Panel::new(tree.with_name("tree").scrollable()));
24    browser.add_child(Panel::new(TextView::new("").with_name("details").scrollable()));
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
20    let world = tree.model.at_path_mut([1].into()).unwrap();
21    for i in 0..10 {
22        world.add_child(NodeKind::Leaf, (), format!("Child #{}", i + 1).into());
23    }
24
25    // Add 10 grandchildren each to "Child #5" -> "Child #10"
26    // Note that we change them to branch in order to support having children
27
28    let mut gc = 0;
29    for c in 4..10 {
30        let child = tree.model.at_path_mut([1, c].into()).unwrap();
31        child.kind = NodeKind::Branch;
32        for _ in 0..10 {
33            child.add_child(NodeKind::Leaf, (), format!("Grandchild #{}", gc + 1).into());
34            gc += 1;
35        }
36    }
37
38    // Expand all nodes
39
40    tree.model.expand(None).unwrap();
41
42    cursive.add_fullscreen_layer(Panel::new(tree.scrollable()));
43    cursive.add_global_callback('q', |cursive| cursive.quit());
44
45    cursive.run();
46}
Source

fn tree_model(context: Self::Context) -> TreeModel<Self>

Create a tree model with this backend.

Source

fn symbol(node: &Node<Self>, context: Self::Context) -> 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: Self::Context) -> Result<NodeList<Self>, Self::Error>

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>, context: Self::Context, ) -> Result<(), Self::Error>

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>, context: Self::Context, ) -> Result<Option<(Self::Data, bool)>, Self::Error>

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. 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>| {
    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: Self::Error)

Called when other backend functions return Err.

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

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§