diff --git a/benches/bench.rs b/benches/bench.rs index 47e47c5..ce6660e 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -7,64 +7,59 @@ use ratatui::widgets::StatefulWidget; use managarr_tree_widget::{Tree, TreeItem, TreeState}; #[must_use] -fn example_items() -> Vec> { +fn example_items() -> Vec> { vec![ - TreeItem::new_leaf("a", "Alfa"), + TreeItem::new_leaf( "Alfa"), TreeItem::new( - "b", "Bravo", vec![ - TreeItem::new_leaf("c", "Charlie"), + TreeItem::new_leaf( "Charlie"), TreeItem::new( - "d", "Delta", vec![ - TreeItem::new_leaf("e", "Echo"), - TreeItem::new_leaf("f", "Foxtrot"), + TreeItem::new_leaf( "Echo"), + TreeItem::new_leaf( "Foxtrot"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("g", "Golf"), + TreeItem::new_leaf( "Golf"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("h", "Hotel"), + TreeItem::new_leaf( "Hotel"), TreeItem::new( - "i", "India", vec![ - TreeItem::new_leaf("j", "Juliett"), - TreeItem::new_leaf("k", "Kilo"), - TreeItem::new_leaf("l", "Lima"), - TreeItem::new_leaf("m", "Mike"), - TreeItem::new_leaf("n", "November"), + TreeItem::new_leaf( "Juliet"), + TreeItem::new_leaf("Kilo"), + TreeItem::new_leaf("Lima"), + TreeItem::new_leaf("Mike"), + TreeItem::new_leaf("November"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("o", "Oscar"), + TreeItem::new_leaf( "Oscar"), TreeItem::new( - "p", "Papa", vec![ - TreeItem::new_leaf("q", "Quebec"), - TreeItem::new_leaf("r", "Romeo"), - TreeItem::new_leaf("s", "Sierra"), - TreeItem::new_leaf("t", "Tango"), - TreeItem::new_leaf("u", "Uniform"), + TreeItem::new_leaf( "Quebec"), + TreeItem::new_leaf( "Romeo"), + TreeItem::new_leaf( "Sierra"), + TreeItem::new_leaf( "Tango"), + TreeItem::new_leaf( "Uniform"), TreeItem::new( - "v", "Victor", vec![ - TreeItem::new_leaf("w", "Whiskey"), - TreeItem::new_leaf("x", "Xray"), - TreeItem::new_leaf("y", "Yankee"), + TreeItem::new_leaf("Whiskey"), + TreeItem::new_leaf ("Xray"), + TreeItem::new_leaf( "Yankee"), ], ) .expect("all item identifiers are unique"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("z", "Zulu"), + TreeItem::new_leaf( "Zulu"), ] } @@ -74,7 +69,7 @@ fn init(criterion: &mut Criterion) { group.bench_function("empty", |bencher| { bencher.iter(|| { - let items = Vec::>::new(); + let items = Vec::>::new(); let _ = black_box(Tree::new(black_box(&items))).unwrap(); }); }); @@ -96,7 +91,7 @@ fn renders(criterion: &mut Criterion) { let buffer_size = Rect::new(0, 0, 100, 100); group.bench_function("empty", |bencher| { - let items: Vec> = vec![]; + let items: Vec> = vec![]; let tree = Tree::new(&items).unwrap(); let mut state = TreeState::default(); bencher.iter_batched( @@ -112,8 +107,8 @@ fn renders(criterion: &mut Criterion) { let items = example_items(); let tree = Tree::new(&items).unwrap(); let mut state = TreeState::default(); - state.open(vec!["b"]); - state.open(vec!["b", "d"]); + state.open(vec![2]); + state.open(vec![2, 4]); bencher.iter_batched( || (tree.clone(), Buffer::empty(buffer_size)), |(tree, mut buffer)| { diff --git a/examples/example.rs b/examples/example.rs index 45bb5ad..2218a7c 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -11,8 +11,8 @@ use managarr_tree_widget::{Tree, TreeItem, TreeState}; #[must_use] struct App { - state: TreeState<&'static str>, - items: Vec>, + state: TreeState, + items: Vec>, } impl App { @@ -20,62 +20,57 @@ impl App { Self { state: TreeState::default(), items: vec![ - TreeItem::new_leaf("a", "Alfa"), + TreeItem::new_leaf( "Alfa"), TreeItem::new( - "b", "Bravo", vec![ - TreeItem::new_leaf("c", "Charlie"), + TreeItem::new_leaf( "Charlie"), TreeItem::new( - "d", "Delta", vec![ - TreeItem::new_leaf("e", "Echo"), - TreeItem::new_leaf("f", "Foxtrot"), + TreeItem::new_leaf("Echo"), + TreeItem::new_leaf( "Foxtrot"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("g", "Golf"), + TreeItem::new_leaf( "Golf"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("h", "Hotel"), + TreeItem::new_leaf("Hotel"), TreeItem::new( - "i", "India", vec![ - TreeItem::new_leaf("j", "Juliett"), - TreeItem::new_leaf("k", "Kilo"), - TreeItem::new_leaf("l", "Lima"), - TreeItem::new_leaf("m", "Mike"), - TreeItem::new_leaf("n", "November"), + TreeItem::new_leaf( "Juliet"), + TreeItem::new_leaf( "Kilo"), + TreeItem::new_leaf( "Lima"), + TreeItem::new_leaf( "Mike"), + TreeItem::new_leaf( "November"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("o", "Oscar"), + TreeItem::new_leaf( "Oscar"), TreeItem::new( - "p", "Papa", vec![ - TreeItem::new_leaf("q", "Quebec"), - TreeItem::new_leaf("r", "Romeo"), - TreeItem::new_leaf("s", "Sierra"), - TreeItem::new_leaf("t", "Tango"), - TreeItem::new_leaf("u", "Uniform"), + TreeItem::new_leaf( "Quebec"), + TreeItem::new_leaf( "Romeo"), + TreeItem::new_leaf( "Sierra"), + TreeItem::new_leaf( "Tango"), + TreeItem::new_leaf( "Uniform"), TreeItem::new( - "v", "Victor", vec![ - TreeItem::new_leaf("w", "Whiskey"), - TreeItem::new_leaf("x", "Xray"), - TreeItem::new_leaf("y", "Yankee"), + TreeItem::new_leaf( "Whiskey"), + TreeItem::new_leaf( "Xray"), + TreeItem::new_leaf( "Yankee"), ], ) .expect("all item identifiers are unique"), ], ) .expect("all item identifiers are unique"), - TreeItem::new_leaf("z", "Zulu"), + TreeItem::new_leaf( "Zulu"), ], } } diff --git a/src/flatten.rs b/src/flatten.rs index 077c067..2f99aba 100644 --- a/src/flatten.rs +++ b/src/flatten.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; - +use std::fmt::Display; +use std::hash::Hash; use crate::tree_item::TreeItem; use ratatui::text::ToText; @@ -7,19 +8,17 @@ use ratatui::text::ToText; /// /// Generated via [`TreeState::flatten`](crate::TreeState::flatten). #[must_use] -pub struct Flattened<'a, Identifier, T> +pub struct Flattened<'a, T> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { - pub identifier: Vec, - pub item: &'a TreeItem, + pub identifier: Vec, + pub item: &'a TreeItem, } -impl<'a, Identifier, T> Flattened<'a, Identifier, T> +impl<'a, T> Flattened<'a, T> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { /// Zero based depth. Depth 0 means top level with 0 indentation. #[must_use] @@ -32,19 +31,18 @@ where /// /// `current` starts empty: `&[]` #[must_use] -pub fn flatten<'a, Identifier, T>( - open_identifiers: &HashSet>, - items: &'a [TreeItem], - current: &[Identifier], -) -> Vec> +pub fn flatten<'a, T>( + open_identifiers: &HashSet>, + items: &'a [TreeItem], + current: &[u64], +) -> Vec> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { let mut result = Vec::new(); for item in items { let mut child_identifier = current.to_vec(); - child_identifier.push(item.identifier.clone()); + child_identifier.push(item.identifier); let child_result = open_identifiers .contains(&child_identifier) @@ -64,9 +62,15 @@ where #[test] fn depth_works() { + use std::hash::{DefaultHasher, Hash, Hasher}; let mut open = HashSet::new(); - open.insert(vec!["b"]); - open.insert(vec!["b", "d"]); + let hash = |s: &str| { + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() + }; + open.insert(vec![hash("Bravo")]); + open.insert(vec![hash("Bravo"), hash("Delta")]); let depths = flatten(&open, &TreeItem::example(), &[]) .into_iter() .map(|flattened| flattened.depth()) @@ -75,7 +79,7 @@ fn depth_works() { } #[cfg(test)] -fn flatten_works(open: &HashSet>, expected: &[&str]) { +fn flatten_works(open: &HashSet>, expected: &[u64]) { let items = TreeItem::example(); let result = flatten(open, &items, &[]); let actual = result @@ -87,29 +91,53 @@ fn flatten_works(open: &HashSet>, expected: &[&str]) { #[test] fn flatten_nothing_open_is_top_level() { + use std::hash::{DefaultHasher, Hash, Hasher}; let open = HashSet::new(); - flatten_works(&open, &["a", "b", "h"]); + let hash = |s: &str| { + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() + }; + flatten_works(&open, &[hash("Alfa"), hash("Bravo"), hash("Hotel")]); } #[test] fn flatten_wrong_open_is_only_top_level() { + use std::hash::{DefaultHasher, Hash, Hasher}; let mut open = HashSet::new(); - open.insert(vec!["a"]); - open.insert(vec!["b", "d"]); - flatten_works(&open, &["a", "b", "h"]); + let hash = |s: &str| { + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() + }; + open.insert(vec![hash("Alfa")]); + open.insert(vec![hash("Bravo"), hash("Delta")]); + flatten_works(&open, &[hash("Alfa"), hash("Bravo"), hash("Hotel")]); } #[test] fn flatten_one_is_open() { + use std::hash::{DefaultHasher, Hash, Hasher}; let mut open = HashSet::new(); - open.insert(vec!["b"]); - flatten_works(&open, &["a", "b", "c", "d", "g", "h"]); + let hash = |s: &str| { + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() + }; + open.insert(vec![hash("Bravo")]); + flatten_works(&open, &[hash("Alfa"), hash("Bravo"), hash("Charlie"), hash("Delta"), hash("Golf"), hash("Hotel")]); } #[test] fn flatten_all_open() { + use std::hash::{DefaultHasher, Hash, Hasher}; let mut open = HashSet::new(); - open.insert(vec!["b"]); - open.insert(vec!["b", "d"]); - flatten_works(&open, &["a", "b", "c", "d", "e", "f", "g", "h"]); + let hash = |s: &str| { + let mut hasher = DefaultHasher::new(); + s.hash(&mut hasher); + hasher.finish() + }; + open.insert(vec![hash("Bravo")]); + open.insert(vec![hash("Bravo"), hash("Delta")]); + flatten_works(&open, &[hash("Alfa"), hash("Bravo"), hash("Charlie"), hash("Delta"), hash("Echo"), hash("Foxtrot"), hash("Golf"), hash("Hotel")]); } diff --git a/src/lib.rs b/src/lib.rs index cb48920..edecc73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,8 @@ The user interaction state (like the current selection) is stored in the [`TreeS */ use std::collections::HashSet; - +use std::fmt::Display; +use std::hash::Hash; use ratatui::buffer::Buffer; use ratatui::layout::Rect; use ratatui::style::Style; @@ -24,9 +25,6 @@ mod tree_state; /// A `Tree` which can be rendered. /// -/// The generic argument `Identifier` is used to keep the state like the currently selected or opened [`TreeItem`]s in the [`TreeState`]. -/// For more information see [`TreeItem`]. -/// /// # Example /// /// ``` @@ -37,7 +35,7 @@ mod tree_state; /// # let mut terminal = Terminal::new(TestBackend::new(32, 32)).unwrap(); /// let mut state = TreeState::default(); /// -/// let item = TreeItem::new_leaf("l", "leaf"); +/// let item = TreeItem::new_leaf("leaf"); /// let items = vec![item]; /// /// terminal.draw(|frame| { @@ -53,12 +51,11 @@ mod tree_state; /// ``` #[must_use] #[derive(Debug, Clone)] -pub struct Tree<'a, Identifier, T> +pub struct Tree<'a, T> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { - items: &'a [TreeItem], + items: &'a [TreeItem], block: Option>, scrollbar: Option>, @@ -78,17 +75,16 @@ where node_no_children_symbol: &'a str, } -impl<'a, Identifier, T> Tree<'a, Identifier, T> +impl<'a, T> Tree<'a, T> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { /// Create a new `Tree`. /// /// # Errors /// /// Errors when there are duplicate identifiers in the children. - pub fn new(items: &'a [TreeItem]) -> std::io::Result { + pub fn new(items: &'a [TreeItem]) -> std::io::Result { let identifiers = items .iter() .map(|item| &item.identifier) @@ -163,18 +159,17 @@ where #[test] #[should_panic = "duplicate identifiers"] fn tree_new_errors_with_duplicate_identifiers() { - let item = TreeItem::new_leaf("same".to_owned(), "text".to_owned()); + let item = TreeItem::new_leaf("text".to_owned()); let another = item.clone(); let items = [item, another]; let _ = Tree::new(&items).unwrap(); } -impl<'a, Identifier, T> StatefulWidget for Tree<'a, Identifier, T> +impl<'a, T> StatefulWidget for Tree<'a, T> where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { - type State = TreeState; + type State = TreeState; #[allow(clippy::too_many_lines)] fn render(self, full_area: Rect, buf: &mut Buffer, state: &mut Self::State) { @@ -339,10 +334,9 @@ where } } -impl<'a, Identifier, T> Widget for Tree<'a, Identifier, T> +impl<'a, T> Widget for Tree<'a, T> where - Identifier: Clone + Default + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { fn render(self, area: Rect, buf: &mut Buffer) { let mut state = TreeState::default(); @@ -352,11 +346,12 @@ where #[cfg(test)] mod render_tests { + use std::hash::{DefaultHasher, Hasher}; use super::*; #[must_use] #[track_caller] - fn render(width: u16, height: u16, state: &mut TreeState<&'static str>) -> Buffer { + fn render(width: u16, height: u16, state: &mut TreeState) -> Buffer { let items = TreeItem::example(); let tree = Tree::new(&items).unwrap(); let area = Rect::new(0, 0, width, height); @@ -389,7 +384,9 @@ mod render_tests { #[test] fn depth_one() { let mut state = TreeState::default(); - state.open(vec!["b"]); + let mut hasher = DefaultHasher::new(); + "Bravo".hash(&mut hasher); + state.open(vec![hasher.finish()]); let buffer = render(13, 7, &mut state); let expected = Buffer::with_lines([ " Alfa ", @@ -406,8 +403,13 @@ mod render_tests { #[test] fn depth_two() { let mut state = TreeState::default(); - state.open(vec!["b"]); - state.open(vec!["b", "d"]); + let mut hasher = DefaultHasher::new(); + "Bravo".hash(&mut hasher); + let bravo_hash = hasher.finish(); + let mut hasher = DefaultHasher::new(); + "Delta".hash(&mut hasher); + state.open(vec![bravo_hash]); + state.open(vec![bravo_hash, hasher.finish()]); let buffer = render(15, 9, &mut state); let expected = Buffer::with_lines([ " Alfa ", diff --git a/src/tree_item.rs b/src/tree_item.rs index bb16daf..4d7ee1a 100644 --- a/src/tree_item.rs +++ b/src/tree_item.rs @@ -1,14 +1,15 @@ use std::collections::HashSet; - +use std::fmt::Display; +use std::hash::{DefaultHasher, Hash, Hasher}; use ratatui::text::ToText; /// One item inside a [`Tree`](crate::Tree). /// /// Can have zero or more `children`. /// -/// # Identifier +/// # identifier /// -/// The generic argument `Identifier` is used to keep the state like the currently selected or opened [`TreeItem`]s in the [`TreeState`](crate::TreeState). +/// The `identifier` is used to keep the state like the currently selected or opened [`TreeItem`]s in the [`TreeState`](crate::TreeState). /// /// It needs to be unique among its siblings but can be used again on parent or child [`TreeItem`]s. /// A common example would be a filename which has to be unique in its directory while it can exist in another. @@ -29,42 +30,30 @@ use ratatui::text::ToText; /// /// ``` /// # use managarr_tree_widget::TreeItem; -/// let a = TreeItem::new_leaf("l", "Leaf"); -/// let b = TreeItem::new("r", "Root", vec![a])?; +/// let a = TreeItem::new_leaf("Leaf"); +/// let b = TreeItem::new("Root", vec![a])?; /// # Ok::<(), std::io::Error>(()) /// ``` #[derive(Debug, Clone)] -pub struct TreeItem +pub struct TreeItem where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { - pub(super) identifier: Identifier, + pub(super) identifier: u64, pub(super) content: T, pub(super) children: Vec, } -impl TreeItem +impl TreeItem where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { - /// Create a new `TreeItem` without children. - #[must_use] - pub const fn new_leaf(identifier: Identifier, content: T) -> Self { - Self { - identifier, - content, - children: Vec::new(), - } - } - /// Create a new `TreeItem` with children. /// /// # Errors /// /// Errors when there are duplicate identifiers in the children. - pub fn new(identifier: Identifier, content: T, children: Vec) -> std::io::Result { + pub fn new(content: T, children: Vec) -> std::io::Result { let identifiers = children .iter() .map(|item| &item.identifier) @@ -76,17 +65,33 @@ where )); } + let mut hasher = DefaultHasher::new(); + content.hash(&mut hasher); + Ok(Self { - identifier, + identifier: hasher.finish(), content, children, }) } + /// Create a new `TreeItem` without children. + #[must_use] + pub fn new_leaf(content: T) -> Self { + let mut hasher = DefaultHasher::new(); + content.hash(&mut hasher); + + Self { + identifier: hasher.finish(), + content, + children: Vec::new(), + } + } + /// Get a reference to the identifier. #[must_use] - pub const fn identifier(&self) -> &Identifier { - &self.identifier + pub const fn identifier(&self) -> u64 { + self.identifier } /// Get a reference to the text. @@ -142,31 +147,29 @@ where } } -impl TreeItem<&'static str, &'static str> { +impl TreeItem<&'static str> { #[cfg(test)] #[must_use] pub(crate) fn example() -> Vec { vec![ - Self::new_leaf("a", "Alfa"), + Self::new_leaf("Alfa"), Self::new( - "b", "Bravo", vec![ - Self::new_leaf("c", "Charlie"), + Self::new_leaf("Charlie"), Self::new( - "d", "Delta", vec![ - Self::new_leaf("e", "Echo"), - Self::new_leaf("f", "Foxtrot"), + Self::new_leaf("Echo"), + Self::new_leaf( "Foxtrot"), ], ) .expect("all item identifiers are unique"), - Self::new_leaf("g", "Golf"), + Self::new_leaf("Golf"), ], ) .expect("all item identifiers are unique"), - Self::new_leaf("h", "Hotel"), + Self::new_leaf( "Hotel"), ] } } @@ -174,16 +177,16 @@ impl TreeItem<&'static str, &'static str> { #[test] #[should_panic = "duplicate identifiers"] fn tree_item_new_errors_with_duplicate_identifiers() { - let item = TreeItem::new_leaf("same", "text"); + let item = TreeItem::new_leaf( "text"); let another = item.clone(); - TreeItem::new("root", "Root", vec![item, another]).unwrap(); + TreeItem::new("Root", vec![item, another]).unwrap(); } #[test] #[should_panic = "identifier already exists"] fn tree_item_add_child_errors_with_duplicate_identifiers() { - let item = TreeItem::new_leaf("same", "text"); + let item = TreeItem::new_leaf("text"); let another = item.clone(); - let mut root = TreeItem::new("root", "Root", vec![item]).unwrap(); + let mut root = TreeItem::new( "Root", vec![item]).unwrap(); root.add_child(another).unwrap(); } diff --git a/src/tree_state.rs b/src/tree_state.rs index 224975b..0bb27b5 100644 --- a/src/tree_state.rs +++ b/src/tree_state.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; - +use std::fmt::Display; +use std::hash::Hash; use ratatui::layout::{Position, Rect}; use ratatui::text::ToText; @@ -8,37 +9,30 @@ use crate::tree_item::TreeItem; /// Keeps the state of what is currently selected and what was opened in a [`Tree`](crate::Tree). /// -/// The generic argument `Identifier` is used to keep the state like the currently selected or opened [`TreeItem`]s in the [`TreeState`]. -/// For more information see [`TreeItem`]. -/// /// # Example /// /// ``` /// # use managarr_tree_widget::TreeState; -/// type Identifier = usize; /// -/// let mut state = TreeState::::default(); +/// let mut state = TreeState::default(); /// ``` #[must_use] #[derive(Debug, Default)] -pub struct TreeState { +pub struct TreeState { pub(super) offset: usize, - pub(super) opened: HashSet>, - pub(super) selected: Vec, + pub(super) opened: HashSet>, + pub(super) selected: Vec, pub(super) ensure_selected_in_view_on_next_render: bool, pub(super) last_area: Rect, pub(super) last_biggest_index: usize, /// All identifiers open on last render - pub(super) last_identifiers: Vec>, + pub(super) last_identifiers: Vec>, /// Identifier rendered at `y` on last render - pub(super) last_rendered_identifiers: Vec<(u16, Vec)>, + pub(super) last_rendered_identifiers: Vec<(u16, Vec)>, } -impl TreeState -where - Identifier: Clone + PartialEq + Eq + core::hash::Hash, -{ +impl TreeState { #[must_use] pub const fn get_offset(&self) -> usize { self.offset @@ -46,17 +40,17 @@ where #[must_use] #[deprecated = "Use self.opened()"] - pub fn get_all_opened(&self) -> Vec> { + pub fn get_all_opened(&self) -> Vec> { self.opened.iter().cloned().collect() } #[must_use] - pub const fn opened(&self) -> &HashSet> { + pub const fn opened(&self) -> &HashSet> { &self.opened } #[must_use] - pub fn selected(&self) -> &[Identifier] { + pub fn selected(&self) -> &[u64] { &self.selected } @@ -64,10 +58,10 @@ where #[must_use] pub fn flatten<'a, T>( &self, - items: &'a [TreeItem], - ) -> Vec> + items: &'a [TreeItem], + ) -> Vec> where - T: ToText + Clone + Default, + T: ToText + Clone + Default + Display + Hash, { flatten(&self.opened, items, &[]) } @@ -80,10 +74,10 @@ where /// /// ```rust /// # use managarr_tree_widget::TreeState; - /// # let mut state = TreeState::::default(); + /// # let mut state = TreeState::default(); /// state.select(Vec::new()); /// ``` - pub fn select(&mut self, identifier: Vec) -> bool { + pub fn select(&mut self, identifier: Vec) -> bool { self.ensure_selected_in_view_on_next_render = true; let changed = self.selected != identifier; self.selected = identifier; @@ -93,7 +87,7 @@ where /// Open a tree node. /// Returns `true` when it was closed and has been opened. /// Returns `false` when it was already open. - pub fn open(&mut self, identifier: Vec) -> bool { + pub fn open(&mut self, identifier: Vec) -> bool { if identifier.is_empty() { false } else { @@ -104,7 +98,7 @@ where /// Close a tree node. /// Returns `true` when it was open and has been closed. /// Returns `false` when it was already closed. - pub fn close(&mut self, identifier: &[Identifier]) -> bool { + pub fn close(&mut self, identifier: &[u64]) -> bool { self.opened.remove(identifier) } @@ -113,7 +107,7 @@ where /// /// Returns `true` when a node is opened / closed. /// As toggle always changes something, this only returns `false` when an empty identifier is given. - pub fn toggle(&mut self, identifier: Vec) -> bool { + pub fn toggle(&mut self, identifier: Vec) -> bool { if identifier.is_empty() { false } else if self.opened.contains(&identifier) { @@ -196,8 +190,7 @@ where /// /// ``` /// # use managarr_tree_widget::TreeState; - /// # type Identifier = usize; - /// # let mut state = TreeState::::default(); + /// # let mut state = TreeState::default(); /// // Move the selection one down /// state.select_relative(|current| { /// // When nothing is currently selected, select index 0 @@ -231,8 +224,7 @@ where /// /// ``` /// # use managarr_tree_widget::TreeState; - /// # type Identifier = usize; - /// # let mut state = TreeState::::default(); + /// # let mut state = TreeState::default(); /// // Move the selection one down /// state.select_relative(|current| { /// // When nothing is currently selected, select index 0 @@ -259,7 +251,7 @@ where /// Get the identifier that was rendered for the given position on last render. #[must_use] - pub fn rendered_at(&self, position: Position) -> Option<&[Identifier]> { + pub fn rendered_at(&self, position: Position) -> Option<&[u64]> { if !self.last_area.contains(position) { return None; }