cursive-tree 0.0.9

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

use {cursive::*, event::*};

//
// TreeView
//

/// Tree view.
///
/// Nodes can be leaves (no children) or branches (potentially have children) and can have custom
/// data (`DataT`) attached to them. Their labels can be stylized with multiple colors and effects.
///
/// Event handling (configurable):
///
/// * Up/Down keys: move selection
/// * PgUp/PgDown keys: move selection by 10 (configurable)
/// * Left/Right keys: collapse/expand selected branch node
/// * Enter key: toggle selected branch node collapse/expand
/// * "-"/"+" keys: collapse/expand selected branch and all children recursively
/// * "<"/">" keys: collapse/expand all nodes
/// * Mouse click on node: select
/// * Mouse click to the left of the node: toggle branch collapse/expand
///
/// The view's data and behavior are backed by a [TreeBackend]. The nodes are stored and managed by
/// a [TreeModel]. The model can be populated in advance and can also fetch data from the backend
/// on demand, e.g. when a branch node is expanded.
pub struct TreeView<BackendT>
where
    BackendT: TreeBackend,
{
    /// Tree model.
    pub model: TreeModel<BackendT>,

    pub(crate) selected_row: Option<usize>,
    pub(crate) page: usize,
    pub(crate) debug: bool,
    pub(crate) actions: Actions,
}

impl<BackendT> TreeView<BackendT>
where
    BackendT: TreeBackend,
{
    /// Page size for
    /// [SelectUpPage](Action::SelectUpPage)/[SelectDownPage](Action::SelectDownPage).
    pub fn page(&self) -> usize {
        self.page
    }

    /// Set page size for
    /// [SelectUpPage](Action::SelectUpPage)/[SelectDownPage](Action::SelectDownPage).
    pub fn set_page(&mut self, page: usize) {
        self.page = page;
    }

    /// Set page size for
    /// [SelectUpPage](Action::SelectUpPage)/[SelectDownPage](Action::SelectDownPage).
    ///
    /// Chainable.
    pub fn with_page(self, page: usize) -> Self {
        self.with(|self_| self_.set_page(page))
    }

    /// Debug mode.
    pub fn debug(&self) -> bool {
        self.debug
    }

    /// Set debug mode.
    pub fn set_debug(&mut self, debug: bool) {
        self.debug = debug;
    }

    /// Set debug mode.
    ///
    /// Chainable.
    pub fn with_debug(self, debug: bool) -> Self {
        self.with(|self_| self_.set_debug(debug))
    }

    /// Action map.
    pub fn actions(&self) -> &Actions {
        &self.actions
    }

    /// Action map.
    pub fn actions_mut(&mut self) -> &mut Actions {
        &mut self.actions
    }

    /// Set action map.
    pub fn set_actions(&mut self, actions: Actions) {
        self.actions = actions;
    }

    /// Set action map.
    ///
    /// Chainable.
    pub fn with_actions(self, actions: Actions) -> Self {
        self.with(|self_| self_.set_actions(actions))
    }

    /// Set action.
    ///
    /// Note that actions can be associated with more than one event.
    pub fn set_action<EventT>(&mut self, action: Action, event: EventT)
    where
        EventT: Into<Event>,
    {
        self.actions.insert(event.into(), action);
    }

    /// Set action.
    ///
    /// Note that actions can be associated with more than one event.
    ///
    /// Chainable.
    pub fn with_action<EventT>(self, action: Action, event: EventT) -> Self
    where
        EventT: Into<Event>,
    {
        self.with(|self_| self_.set_action(action, event))
    }

    /// Remove action.
    ///
    /// Will remove all associated events.
    ///
    /// Return true if removed.
    pub fn remove_action(&mut self, action: Action) -> bool {
        action.remove(&mut self.actions)
    }

    /// Remove action.
    ///
    /// Will remove all associated events.
    ///
    /// Chainable.
    pub fn without_action(self, action: Action) -> Self {
        self.with(|self_| _ = self_.remove_action(action))
    }
}

impl<BackendT> From<TreeModel<BackendT>> for TreeView<BackendT>
where
    BackendT: TreeBackend,
{
    fn from(model: TreeModel<BackendT>) -> Self {
        Self { model, selected_row: None, page: 10, debug: false, actions: Action::defaults() }
    }
}