tui_tree_widget/
tree_item.rs1use std::collections::HashSet;
2
3use ratatui::text::Text;
4
5#[derive(Debug, Clone)]
37pub struct TreeItem<'text, Identifier> {
38 pub(super) identifier: Identifier,
39 pub(super) text: Text<'text>,
40 pub(super) children: Vec<Self>,
41}
42
43impl<'text, Identifier> TreeItem<'text, Identifier>
44where
45 Identifier: Clone + PartialEq + Eq + core::hash::Hash,
46{
47 #[must_use]
49 pub fn new_leaf<T>(identifier: Identifier, text: T) -> Self
50 where
51 T: Into<Text<'text>>,
52 {
53 Self {
54 identifier,
55 text: text.into(),
56 children: Vec::new(),
57 }
58 }
59
60 pub fn new<T>(identifier: Identifier, text: T, children: Vec<Self>) -> std::io::Result<Self>
66 where
67 T: Into<Text<'text>>,
68 {
69 let identifiers = children
70 .iter()
71 .map(|item| &item.identifier)
72 .collect::<HashSet<_>>();
73 if identifiers.len() != children.len() {
74 return Err(std::io::Error::new(
75 std::io::ErrorKind::AlreadyExists,
76 "The children contain duplicate identifiers",
77 ));
78 }
79
80 Ok(Self {
81 identifier,
82 text: text.into(),
83 children,
84 })
85 }
86
87 #[must_use]
89 pub const fn identifier(&self) -> &Identifier {
90 &self.identifier
91 }
92
93 #[must_use]
94 pub fn children(&self) -> &[Self] {
95 &self.children
96 }
97
98 #[must_use]
100 pub fn child(&self, index: usize) -> Option<&Self> {
101 self.children.get(index)
102 }
103
104 #[must_use]
108 pub fn child_mut(&mut self, index: usize) -> Option<&mut Self> {
109 self.children.get_mut(index)
110 }
111
112 #[must_use]
113 pub fn height(&self) -> usize {
114 self.text.height()
115 }
116
117 pub fn add_child(&mut self, child: Self) -> std::io::Result<()> {
123 let existing = self
124 .children
125 .iter()
126 .map(|item| &item.identifier)
127 .collect::<HashSet<_>>();
128 if existing.contains(&child.identifier) {
129 return Err(std::io::Error::new(
130 std::io::ErrorKind::AlreadyExists,
131 "identifier already exists in the children",
132 ));
133 }
134
135 self.children.push(child);
136 Ok(())
137 }
138}
139
140impl TreeItem<'static, &'static str> {
141 #[cfg(test)]
142 #[must_use]
143 pub(crate) fn example() -> Vec<Self> {
144 vec![
145 Self::new_leaf("a", "Alfa"),
146 Self::new(
147 "b",
148 "Bravo",
149 vec![
150 Self::new_leaf("c", "Charlie"),
151 Self::new(
152 "d",
153 "Delta",
154 vec![Self::new_leaf("e", "Echo"), Self::new_leaf("f", "Foxtrot")],
155 )
156 .expect("all item identifiers are unique"),
157 Self::new_leaf("g", "Golf"),
158 ],
159 )
160 .expect("all item identifiers are unique"),
161 Self::new_leaf("h", "Hotel"),
162 ]
163 }
164}
165
166#[test]
167#[should_panic = "duplicate identifiers"]
168fn tree_item_new_errors_with_duplicate_identifiers() {
169 let item = TreeItem::new_leaf("same", "text");
170 let another = item.clone();
171 TreeItem::new("root", "Root", vec![item, another]).unwrap();
172}
173
174#[test]
175#[should_panic = "identifier already exists"]
176fn tree_item_add_child_errors_with_duplicate_identifiers() {
177 let item = TreeItem::new_leaf("same", "text");
178 let another = item.clone();
179 let mut root = TreeItem::new("root", "Root", vec![item]).unwrap();
180 root.add_child(another).unwrap();
181}