cursive-tree 0.0.9

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

use {cursive::*, std::cmp::*};

impl<BackendT> TreeView<BackendT>
where
    BackendT: TreeBackend,
{
    /// The selected row.
    pub fn selected_row(&self) -> Option<usize> {
        self.selected_row
    }

    /// The selected node.
    pub fn selected_node(&self) -> Option<&Node<BackendT>> {
        self.selected_row.and_then(|selected_row| self.model.at_row(selected_row))
    }

    /// The selected node.
    pub fn selected_node_mut(&mut self) -> Option<&mut Node<BackendT>> {
        self.selected_path().and_then(|path| self.model.at_path_mut(path))
    }

    /// The selected path.
    pub fn selected_path(&self) -> Option<NodePath> {
        self.selected_node().and_then(|node| self.model.path(node))
    }

    /// Whether the row is selected.
    pub fn is_selected(&self, row: usize) -> bool {
        self.selected_row.map(|selected_row| selected_row == row).unwrap_or_default()
    }

    /// Set selected row.
    ///
    /// If the row is invalid will set the selection to [None].
    ///
    /// If the selection is changed will call
    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
    pub fn select(&mut self, row: usize, cursive: &mut Cursive)
    where
        BackendT::Context: Clone,
    {
        let last_selected_row = self.selected_row;
        self.selected_row = if self.model.is_empty() || row >= self.model.extents().y { None } else { Some(row) };
        if self.selected_row != last_selected_row {
            BackendT::handle_selection_changed(cursive, self.model.context.clone());
        }
    }

    /// Select top row.
    ///
    /// If the tree is empty will set the selection to [None].
    ///
    /// If the selection is changed will call
    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
    pub fn select_top(&mut self, cursive: &mut Cursive)
    where
        BackendT::Context: Clone,
    {
        let last_selected_row = self.selected_row;
        self.select_top_();
        if self.selected_row != last_selected_row {
            BackendT::handle_selection_changed(cursive, self.model.context.clone());
        }
    }

    /// Select bottom row.
    ///
    /// If the tree is empty will set the selection to [None].
    ///
    /// If the selection is changed will call
    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
    pub fn select_bottom(&mut self, cursive: &mut Cursive)
    where
        BackendT::Context: Clone,
    {
        let last_selected_row = self.selected_row;
        self.select_bottom_();
        if self.selected_row != last_selected_row {
            BackendT::handle_selection_changed(cursive, self.model.context.clone());
        }
    }

    /// Move selection by delta rows if possible.
    ///
    /// If the selection is [None] will select the top row.
    ///
    /// If the selection is changed will call
    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
    pub fn move_selection(&mut self, delta: isize, cursive: &mut Cursive)
    where
        BackendT::Context: Clone,
    {
        let last_selected_row = self.selected_row;
        self.move_selection_(delta);
        if self.selected_row != last_selected_row {
            BackendT::handle_selection_changed(cursive, self.model.context.clone());
        }
    }

    // Select top row.
    pub(crate) fn select_top_(&mut self) {
        self.selected_row = if self.model.is_empty() || self.model.extents().y == 0 { None } else { Some(0) }
    }

    // Select bottom row.
    pub(crate) fn select_bottom_(&mut self) {
        self.selected_row = if self.model.is_empty() {
            None
        } else {
            let height = self.model.extents().y;
            if height == 0 { None } else { Some(height - 1) }
        };
    }

    // Move selection by delta rows.
    pub(crate) fn move_selection_(&mut self, delta: isize) {
        if delta == 0 {
            return;
        }

        self.selected_row = if self.model.is_empty() {
            None
        } else {
            let height = self.model.extents().y;
            if height == 0 {
                None
            } else {
                Some(
                    self.selected_row
                        .map(|selected_row| min(selected_row.checked_add_signed(delta).unwrap_or_default(), height - 1))
                        .unwrap_or_default(),
                )
            }
        };
    }
}