1use crate::checklist::{Checklist, ChecklistItem, ChecklistItems, Path};
2use cursive::{traits::*, views::NamedView, Cursive};
3use cursive_tree_view::{Placement, TreeView};
4
5pub type ChecklistTree = TreeView<ChecklistItem>;
6
7pub struct Tree {
8 current: Path,
9 checklist: Checklist,
10}
11
12fn collapse_func(siv: &mut Cursive, row: usize, is_collapsed: bool, children: usize) {
13 if !is_collapsed && children == 0 {
14 siv.call_on_name("tree", move |tree: &mut ChecklistTree| {
15 tree_insert(
16 tree,
17 tree.borrow_item(row).unwrap().items().to_vec(),
18 row,
19 Placement::LastChild,
20 );
21 });
22 }
23}
24
25fn tree_insert(tv: &mut ChecklistTree, items: ChecklistItems, parent: usize, placement: Placement) {
26 for item in items {
27 if item.items().is_empty() {
28 tv.insert_item(item.clone(), placement, parent);
29 } else {
30 if let Some(id) = tv.insert_container_item(item.clone(), placement, parent) {
31 tv.expand_item(id);
32
33 tree_insert(
34 tv,
35 tv.borrow_item(id).unwrap().items().to_vec(),
36 id,
37 Placement::LastChild,
38 );
39
40 tv.collapse_item(id);
41 }
42 }
43 }
44}
45
46impl Tree {
47 pub fn new(checklist: Checklist) -> Self {
48 Tree {
49 current: Path::default(),
50 checklist,
51 }
52 }
53
54 pub fn title(&self) -> String {
55 self.checklist.title.clone()
56 }
57
58 pub fn next_path(&self) -> Path {
59 let mut path = self.current_path();
60 while let Some(idx) = path.pop() {
61 if let Some(item) = self.checklist.path(path.clone()) {
62 if item.items().len() - 1 > idx {
63 path.push(idx + 1);
64 return path;
65 }
66 }
67 }
68
69 return Path::default();
70 }
71
72 pub fn last_path(&self) -> Path {
73 let mut path = self.current_path();
74 while let Some(idx) = path.pop() {
75 if let Some(item) = self.checklist.path(path.clone()) {
76 if idx > 0 && !item.items().is_empty() {
77 path.push(idx - 1);
78 return path;
79 }
80 }
81 }
82
83 return Path::default();
84 }
85
86 pub fn move_item(&mut self, _from: Path, _to: Path) {}
87 pub fn delete_item(&mut self, _path: Path) {}
88
89 pub fn set_current(&mut self, path: Path) {
90 self.current = path;
91 }
92
93 pub fn current_path(&self) -> Path {
94 self.current.clone()
95 }
96
97 pub fn current_item(&self) -> ChecklistItem {
98 self.checklist.path(self.current.clone()).unwrap()
99 }
100
101 pub fn as_treeview(&self) -> NamedView<ChecklistTree> {
102 let mut tv = ChecklistTree::new();
103 tree_insert(&mut tv, self.checklist.items.to_vec(), 0, Placement::After);
104 tv.set_on_collapse(collapse_func);
105 tv.with_name("tree")
106 }
107}