cursive-tree 0.0.9

Tree view for the Cursive TUI library
Documentation
use super::{super::backend::*, depth::*, iterator::*, kind::*, node::*, path::*};

use {
    cursive::{style::*, utils::span::*},
    std::{ptr, slice::*},
};

//
// NodeList
//

/// Tree node list.
pub struct NodeList<BackendT>(pub Vec<Node<BackendT>>)
where
    BackendT: TreeBackend;

impl<BackendT> NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    /// Iterate nodes in visual order from top to bottom.
    ///
    /// When only_expanded is true will skip the children of collapsed branches.
    pub fn iter(&self, only_expanded: bool) -> NodeIterator<'_, BackendT> {
        NodeIterator::new(self, only_expanded)
    }

    /// Get node at path.
    pub fn at_path(&self, mut path: NodePath) -> Option<&Node<BackendT>> {
        path.pop_front().and_then(|index| self.0.get(index)).and_then(|node| node.at_path(path))
    }

    /// Get node at path.
    pub fn at_path_mut(&mut self, mut path: NodePath) -> Option<&mut Node<BackendT>> {
        path.pop_front().and_then(|index| self.0.get_mut(index)).and_then(|node| node.at_path_mut(path))
    }

    /// Fill path to node.
    ///
    /// Returns true if found.
    pub fn fill_path(&self, path: &mut NodePath, node: &Node<BackendT>) -> bool {
        if self.0.is_empty() {
            return false;
        }

        for (index, node_) in self.0.iter().enumerate() {
            path.push_back(index);
            if ptr::eq(node, node_) {
                return true;
            } else if node_.fill_path(path, node) {
                return true;
            } else {
                path.pop_back();
            }
        }

        false
    }

    /// Add a node.
    pub fn add<IdT, LabelT>(&mut self, depth: usize, kind: NodeKind, id: IdT, label: LabelT)
    where
        IdT: Into<BackendT::ID>,
        LabelT: Into<SpannedString<Style>>,
    {
        self.0.push(Node::new(depth, kind, id, label));
    }

    /// Insert a node.
    pub fn insert<IdT, LabelT>(&mut self, index: usize, depth: usize, kind: NodeKind, id: IdT, label: LabelT)
    where
        IdT: Into<BackendT::ID>,
        LabelT: Into<SpannedString<Style>>,
    {
        self.0.insert(index, Node::new(depth, kind, id, label));
    }

    /// Expand branch nodes.
    ///
    /// If depth is [None] will expand all depths.
    ///
    /// If depth is 0 will do nothing.
    ///
    /// Note that this *will* populate expanded nodes from the backend.
    pub fn expand(&mut self, mut depth: Option<usize>, context: BackendT::Context) -> Result<(), BackendT::Error>
    where
        BackendT::Context: Clone,
    {
        if depth.is_zero() {
            return Ok(());
        }

        depth.decrease();
        if !depth.is_zero() {
            for node in self {
                node.expand(depth, context.clone())?;
            }
        }

        Ok(())
    }

    /// Collapse branch nodes.
    ///
    /// If depth is [None] will collapse all depths.
    ///
    /// If depth is 0 will do nothing.
    pub fn collapse(&mut self, mut depth: Option<usize>) {
        if depth.is_zero() {
            return;
        }

        depth.decrease();
        if !depth.is_zero() {
            for node in self {
                node.collapse(depth);
            }
        }
    }
}

impl<BackendT> Default for NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    fn default() -> Self {
        Self(Default::default())
    }
}

impl<'this, BackendT> IntoIterator for &'this NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    type Item = &'this Node<BackendT>;
    type IntoIter = Iter<'this, Node<BackendT>>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl<'this, BackendT> IntoIterator for &'this mut NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    type Item = &'this mut Node<BackendT>;
    type IntoIter = IterMut<'this, Node<BackendT>>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

impl<BackendT> FromIterator<Node<BackendT>> for NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    fn from_iter<IteratorT>(iterator: IteratorT) -> Self
    where
        IteratorT: IntoIterator<Item = Node<BackendT>>,
    {
        Self(Vec::from_iter(iterator))
    }
}

impl<BackendT> From<Vec<Node<BackendT>>> for NodeList<BackendT>
where
    BackendT: TreeBackend,
{
    fn from(vector: Vec<Node<BackendT>>) -> Self {
        Self(vector)
    }
}