use std::collections::HashMap;
use std::path::{Path, PathBuf};
use crate::Error;
#[derive(Debug, Clone)]
pub struct TreeNode {
pub path: PathBuf,
pub is_dir: bool,
pub is_expanded: bool,
pub is_loaded: bool,
pub children: Vec<TreeNode>,
pub is_selected: bool,
pub error: Option<Error>,
}
impl TreeNode {
pub(crate) fn new_root(path: PathBuf) -> Self {
Self {
path,
is_dir: true,
is_expanded: false,
is_loaded: false,
children: Vec::new(),
is_selected: false,
error: None,
}
}
pub(crate) fn from_entry(entry: &LoadedEntry) -> Self {
Self {
path: entry.path.clone(),
is_dir: entry.is_dir,
is_expanded: false,
is_loaded: false,
children: Vec::new(),
is_selected: false,
error: None,
}
}
pub(crate) fn find_mut(&mut self, target: &Path) -> Option<&mut TreeNode> {
if self.path == target {
return Some(self);
}
if !target.starts_with(&self.path) {
return None;
}
for child in &mut self.children {
if let Some(hit) = child.find_mut(target) {
return Some(hit);
}
}
None
}
pub(crate) fn clear_selection(&mut self) {
self.is_selected = false;
for child in &mut self.children {
child.clear_selection();
}
}
#[allow(dead_code)]
pub(crate) fn node_count(&self) -> usize {
1 + self.children.iter().map(Self::node_count).sum::<usize>()
}
pub(crate) fn visible_rows(&self) -> Vec<VisibleRow<'_>> {
let mut out = Vec::new();
collect_visible(self, 0, &mut out);
out
}
}
#[derive(Debug)]
pub(crate) struct VisibleRow<'a> {
pub node: &'a TreeNode,
#[allow(dead_code)]
pub depth: u32,
}
fn collect_visible<'a>(node: &'a TreeNode, depth: u32, out: &mut Vec<VisibleRow<'a>>) {
out.push(VisibleRow { node, depth });
if node.is_dir && node.is_expanded && node.is_loaded {
for child in &node.children {
collect_visible(child, depth + 1, out);
}
}
}
#[derive(Debug, Clone)]
pub struct LoadedEntry {
pub path: PathBuf,
pub is_dir: bool,
#[allow(dead_code)]
pub is_symlink: bool,
pub is_hidden: bool,
}
impl LoadedEntry {
pub(crate) fn passes(&self, filter: crate::DirectoryFilter) -> bool {
if filter.skips_hidden() && self.is_hidden {
return false;
}
if filter.skips_files() && !self.is_dir {
return false;
}
true
}
}
#[derive(Debug, Default, Clone)]
pub struct TreeCache {
entries: HashMap<PathBuf, CacheEntry>,
}
#[derive(Debug, Clone)]
pub(crate) struct CacheEntry {
#[allow(dead_code)]
pub generation: u64,
pub raw: Vec<LoadedEntry>,
}
impl TreeCache {
pub(crate) fn put(&mut self, dir: PathBuf, generation: u64, raw: Vec<LoadedEntry>) {
self.entries.insert(dir, CacheEntry { generation, raw });
}
pub(crate) fn get(&self, dir: &Path) -> Option<&CacheEntry> {
self.entries.get(dir)
}
#[allow(dead_code)]
pub(crate) fn clear(&mut self) {
self.entries.clear();
}
}
#[cfg(test)]
mod tests;