diff --git a/src/flatten.rs b/src/flatten.rs index 959afed..6896e88 100644 --- a/src/flatten.rs +++ b/src/flatten.rs @@ -1,8 +1,10 @@ +use std::collections::HashSet; + use crate::TreeItem; /// A flattened item of all visible [`TreeItem`s](TreeItem). /// -/// Generated via [`flatten`]. +/// Generated via [`TreeState::flatten`](crate::TreeState::flatten). pub struct Flattened<'a, Identifier> { pub identifier: Vec, pub item: &'a TreeItem<'a, Identifier>, @@ -18,26 +20,25 @@ impl<'a, Identifier> Flattened<'a, Identifier> { /// Get a flat list of all visible [`TreeItem`s](TreeItem). #[must_use] pub fn flatten<'a, Identifier>( - opened: &[Vec], + opened: &HashSet>, items: &'a [TreeItem<'a, Identifier>], ) -> Vec> where - Identifier: Clone + PartialEq, + Identifier: Clone + PartialEq + Eq + core::hash::Hash, { internal(opened, items, &[]) } #[must_use] fn internal<'a, Identifier>( - opened: &[Vec], + opened: &HashSet>, items: &'a [TreeItem<'a, Identifier>], current: &[Identifier], ) -> Vec> where - Identifier: Clone + PartialEq, + Identifier: Clone + PartialEq + Eq + core::hash::Hash, { let mut result = Vec::new(); - for item in items { let mut child_identifier = current.to_vec(); child_identifier.push(item.identifier.clone()); @@ -52,7 +53,6 @@ where result.append(&mut child_result); } } - result } @@ -85,7 +85,8 @@ fn get_example_tree_items() -> Vec> { #[test] fn get_opened_nothing_opened_is_top_level() { let items = get_example_tree_items(); - let result = flatten(&[], &items); + let opened = HashSet::new(); + let result = flatten(&opened, &items); let result_text = result.iter().map(|o| o.item.identifier).collect::>(); assert_eq!(result_text, ["a", "b", "h"]); } @@ -93,7 +94,9 @@ fn get_opened_nothing_opened_is_top_level() { #[test] fn get_opened_wrong_opened_is_only_top_level() { let items = get_example_tree_items(); - let opened = [vec!["a"], vec!["b", "d"]]; + let mut opened = HashSet::new(); + opened.insert(vec!["a"]); + opened.insert(vec!["b", "d"]); let result = flatten(&opened, &items); let result_text = result.iter().map(|o| o.item.identifier).collect::>(); assert_eq!(result_text, ["a", "b", "h"]); @@ -102,7 +105,8 @@ fn get_opened_wrong_opened_is_only_top_level() { #[test] fn get_opened_one_is_opened() { let items = get_example_tree_items(); - let opened = [vec!["b"]]; + let mut opened = HashSet::new(); + opened.insert(vec!["b"]); let result = flatten(&opened, &items); let result_text = result.iter().map(|o| o.item.identifier).collect::>(); assert_eq!(result_text, ["a", "b", "c", "d", "g", "h"]); @@ -111,7 +115,9 @@ fn get_opened_one_is_opened() { #[test] fn get_opened_all_opened() { let items = get_example_tree_items(); - let opened = [vec!["b"], vec!["b", "d"]]; + let mut opened = HashSet::new(); + opened.insert(vec!["b"]); + opened.insert(vec!["b", "d"]); let result = flatten(&opened, &items); let result_text = result.iter().map(|o| o.item.identifier).collect::>(); assert_eq!(result_text, ["a", "b", "c", "d", "e", "f", "g", "h"]); diff --git a/src/lib.rs b/src/lib.rs index dfe7ba9..37fbab4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,8 @@ use unicode_width::UnicodeWidthStr; mod flatten; mod identifier; -pub use crate::flatten::{flatten, Flattened}; +use crate::flatten::flatten; +pub use crate::flatten::Flattened; pub use crate::identifier::get_without_leaf as get_identifier_without_leaf; /// Keeps the state of what is currently selected and what was opened in a [`Tree`]. @@ -56,6 +57,15 @@ where self.opened.iter().cloned().collect() } + /// Get a flat list of all visible [`TreeItem`s](TreeItem) with this `TreeState`. + #[must_use] + pub fn flatten<'a>( + &self, + items: &'a [TreeItem<'a, Identifier>], + ) -> Vec> { + flatten(&self.opened, items) + } + #[must_use] pub fn selected(&self) -> Vec { self.selected.clone() @@ -119,7 +129,7 @@ where /// Select the last visible node. pub fn select_last(&mut self, items: &[TreeItem]) { - let visible = flatten(&self.get_all_opened(), items); + let visible = self.flatten(items); let new_identifier = visible .last() .map(|o| o.identifier.clone()) @@ -138,7 +148,7 @@ where new_index: usize, ) -> bool { let current_identifier = self.selected(); - let visible = flatten(&self.get_all_opened(), items); + let visible = self.flatten(items); let new_index = new_index.min(visible.len().saturating_sub(1)); let new_identifier = visible .get(new_index) @@ -172,7 +182,7 @@ where where F: FnOnce(Option) -> usize, { - let visible = flatten(&self.get_all_opened(), items); + let visible = self.flatten(items); let current_identifier = self.selected(); let current_index = visible .iter() @@ -540,7 +550,7 @@ where return; } - let visible = flatten(&state.get_all_opened(), &self.items); + let visible = state.flatten(&self.items); if visible.is_empty() { return; }