1use crate::app::{Application, CommandType, Error, Mode};
2use crate::flattree::{FlatTreeBuilder, FlatTreeState};
3use crate::node::{Node, NodeData, Priority, wrap_text};
4use crate::store::{Store, StoreReader};
5use crate::ui::tree::SelRetention;
6
7pub trait Actions {
8 fn enter_command_mode(&mut self, cmd: CommandType);
9 fn add_child(&mut self) -> Result<(), Error>;
10 fn delete(&mut self) -> Result<(), Error>;
11 fn rename(&mut self) -> Result<(), Error>;
12 fn set_priority(&mut self, priority: Priority) -> Result<(), Error>;
13 fn set_due_date(&mut self) -> Result<(), Error>;
14 fn unset_due_date(&mut self) -> Result<(), Error>;
15 fn move_into(&mut self) -> Result<(), Error>;
16 fn move_out(&mut self) -> Result<(), Error>;
17 fn cancel(&mut self);
18 fn resize(&mut self, width: u16, height: u16) -> Result<(), Error>;
19}
20
21impl Actions for Application {
22 fn enter_command_mode(&mut self, cmd: CommandType) {
23 self.mode = Mode::Command(cmd);
24 let title = match cmd {
25 CommandType::AddChild => "add: ",
26 CommandType::Rename => "rename: ",
27 CommandType::SetDueDate => "due date: ",
28 };
29 self.status_view.set_title(title);
30 }
31
32 fn add_child(&mut self) -> Result<(), Error> {
33 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
34
35 let name = self.status_view.get_command();
36 let data = bincode::serialize(&NodeData::with_name(name))?;
37
38 let mut writer = self.store.writer()?;
39 writer.add_child(sel_node.id, &data)?;
40 writer.commit()?;
41
42 let height = self.screen.tree_height().into();
43 let width = self.screen.tree_width().into();
44 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
45 self.tree_view.reset(flattree, SelRetention::Stay);
46
47 self.cancel();
48 Ok(())
49 }
50
51 fn delete(&mut self) -> Result<(), Error> {
52 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
53 if self.tree_view.is_root_selected() { return Ok(()) }
54
55 let mut writer = self.store.writer()?;
56 writer.delete(sel_node.pid, sel_node.id)?;
57 writer.commit()?;
58
59 let height = self.screen.tree_height().into();
60 let width = self.screen.tree_width().into();
61 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
62 self.tree_view.reset(flattree, SelRetention::MoveUp);
63 Ok(())
64 }
65
66 fn rename(&mut self) -> Result<(), Error> {
67 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
68
69 let reader = self.store.reader()?;
70 let original = bincode::deserialize(reader.read(sel_node.id)?.unwrap())?;
71 drop(reader);
72
73 let name = self.status_view.get_command();
74 let data = bincode::serialize(&NodeData { name: name.into(), ..original })?;
75
76 let mut writer = self.store.writer()?;
77 writer.modify(sel_node.id, &data)?;
78 writer.commit()?;
79
80 let height = self.screen.tree_height().into();
81 let width = self.screen.tree_width().into();
82 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
83 self.tree_view.reset(flattree, SelRetention::SameId);
84
85 self.cancel();
86 Ok(())
87 }
88
89 fn set_priority(&mut self, priority: Priority) -> Result<(), Error> {
90 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
91
92 let reader = self.store.reader()?;
93 let original = bincode::deserialize(reader.read(sel_node.id)?.unwrap())?;
94 drop(reader);
95
96 let data = bincode::serialize(&NodeData { priority, ..original })?;
97
98 let mut writer = self.store.writer()?;
99 writer.modify(sel_node.id, &data)?;
100 writer.commit()?;
101
102 let height = self.screen.tree_height().into();
103 let width = self.screen.tree_width().into();
104 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
105 self.tree_view.reset(flattree, SelRetention::SameId);
106
107 self.cancel();
108 Ok(())
109 }
110
111 fn set_due_date(&mut self) -> Result<(), Error> {
112 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
113
114 let reader = self.store.reader()?;
115 let original = bincode::deserialize(reader.read(sel_node.id)?.unwrap())?;
116 drop(reader);
117
118 let Ok(due_date) = fuzzydate::parse(self.status_view.get_command()) else {
119 return Ok(());
120 };
121 let data = bincode::serialize(&NodeData { due_date: Some(due_date), ..original })?;
122
123 let mut writer = self.store.writer()?;
124 writer.modify(sel_node.id, &data)?;
125 writer.commit()?;
126
127 let height = self.screen.tree_height().into();
128 let width = self.screen.tree_width().into();
129 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
130 self.tree_view.reset(flattree, SelRetention::SameId);
131
132 self.cancel();
133 Ok(())
134 }
135
136 fn unset_due_date(&mut self) -> Result<(), Error> {
137 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
138
139 let reader = self.store.reader()?;
140 let original = bincode::deserialize(reader.read(sel_node.id)?.unwrap())?;
141 drop(reader);
142
143 let data = bincode::serialize(&NodeData { due_date: None, ..original })?;
144
145 let mut writer = self.store.writer()?;
146 writer.modify(sel_node.id, &data)?;
147 writer.commit()?;
148
149 let height = self.screen.tree_height().into();
150 let width = self.screen.tree_width().into();
151 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
152 self.tree_view.reset(flattree, SelRetention::SameId);
153 Ok(())
154 }
155
156 fn move_into(&mut self) -> Result<(), Error> {
157 let Some(sel_node) = self.tree_view.sel_node() else { return Ok(()) };
158
159 if self.tree_view.is_root_selected() { return Ok(()) }
160
161 self.stack.push(self.root_id);
162 self.root_id = sel_node.id;
163
164 let height = self.screen.tree_height().into();
165 let width = self.screen.tree_width().into();
166 let flattree = build_flattree(sel_node.id, &self.store, height, width)?;
167 self.tree_view.reset(flattree, SelRetention::Reset);
168 Ok(())
169 }
170
171 fn move_out(&mut self) -> Result<(), Error> {
172 let Some(root_id) = self.stack.pop() else { return Ok(()) };
173 self.root_id = root_id;
174
175 let height = self.screen.tree_height().into();
176 let width = self.screen.tree_width().into();
177 let flattree = build_flattree(root_id, &self.store, height, width)?;
178 self.tree_view.reset(flattree, SelRetention::Reset);
179 Ok(())
180 }
181
182 fn cancel(&mut self) {
183 self.status_view.clear();
184 self.mode = Mode::Normal;
185 }
186
187 fn resize(&mut self, width: u16, height: u16) -> Result<(), Error> {
188 self.screen.update(width, height);
189 let height = self.screen.tree_height().into();
190 let width = self.screen.tree_width().into();
191 let flattree = build_flattree(self.root_id, &self.store, height, width)?;
192 self.tree_view.reset(flattree, SelRetention::SameId);
193 Ok(())
194 }
195}
196
197pub fn build_flattree(
198 id: u64,
199 store: &Store,
200 height: usize,
201 width: usize,
202) -> Result<Vec<Node<'static>>, Error> {
203 if width == 0 { return Ok(Vec::new()) }
204
205 let reader = store.reader()?;
206 let root_data: NodeData = bincode::deserialize(reader.read(id)?.unwrap())?;
207 let root_splits = wrap_text(&root_data.name, width);
208 if root_splits.len() - 1 > height { return Ok(Vec::new()) }
209 let root = Node { id, pid: id, data: root_data, depth: 0, splits: root_splits };
210 let mut builder = FlatTreeBuilder::new(root, height);
211
212 loop {
213 match builder.step() {
214 FlatTreeState::Build => continue,
215 FlatTreeState::Refill => {
216 for i in builder.fill_range() {
217 builder.fill(get_children(builder.id(i), &reader, builder.depth(i), width)?, i);
218 }
219 builder.finish_fill();
220 }
221 FlatTreeState::Done => return Ok(builder.finish()),
222 }
223 }
224}
225
226fn get_children(
227 pid: u64,
228 reader: &StoreReader,
229 mut depth: usize,
230 width: usize
231) -> Result<Vec<Node<'static>>, Error> {
232 depth += 1;
233 let mut children = Vec::new();
234 for entry in reader.children(pid)? {
235 let (id, data) = entry?;
236 let data: NodeData = bincode::deserialize(data)?;
237 let width = width.saturating_sub(2 * depth);
238 if width == 0 { continue }
239 let splits = wrap_text(&data.name, width);
240 children.push(Node { id, pid, depth, data, splits });
241 }
242 Ok(children)
243}