1use super::Node;
6
7#[derive(Default, Clone)]
9pub struct TreeState {
10 open: Vec<String>,
12 selected: Option<String>,
14}
15
16impl TreeState {
17 pub fn is_open<V>(&self, node: &Node<V>) -> bool {
19 self.open.contains(node.id())
20 }
21
22 pub fn is_closed<V>(&self, node: &Node<V>) -> bool {
24 !self.is_open(node)
25 }
26
27 pub fn selected(&self) -> Option<&str> {
29 self.selected.as_deref()
30 }
31
32 pub fn is_selected<V>(&self, node: &Node<V>) -> bool {
34 self.selected
35 .as_ref()
36 .map(|x| x == node.id())
37 .unwrap_or(false)
38 }
39
40 pub fn first_sibling<'a, V>(&self, tree: &'a Node<V>) -> Option<&'a Node<V>> {
42 let selected = self.selected.as_ref()?;
43 let parent = tree.parent(selected)?;
44 parent.iter().next()
45 }
46
47 pub fn last_sibling<'a, V>(&self, tree: &'a Node<V>) -> Option<&'a Node<V>> {
49 let selected = self.selected.as_ref()?;
50 let parent = tree.parent(selected)?;
51 parent.iter().last()
52 }
53
54 pub fn tree_changed<V>(&mut self, root: &Node<V>, preserve: bool) {
56 if preserve {
57 self.selected = self
59 .selected
60 .take()
61 .map(|selected| root.query(&selected).unwrap_or(root).id().to_string());
62 self.open.retain(|x| root.query(x).is_some());
64 } else {
65 self.open = Vec::new();
67 self.selected = Some(root.id().to_string());
68 }
69 }
70
71 pub fn open<V>(&mut self, root: &Node<V>) {
73 if let Some(selected) = self.selected.as_ref() {
74 if let Some(node) = root.query(selected) {
75 self.open_node(root, node);
76 }
77 }
78 }
79
80 pub fn close<V>(&mut self, root: &Node<V>) {
83 if let Some(selected) = self.selected.as_ref() {
84 if let Some(node) = root.query(selected) {
85 if self.is_open(node) {
86 self.close_node(node);
87 }
88 }
89 }
90 }
91
92 pub fn move_down<V>(&mut self, root: &Node<V>) {
94 if let Some(selected) = self.selected.take() {
95 if let Some(node) = root.query(&selected) {
97 if !node.is_leaf() && self.is_open(node) {
99 self.selected = Some(node.iter().next().unwrap().id().to_string());
101 } else {
102 if let Some(sibling) = self.next_sibling(root, node) {
104 self.selected = Some(sibling.id().to_string());
105 } else {
106 let mut current = &selected;
109 loop {
110 if let Some(parent) = root.parent(current) {
111 current = parent.id();
112 if let Some(sibling) = self.next_sibling(root, parent) {
113 self.selected = Some(sibling.id().to_string());
114 break;
115 }
116 } else {
117 self.selected = Some(selected);
119 break;
120 }
121 }
122 }
123 }
124 }
125 }
126 }
127
128 pub fn move_up<V>(&mut self, root: &Node<V>) {
130 if let Some(selected) = self.selected.take() {
131 if let Some(parent) = root.parent(&selected) {
133 self.selected = Some(
135 self.previous_sibling(root, root.query(&selected).unwrap())
136 .map(|x| self.get_last_open_heir(x))
137 .unwrap_or(parent)
138 .id()
139 .to_string(),
140 );
141 } else {
142 self.selected = Some(selected);
144 }
145 }
146 }
147
148 pub fn select<V>(&mut self, root: &Node<V>, node: &Node<V>) {
151 self.open_ancestors(root, node);
152 self.selected = Some(node.id().to_string());
153 }
154
155 fn close_node<V>(&mut self, node: &Node<V>) {
157 self.open.retain(|x| x != node.id());
159 self.close_children(node);
161 }
162
163 fn open_node<V>(&mut self, root: &Node<V>, node: &Node<V>) {
167 if !node.is_leaf() && self.is_closed(node) {
168 self.open.push(node.id().to_string());
169 }
170 self.open_ancestors(root, node);
171 }
172
173 fn close_children<V>(&mut self, node: &Node<V>) {
175 node.iter().for_each(|x| self.close_node(x));
176 }
177
178 fn open_ancestors<V>(&mut self, root: &Node<V>, node: &Node<V>) {
180 if let Some(parent) = root.parent(node.id()) {
181 self.open_node(root, parent);
182 }
183 }
184
185 fn previous_sibling<'a, V>(
187 &mut self,
188 root: &'a Node<V>,
189 node: &'a Node<V>,
190 ) -> Option<&'a Node<V>> {
191 let parent = root.parent(node.id())?;
192 let mut prev_node = None;
193 for child in parent.iter() {
194 if child.id() == node.id() {
195 break;
196 }
197 prev_node = Some(child);
198 }
199 prev_node
200 }
201
202 fn next_sibling<'a, V>(&mut self, root: &'a Node<V>, node: &'a Node<V>) -> Option<&'a Node<V>> {
204 let parent = root.parent(node.id())?;
205 let mut keep_next = false;
206 for child in parent.iter() {
207 if keep_next {
208 return Some(child);
210 } else if child.id() == node.id() {
211 keep_next = true;
213 }
214 }
215 None
217 }
218
219 fn get_last_open_heir<'a, V>(&self, node: &'a Node<V>) -> &'a Node<V> {
221 if self.is_open(node) {
222 self.get_last_open_heir(node.iter().last().unwrap())
224 } else {
225 node
227 }
228 }
229
230 #[cfg(test)]
231 pub fn force_open(&mut self, open: &[&str]) {
233 self.open = open.iter().map(|x| x.to_string()).collect();
234 }
235}
236
237#[cfg(test)]
238mod test {
239
240 use pretty_assertions::assert_eq;
241
242 use super::*;
243 use crate::mock::mock_tree;
244
245 #[test]
246 fn should_initialize_tree_state() {
247 let state = TreeState::default();
248 assert!(state.open.is_empty());
249 assert!(state.selected().is_none());
250 }
251
252 #[test]
253 fn should_select_nodes() {
254 let mut state = TreeState::default();
255 let tree = mock_tree();
256 state.select(tree.root(), tree.root().query(&String::from("bA")).unwrap());
258 assert_eq!(state.selected().unwrap(), "bA");
259 assert_eq!(state.open.len(), 2);
261 assert!(state.is_open(tree.root().query(&String::from("b")).unwrap()));
262 assert!(state.is_open(tree.root()));
263 }
264
265 #[test]
266 fn should_open_and_close_nodes() {
267 let mut state = TreeState::default();
268 let tree = mock_tree();
269 let ba = tree.root().query(&String::from("bA")).unwrap();
271 state.select(tree.root(), ba);
272 state.open(tree.root());
274 assert!(state.is_open(ba));
275 assert!(state.is_open(tree.root().query(&String::from("b")).unwrap()));
277 assert!(state.is_open(tree.root()));
278 assert_eq!(state.open.len(), 3);
279 let ba0 = tree.root().query(&String::from("bA0")).unwrap();
281 state.select(tree.root(), ba0);
282 state.open(tree.root());
283 assert!(state.is_open(ba0));
284 assert_eq!(state.open.len(), 4);
285 let b = tree.root().query(&String::from("b")).unwrap();
287 state.select(tree.root(), b);
288 state.close(tree.root());
289 assert!(state.is_closed(b));
290 assert!(state.is_closed(ba));
292 assert!(state.is_closed(ba0));
293 assert!(state.is_open(tree.root()));
295 }
296
297 #[test]
298 fn should_not_open_twice() {
299 let mut state = TreeState::default();
300 let tree = mock_tree();
301 state.select(tree.root(), tree.root());
303 state.open(tree.root());
304 assert_eq!(state.open.len(), 1);
305 assert!(state.is_open(tree.root()));
306 state.open(tree.root());
308 assert_eq!(state.open.len(), 1);
309 assert!(state.is_open(tree.root()));
310 }
311
312 #[test]
313 fn should_find_previous_sibling() {
314 let mut state = TreeState::default();
315 let tree = mock_tree();
316 let bb4 = tree.root().query(&String::from("bB4")).unwrap();
317 let bb3 = tree.root().query(&String::from("bB3")).unwrap();
319 assert_eq!(state.previous_sibling(tree.root(), bb4).unwrap(), bb3);
320 let bb0 = tree.root().query(&String::from("bB0")).unwrap();
322 assert!(state.previous_sibling(tree.root(), bb0).is_none());
323 }
324
325 #[test]
326 fn should_find_next_sibling() {
327 let mut state = TreeState::default();
328 let tree = mock_tree();
329 let bb4 = tree.root().query(&String::from("bB4")).unwrap();
330 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
332 assert_eq!(state.next_sibling(tree.root(), bb4).unwrap(), bb5);
333 assert!(state.next_sibling(tree.root(), bb5).is_none());
335 }
336
337 #[test]
338 fn should_find_first_sibling() {
339 let mut state = TreeState::default();
340 let tree = mock_tree();
341 let bb4 = tree.root().query(&String::from("bB4")).unwrap();
342 state.select(tree.root(), bb4);
343 let bb0 = tree.root().query(&String::from("bB0")).unwrap();
345 assert_eq!(state.first_sibling(tree.root()).unwrap(), bb0);
346 state.select(tree.root(), tree.root());
348 assert!(state.first_sibling(tree.root()).is_none());
349 }
350
351 #[test]
352 fn should_find_last_sibling() {
353 let mut state = TreeState::default();
354 let tree = mock_tree();
355 let bb2 = tree.root().query(&String::from("bB2")).unwrap();
356 state.select(tree.root(), bb2);
357 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
359 assert_eq!(state.last_sibling(tree.root()).unwrap(), bb5);
360 state.select(tree.root(), tree.root());
362 assert!(state.last_sibling(tree.root()).is_none());
363 }
364
365 #[test]
366 fn should_preserve_tree_state() {
367 let mut state = TreeState::default();
368 let tree = mock_tree();
369 let ca = tree.root().query(&String::from("cA")).unwrap();
371 state.select(tree.root(), ca);
372 state.open(tree.root());
373 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
374 state.select(tree.root(), bb5);
375 state.tree_changed(tree.root(), true);
377 assert_eq!(state.open.len(), 5);
379 assert!(state.is_open(ca));
380 assert_eq!(state.selected().unwrap(), "bB5");
381 }
382
383 #[test]
384 fn should_not_preserve_tree_state() {
385 let mut state = TreeState::default();
386 let mut tree = mock_tree();
387 let ca = tree.root().query(&String::from("cA")).unwrap();
389 state.select(tree.root(), ca);
390 state.open(tree.root());
391 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
392 state.select(tree.root(), bb5);
393 tree.root_mut()
395 .query_mut(&String::from("b"))
396 .unwrap()
397 .remove_child(&String::from("bB"));
398 tree.root_mut().remove_child(&String::from("c"));
399 state.tree_changed(tree.root(), true);
401 assert_eq!(state.selected().unwrap(), "/");
403 assert_eq!(state.open.len(), 2);
405 assert_eq!(state.open, vec![String::from("/"), String::from("b")]);
406 assert!(state.is_open(tree.root()));
407 }
408
409 #[test]
410 fn should_reinitialize_tree_state() {
411 let mut state = TreeState::default();
412 let tree = mock_tree();
413 let ca = tree.root().query(&String::from("cA")).unwrap();
415 state.select(tree.root(), ca);
416 state.open(tree.root());
417 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
418 state.select(tree.root(), bb5);
419 state.tree_changed(tree.root(), false);
421 assert!(state.open.is_empty());
423 assert_eq!(state.selected().unwrap(), "/");
424 }
425
426 #[test]
427 fn should_move_cursor_down_on_sibling() {
428 let mut state = TreeState::default();
429 let tree = mock_tree();
430 let bb3 = tree.root().query(&String::from("bB3")).unwrap();
432 state.select(tree.root(), bb3);
433 state.move_down(tree.root());
435 assert_eq!(state.selected().unwrap(), "bB4");
436 state.move_down(tree.root());
438 assert_eq!(state.selected().unwrap(), "bB5");
439 }
440
441 #[test]
442 fn should_move_cursor_down_to_next_lower_node_if_last_child() {
443 let mut state = TreeState::default();
444 let tree = mock_tree();
445 let bb5 = tree.root().query(&String::from("bB5")).unwrap();
447 state.select(tree.root(), bb5);
448 state.move_down(tree.root());
450 assert_eq!(state.selected().unwrap(), "c");
451 }
452
453 #[test]
454 fn should_move_cursor_down_to_child_if_parent_is_open() {
455 let mut state = TreeState::default();
456 let tree = mock_tree();
457 let b = tree.root().query(&String::from("b")).unwrap();
459 state.select(tree.root(), b);
460 state.open(tree.root());
462 state.move_down(tree.root());
464 assert_eq!(state.selected().unwrap(), "bA");
465 state.open(tree.root());
467 state.move_down(tree.root());
469 assert_eq!(state.selected().unwrap(), "bA0");
470 }
471
472 #[test]
473 fn should_move_cursor_down_to_next_sibling_if_node_is_closed() {
474 let mut state = TreeState::default();
475 let tree = mock_tree();
476 let aa = tree.root().query(&String::from("aA")).unwrap();
478 state.select(tree.root(), aa);
479 state.move_down(tree.root());
481 assert_eq!(state.selected().unwrap(), "aB");
482 state.move_down(tree.root());
484 assert_eq!(state.selected().unwrap(), "aC");
485 }
486
487 #[test]
488 fn should_not_move_cursor_down_if_root_is_closed() {
489 let mut state = TreeState::default();
490 let tree = mock_tree();
491 state.select(tree.root(), tree.root());
492 state.move_down(tree.root());
494 assert_eq!(state.selected().unwrap(), "/");
495 }
496
497 #[test]
498 fn should_not_move_cursor_down_if_last_element_is_selected() {
499 let mut state = TreeState::default();
500 let tree = mock_tree();
501 let ca2 = tree.root().query(&String::from("cA2")).unwrap();
502 state.select(tree.root(), ca2);
503 state.move_down(tree.root());
505 assert_eq!(state.selected().unwrap(), "cA2");
506 }
507
508 #[test]
509 fn should_move_cursor_up_on_sibling() {
510 let mut state = TreeState::default();
511 let tree = mock_tree();
512 let bb4 = tree.root().query(&String::from("bB4")).unwrap();
514 state.select(tree.root(), bb4);
515 state.move_up(tree.root());
517 assert_eq!(state.selected().unwrap(), "bB3");
518 state.move_up(tree.root());
520 assert_eq!(state.selected().unwrap(), "bB2");
521 }
522
523 #[test]
524 fn should_move_cursor_up_on_deepest_child_of_previous_sibling() {
525 let mut state = TreeState::default();
526 let tree = mock_tree();
527 state.select(tree.root(), tree.root().query(&String::from("bB")).unwrap());
529 state.open(tree.root());
530 state.select(tree.root(), tree.root().query(&String::from("c")).unwrap());
532 state.move_up(tree.root());
534 assert_eq!(state.selected().unwrap(), "bB5");
535 }
536
537 #[test]
538 fn should_move_cursor_up_to_parent_if_first_child() {
539 let mut state = TreeState::default();
540 let tree = mock_tree();
541 state.select(
543 tree.root(),
544 tree.root().query(&String::from("bB0")).unwrap(),
545 );
546 state.move_up(tree.root());
548 assert_eq!(state.selected().unwrap(), "bB");
549 state.move_up(tree.root());
551 assert_eq!(state.selected().unwrap(), "bA");
552 state.move_up(tree.root());
554 assert_eq!(state.selected().unwrap(), "b");
555 }
556
557 #[test]
558 fn should_not_move_cursor_up_if_root_is_selected() {
559 let mut state = TreeState::default();
560 let tree = mock_tree();
561 state.select(tree.root(), tree.root());
562 state.move_up(tree.root());
564 assert_eq!(state.selected().unwrap(), "/");
565 }
566
567 #[test]
568 fn should_get_last_open_heir() {
569 let mut state = TreeState::default();
570 let tree = mock_tree();
571 state.select(tree.root(), tree.root().query(&String::from("aA")).unwrap());
573 state.open(tree.root());
574 state.select(tree.root(), tree.root().query(&String::from("aB")).unwrap());
575 state.open(tree.root());
576 state.select(tree.root(), tree.root().query(&String::from("aC")).unwrap());
577 state.open(tree.root());
578 state.select(tree.root(), tree.root().query(&String::from("bB")).unwrap());
580 state.open(tree.root());
581 assert_eq!(
583 state
584 .get_last_open_heir(tree.root().query(&String::from("bB")).unwrap())
585 .id()
586 .as_str(),
587 "bB5"
588 );
589 assert_eq!(
591 state
592 .get_last_open_heir(tree.root().query(&String::from("a")).unwrap())
593 .id()
594 .as_str(),
595 "aC0"
596 );
597 }
598}