pull/10/head
Takayuki Maeda 3 years ago
parent 68d4053e5c
commit c1f493a287

@ -38,7 +38,7 @@ impl DatabaseTreeItems {
Ok(items)
}
/// how many individual items (files/paths) are in the list
/// how many individual items are in the list
pub fn len(&self) -> usize {
self.tree_items.len()
}
@ -49,29 +49,25 @@ impl DatabaseTreeItems {
}
fn push_databases<'a>(
item_path: &'a Database,
database: &'a Database,
nodes: &mut Vec<DatabaseTreeItem>,
// helps to only add new nodes for paths that were not added before
// we also count the number of children a node has for later folding
items_added: &mut HashMap<String, usize>,
collapsed: &BTreeSet<&String>,
) -> Result<()> {
let c = item_path.name.clone();
let c = database.name.clone();
if !items_added.contains_key(&c) {
// add node and set count to have no children
items_added.insert(c.clone(), 0);
// increase the number of children in the parent node count
*items_added.entry(item_path.name.clone()).or_insert(0) += 1;
*items_added.entry(database.name.clone()).or_insert(0) += 1;
//TODO: make non alloc
let path_string = c;
let is_collapsed = collapsed.contains(&path_string);
nodes.push(DatabaseTreeItem::new_database(item_path, is_collapsed)?);
let is_collapsed = collapsed.contains(&c);
nodes.push(DatabaseTreeItem::new_database(database, is_collapsed)?);
}
// increase child count in parent node (the above ancenstor ignores the leaf component)
*items_added.entry(item_path.name.clone()).or_insert(0) += 1;
*items_added.entry(database.name.clone()).or_insert(0) += 1;
Ok(())
}
@ -80,7 +76,7 @@ impl DatabaseTreeItems {
if self.tree_items[index].kind().is_database() {
self.tree_items[index].collapse_database();
let path = self.tree_items[index].info().full_path_str().to_string();
let name = self.tree_items[index].kind().name();
for i in index + 1..self.tree_items.len() {
let item = &mut self.tree_items[i];
@ -90,7 +86,7 @@ impl DatabaseTreeItems {
}
if let Some(db) = item.kind().database_name() {
if db == path {
if db == name {
item.hide();
}
} else {
@ -104,14 +100,14 @@ impl DatabaseTreeItems {
if self.tree_items[index].kind().is_database() {
self.tree_items[index].expand_database();
let full_path = self.tree_items[index].info().full_path_str().to_string();
let name = self.tree_items[index].kind().name();
if recursive {
for i in index + 1..self.tree_items.len() {
let item = &mut self.tree_items[i];
if let Some(db) = item.kind().database_name() {
if *db != full_path {
if *db != name {
break;
}
}
@ -122,18 +118,17 @@ impl DatabaseTreeItems {
}
}
self.update_visibility(&Some(full_path), index + 1, false);
self.update_visibility(&Some(name), index + 1, false);
}
}
fn update_visibility(&mut self, prefix: &Option<String>, start_idx: usize, set_defaults: bool) {
// if we are in any subpath that is collapsed we keep skipping over it
let mut inner_collapsed: Option<String> = None;
for i in start_idx..self.tree_items.len() {
if let Some(ref collapsed_path) = inner_collapsed {
if let Some(ref collapsed_item) = inner_collapsed {
if let Some(db) = self.tree_items[i].kind().database_name().clone() {
if db == *collapsed_path {
if db == *collapsed_item {
if set_defaults {
self.tree_items[i].info_mut().set_visible(false);
}
@ -146,7 +141,6 @@ impl DatabaseTreeItems {
let item_kind = self.tree_items[i].kind().clone();
if matches!(item_kind, DatabaseTreeItemKind::Database{ collapsed, .. } if collapsed) {
// we encountered an inner path that is still collapsed
inner_collapsed = item_kind.database_name().clone();
}

@ -3,9 +3,6 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("InvalidPath: `{0}`")]
InvalidPath(PathBuf),
#[error("TryFromInt error:{0}")]
IntConversion(#[from] TryFromIntError),
}

@ -1,28 +1,18 @@
use crate::error::Result;
use crate::{Database, Table};
use std::{convert::TryFrom, path::PathBuf};
use std::convert::TryFrom;
/// holds the information shared among all `DatabaseTreeItem` in a `FileTree`
#[derive(Debug, Clone)]
pub struct TreeItemInfo {
/// indent level
indent: u8,
/// currently visible depending on the folder collapse states
visible: bool,
/// contains this paths last component and folded up paths added to it
/// if this is `None` nothing was folding into here
folded: Option<PathBuf>,
/// the full path
pub full_path: String,
}
impl TreeItemInfo {
pub const fn new(indent: u8, full_path: String) -> Self {
pub const fn new(indent: u8) -> Self {
Self {
indent,
visible: true,
folded: None,
full_path,
}
}
@ -30,17 +20,6 @@ impl TreeItemInfo {
self.visible
}
pub fn full_path_str(&self) -> &str {
self.full_path.as_str()
}
pub fn path_str(&self) -> &str {
match self.full_path.split('/').collect::<Vec<_>>().get(1) {
Some(path) => path,
None => self.full_path.as_str(),
}
}
pub const fn indent(&self) -> u8 {
self.indent
}
@ -77,6 +56,13 @@ impl DatabaseTreeItemKind {
}
}
pub fn name(&self) -> String {
match self {
Self::Database { name, .. } => name.to_string(),
Self::Table { table, .. } => table.name.clone(),
}
}
pub fn database_name(&self) -> Option<String> {
match self {
Self::Database { .. } => None,
@ -97,7 +83,7 @@ impl DatabaseTreeItem {
let indent = u8::try_from((3_usize).saturating_sub(2))?;
Ok(Self {
info: TreeItemInfo::new(indent, table.name.clone()),
info: TreeItemInfo::new(indent),
kind: DatabaseTreeItemKind::Table {
database: database.name.clone(),
table: table.clone(),
@ -107,7 +93,7 @@ impl DatabaseTreeItem {
pub fn new_database(database: &Database, collapsed: bool) -> Result<Self> {
Ok(Self {
info: TreeItemInfo::new(0, database.name.to_string()),
info: TreeItemInfo::new(0),
kind: DatabaseTreeItemKind::Database {
name: database.name.to_string(),
collapsed,
@ -115,14 +101,6 @@ impl DatabaseTreeItem {
})
}
pub fn fold(&mut self, next: Self) {
if let Some(folded) = self.info.folded.as_mut() {
*folded = folded.join(&next.info.full_path);
}
self.info.full_path = next.info.full_path
}
pub const fn info(&self) -> &TreeItemInfo {
&self.info
}
@ -162,18 +140,24 @@ impl Eq for DatabaseTreeItem {}
impl PartialEq for DatabaseTreeItem {
fn eq(&self, other: &Self) -> bool {
self.info.full_path.eq(&other.info.full_path)
if self.kind.is_database() && other.kind().is_database() {
return self.kind.name().eq(&other.kind.name());
}
if !self.kind.is_database() && !other.kind.is_database() {
return self.kind.name().eq(&other.kind.name());
}
false
}
}
impl PartialOrd for DatabaseTreeItem {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.info.full_path.partial_cmp(&other.info.full_path)
self.kind.name().partial_cmp(&other.kind.name())
}
}
impl Ord for DatabaseTreeItem {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.info.full_path.cmp(&other.info.full_path)
self.kind.name().cmp(&other.kind.name())
}
}

@ -39,7 +39,7 @@ impl DatabasesComponent {
}
fn tree_item_to_span(item: &DatabaseTreeItem, selected: bool, width: u16) -> Span<'_> {
let path = item.info().full_path.to_string();
let name = item.kind().name();
let indent = item.info().indent();
let indent_str = if indent == 0 {
@ -59,15 +59,15 @@ impl DatabasesComponent {
EMPTY_STR
};
let path = format!(
let name = format!(
"{}{}{:w$}",
indent_str,
path_arrow,
path,
name,
w = width as usize
);
Span::styled(
path,
name,
if selected {
Style::default().fg(Color::Magenta).bg(Color::Green)
} else {

Loading…
Cancel
Save