cursive-tree 0.0.9

Tree view for the Cursive TUI library
Documentation
use super::super::{model::*, view::*};

use cursive::*;

/// Default leaf symbol. Unicode U+25AA.
pub const DEFAULT_LEAF_SYMBOL: &str = "";

/// Default branch expanded symbol. Unicode U+25BC.
pub const DEFAULT_BRANCH_EXPANDED_SYMBOL: &str = "";

/// Default branch collapsed symbol. Unicode U+25B6.
pub const DEFAULT_BRANCH_COLLAPSED_SYMBOL: &str = "";

//
// TreeBackend
//

/// Tree view backend.
///
/// Also see [SimpleTreeBackend](super::SimpleTreeBackend).
pub trait TreeBackend: Sized {
    /// A context is provided as an argument to 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](TreeModel::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](std::sync::Arc).
    ///
    /// If you don't need it, it can be set to `()`.
    type Context;

    /// Returned as the [Err] of some of the trait functions.
    ///
    /// You can implement [handle_error](TreeBackend::handle_error) to display an error message to
    /// the user, log it, etc.
    ///
    /// If you don't need it, it can be set to `()`.
    type Error;

    /// Each node has an [id](Node::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](TreeBackend::populate) and [data](TreeBackend::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 `()`.
    type ID;

    /// For associating custom data with nodes.
    ///
    /// Node's have a [data](Node::data) function that in turn calls our
    /// [data](TreeBackend::data) function.
    ///
    /// Depending on your needs, the data can be optionally cached in the node's
    /// [data](Node#structfield.data) field.
    ///
    /// If you don't need it, it can be set to `()`.
    type Data;

    /// Create a tree view with this backend.
    fn tree_view(context: Self::Context) -> TreeView<Self> {
        Self::tree_model(context).into()
    }

    /// Create a tree model with this backend.
    fn tree_model(context: Self::Context) -> TreeModel<Self> {
        TreeModel::new(context)
    }

    /// Get a node's symbol.
    ///
    /// Note that its char count *must be 1*.
    ///
    /// The default implementation uses the node kind and branch state.
    #[allow(unused)]
    fn symbol(node: &Node<Self>, context: Self::Context) -> Symbol<'_> {
        match (node.kind, node.branch_state) {
            (NodeKind::Leaf, _) => DEFAULT_LEAF_SYMBOL,
            (NodeKind::Branch, BranchState::Expanded) => DEFAULT_BRANCH_EXPANDED_SYMBOL,
            (NodeKind::Branch, BranchState::Collapsed) => DEFAULT_BRANCH_COLLAPSED_SYMBOL,
        }
        .into()
    }

    /// 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.
    #[allow(unused)]
    fn roots(context: Self::Context) -> Result<NodeList<Self>, Self::Error> {
        Ok(Default::default())
    }

    /// 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.
    #[allow(unused)]
    fn populate(node: &mut Node<Self>, context: Self::Context) -> Result<(), Self::Error> {
        Ok(())
    }

    /// 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].
    #[allow(unused)]
    fn data(node: &mut Node<Self>, context: Self::Context) -> Result<Option<(Self::Data, bool)>, Self::Error> {
        Ok(None)
    }

    /// 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](super::super::view::TreeView::selected_node). Thus, you may want to wrap
    /// the tree view in a [NamedView](cursive::views::NamedView). You can then access it here like
    /// so:
    ///
    /// ```rust
    /// 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),
    ///     _ => {},
    /// }
    /// ```
    #[allow(unused)]
    fn handle_selection_changed(cursive: &mut Cursive, context: Self::Context) {}

    /// Called when other backend functions return [Err].
    #[allow(unused)]
    fn handle_error(cursive: &mut Cursive, context: Self::Context, error: Self::Error) {}
}