tui_treelistview/state/
marks.rs1use std::hash::Hash;
2
3use crate::context::TreeMarkState;
4use crate::model::TreeModel;
5use crate::traversal::TreePostorder;
6
7use super::TreeListViewState;
8
9impl<Id: Copy + Eq + Hash> TreeListViewState<Id> {
10 pub fn ensure_mark_states<T: TreeModel<Id = Id>>(&mut self, model: &T) {
12 let stamp = (model.revision(), self.manual_marked.revision());
13 if self.mark_stamp == Some(stamp) {
14 return;
15 }
16
17 self.mark_states.clear();
18 for node in TreePostorder::forest(model) {
19 let mark = if self.manual_marked.contains(&node.id) {
20 TreeMarkState::Marked
21 } else {
22 let children = node.children;
23 if children.is_empty() {
24 TreeMarkState::Unmarked
25 } else {
26 let mut any = false;
27 let mut all = true;
28 for child in children {
29 let child_mark = self.mark_states.get(child).copied().unwrap_or_default();
30 any |= child_mark != TreeMarkState::Unmarked;
31 all &= child_mark == TreeMarkState::Marked;
32 }
33 if all {
34 TreeMarkState::Marked
35 } else if any {
36 TreeMarkState::Partial
37 } else {
38 TreeMarkState::Unmarked
39 }
40 }
41 };
42 if mark != TreeMarkState::Unmarked {
43 self.mark_states.insert(node.id, mark);
44 }
45 }
46
47 for id in self.manual_marked.iter().copied() {
48 self.mark_states.insert(id, TreeMarkState::Marked);
49 }
50 self.mark_stamp = Some(stamp);
51 }
52
53 #[must_use]
55 pub fn mark_state(&self, id: Id) -> TreeMarkState {
56 self.mark_state_cached(id)
57 }
58
59 #[must_use]
60 pub fn is_manually_marked(&self, id: Id) -> bool {
61 self.manual_marked.contains(&id)
62 }
63
64 pub fn set_marked(&mut self, id: Id, marked: bool) -> bool {
66 self.manual_marked.set_membership(id, marked)
67 }
68
69 pub fn toggle_marked(&mut self, id: Id) -> bool {
71 let marked = !self.manual_marked.contains(&id);
72 self.set_marked(id, marked)
73 }
74
75 pub fn clear_marks(&mut self) -> bool {
77 self.manual_marked.clear()
78 }
79
80 pub fn manual_marked_ids(&self) -> impl Iterator<Item = Id> + '_ {
81 self.manual_marked.iter().copied()
82 }
83}