cursive_tree/view/
view.rs1use super::{
2 super::{backend::*, model::*},
3 actions::*,
4 tree::*,
5};
6
7use cursive::{direction::*, event::*, theme::*, view::*, *};
8
9const TYPE_NAME: &str = "TreeView";
10
11impl<BackendT> View for TreeView<BackendT>
12where
13 BackendT: 'static + TreeBackend + Send + Sync,
14 BackendT::Context: Clone + Send + Sync,
15 BackendT::Error: Send + Sync,
16 BackendT::ID: Send + Sync,
17 BackendT::Data: Send + Sync,
18{
19 fn type_name(&self) -> &'static str {
20 TYPE_NAME
21 }
22
23 fn take_focus(&mut self, _source: Direction) -> Result<EventResult, CannotFocus> {
24 if self.model.is_empty() { Err(CannotFocus) } else { Ok(EventResult::consumed()) }
25 }
26
27 fn required_size(&mut self, _constraint: Vec2) -> Vec2 {
28 self.model.extents()
29 }
30
31 fn important_area(&self, view_size: Vec2) -> Rect {
32 if let Some(selected_row) = self.selected_row {
33 Rect::from_size((0, selected_row), (view_size.x, 1))
34 } else {
35 Rect::from_size((0, 0), view_size)
36 }
37 }
38
39 fn on_event(&mut self, event: Event) -> EventResult {
40 let selected_row = self.selected_row;
41
42 match self.actions.get(&event) {
43 Some(action) => match action {
44 Action::SelectTop => self.select_top(),
45 Action::SelectUp => self.move_selection(-1),
46 Action::SelectUpPage => self.move_selection(-(self.page as isize)),
47 Action::SelectBottom => self.select_bottom(),
48 Action::SelectDown => self.move_selection(1),
49 Action::SelectDownPage => self.move_selection(self.page as isize),
50
51 Action::Expand => {
52 let context = self.model.context.clone();
53 if let Some(node) = self.selected_node_mut() {
54 return Self::on_expand_branch(node, Some(1), context);
55 }
56 }
57
58 Action::ExpandRecursive => {
59 let context = self.model.context.clone();
60 if let Some(node) = self.selected_node_mut() {
61 return Self::on_expand_branch(node, None, context);
62 }
63 }
64
65 Action::ExpandAll => {
66 self.selected_row = None; return self.on_expand_all();
68 }
69
70 Action::Collapse => {
71 if let Some(node) = self.selected_node_mut() {
72 node.collapse(Some(1));
73 }
74 }
75
76 Action::CollapseRecursive => {
77 if let Some(node) = self.selected_node_mut() {
78 node.collapse(None);
79 }
80 }
81
82 Action::CollapseAll => {
83 self.selected_row = None; self.model.collapse(None);
85 }
86
87 Action::ToggleState => {
88 let context = self.model.context.clone();
89 if let Some(node) = self.selected_node_mut() {
90 return Self::on_toggle_branch_state(node, context);
91 }
92 }
93 },
94
95 None => {
96 match event {
97 Event::Mouse { offset, position, event: MouseEvent::Press(_) } => {
98 self.selected_row = if let Some(position) = position.checked_sub(offset)
99 && let Some(node) = self.model.at_row(position.y)
100 {
101 if node.kind.is_branch() && (position.x < node.depth * 2 + 2) {
102 let context = self.model.context.clone();
104 if let Some(path) = self.model.path(node)
105 && let Some(node) = self.model.at_path_mut(path)
106 {
107 return Self::on_toggle_branch_state(node, context);
108 } else {
109 None
110 }
111 } else {
112 Some(position.y)
114 }
115 } else {
116 None
117 };
118 }
119
120 _ => return EventResult::Ignored,
121 }
122 }
123 }
124
125 EventResult::Consumed(if self.selected_row != selected_row {
126 Some(Callback::from_fn_once(BackendT::handle_selection_changed))
128 } else {
129 None
130 })
131 }
132
133 fn draw(&self, printer: &Printer) {
134 let mut start = Vec2::default();
135 for node in self.model.iter(true) {
136 if start.y >= printer.offset.y + printer.size.y {
137 break;
139 }
140
141 if start.y >= printer.content_offset.y {
143 start.x = node.depth * 2;
146 match node.symbol(self.model.context.clone()) {
147 Symbol::Representation(symbol) => printer.print_styled(start, &symbol),
148 Symbol::String(symbol) => printer.print(start, symbol),
149 };
150 start.x += 2;
151
152 let mut representation = &node.representation;
155
156 let debug_representation = if self.debug
157 && let Some(path) = self.model.path(node)
158 {
159 let path: Vec<_> = path.into_iter().map(|i| i.to_string()).collect();
160 let mut representation = representation.clone();
161 representation.append(format!(" {}", path.join(".")));
162 Some(representation)
163 } else {
164 None
165 };
166
167 if let Some(debug_representation) = &debug_representation {
168 representation = debug_representation;
169 }
170
171 let highlight = if self.is_selected(start.y) {
172 Some(if printer.focused { PaletteStyle::Highlight } else { PaletteStyle::HighlightInactive })
173 } else {
174 None
175 };
176
177 let print = |printer: &Printer| printer.print_styled(start, representation);
178
179 match highlight {
180 Some(highlight) => printer.with_style(highlight, print),
181 None => print(printer),
182 }
183 }
184
185 start.y += node.representation_size.y;
186 }
187 }
188}