rat_ftable2/selection/
rowsetselection.rs1use crate::TableSelection;
2use crate::event::TableOutcome;
3use crate::table::TableState;
4use rat_event::{HandleEvent, MouseOnly, Regular, ct_event, flow};
5use rat_focus::HasFocus;
6use rat_ftable::selection::RowSetSelection;
7use rat_scrolled::ScrollAreaState;
8use rat_scrolled::event::ScrollOutcome;
9use ratatui_crossterm::crossterm::event::{Event, KeyModifiers};
10use std::cmp::max;
11
12impl HandleEvent<Event, Regular, TableOutcome> for TableState<RowSetSelection> {
13 fn handle(&mut self, event: &Event, _: Regular) -> TableOutcome {
14 let res = if self.is_focused() {
15 match event {
16 ct_event!(keycode press Up) => {
17 if self.move_up(1, false) {
18 TableOutcome::Selected
19 } else {
20 TableOutcome::Unchanged
21 }
22 }
23 ct_event!(keycode press Down) => {
24 if self.move_down(1, false) {
25 TableOutcome::Selected
26 } else {
27 TableOutcome::Unchanged
28 }
29 }
30 ct_event!(keycode press CONTROL-Up)
31 | ct_event!(keycode press CONTROL-Home)
32 | ct_event!(keycode press Home) => {
33 if self.move_to(0, false) {
34 TableOutcome::Selected
35 } else {
36 TableOutcome::Unchanged
37 }
38 }
39 ct_event!(keycode press CONTROL-Down)
40 | ct_event!(keycode press CONTROL-End)
41 | ct_event!(keycode press End) => {
42 if self.move_to(self.rows.saturating_sub(1), false) {
43 TableOutcome::Selected
44 } else {
45 TableOutcome::Unchanged
46 }
47 }
48 ct_event!(keycode press PageUp) => {
49 if self.move_up(max(1, self.page_len().saturating_sub(1)), false) {
50 TableOutcome::Selected
51 } else {
52 TableOutcome::Unchanged
53 }
54 }
55 ct_event!(keycode press PageDown) => {
56 if self.move_down(max(1, self.page_len().saturating_sub(1)), false) {
57 TableOutcome::Selected
58 } else {
59 TableOutcome::Unchanged
60 }
61 }
62 ct_event!(keycode press SHIFT-Up) => {
63 if self.move_up(1, true) {
64 TableOutcome::Selected
65 } else {
66 TableOutcome::Unchanged
67 }
68 }
69 ct_event!(keycode press SHIFT-Down) => {
70 if self.move_down(1, true) {
71 TableOutcome::Selected
72 } else {
73 TableOutcome::Unchanged
74 }
75 }
76 ct_event!(keycode press CONTROL_SHIFT-Up)
77 | ct_event!(keycode press CONTROL_SHIFT-Home)
78 | ct_event!(keycode press SHIFT-Home) => {
79 if self.move_to(0, true) {
80 TableOutcome::Selected
81 } else {
82 TableOutcome::Unchanged
83 }
84 }
85 ct_event!(keycode press CONTROL_SHIFT-Down)
86 | ct_event!(keycode press CONTROL_SHIFT-End)
87 | ct_event!(keycode press SHIFT-End) => {
88 if self.move_to(self.rows.saturating_sub(1), true) {
89 TableOutcome::Selected
90 } else {
91 TableOutcome::Unchanged
92 }
93 }
94 ct_event!(keycode press SHIFT-PageUp) => {
95 if self.move_up(max(1, self.page_len().saturating_sub(1)), true) {
96 TableOutcome::Selected
97 } else {
98 TableOutcome::Unchanged
99 }
100 }
101 ct_event!(keycode press SHIFT-PageDown) => {
102 if self.move_down(max(1, self.page_len().saturating_sub(1)), true) {
103 TableOutcome::Selected
104 } else {
105 TableOutcome::Unchanged
106 }
107 }
108 ct_event!(keycode press Left) => {
109 if self.scroll_left(1) {
110 TableOutcome::Changed
111 } else {
112 TableOutcome::Unchanged
113 }
114 }
115 ct_event!(keycode press Right) => {
116 if self.scroll_right(1) {
117 TableOutcome::Changed
118 } else {
119 TableOutcome::Unchanged
120 }
121 }
122 ct_event!(keycode press CONTROL-Left) => {
123 if self.scroll_to_x(0) {
124 TableOutcome::Changed
125 } else {
126 TableOutcome::Unchanged
127 }
128 }
129 ct_event!(keycode press CONTROL-Right) => {
130 if self.scroll_to_x(self.x_max_offset()) {
131 TableOutcome::Changed
132 } else {
133 TableOutcome::Unchanged
134 }
135 }
136 _ => TableOutcome::Continue,
137 }
138 } else {
139 TableOutcome::Continue
140 };
141
142 if res == TableOutcome::Continue {
143 self.handle(event, MouseOnly)
144 } else {
145 res
146 }
147 }
148}
149
150impl HandleEvent<Event, MouseOnly, TableOutcome> for TableState<RowSetSelection> {
151 fn handle(&mut self, event: &Event, _: MouseOnly) -> TableOutcome {
152 if self.is_obscured() {
153 return TableOutcome::Continue;
154 }
155
156 flow!(match event {
157 ct_event!(mouse any for m) | ct_event!(mouse any CONTROL for m)
158 if self.mouse.drag(self.table_area, m)
159 || self.mouse.drag2(self.table_area, m, KeyModifiers::CONTROL) =>
160 {
161 if self.move_to(self.row_at_drag((m.column, m.row)), true) {
162 TableOutcome::Selected
163 } else {
164 TableOutcome::Unchanged
165 }
166 }
167 ct_event!(mouse down Left for column, row) => {
168 let pos = (*column, *row);
169 if self.table_area.contains(pos.into()) {
170 if let Some(new_row) = self.row_at_clicked(pos) {
171 if self.move_to(new_row, false) {
172 TableOutcome::Selected
173 } else {
174 TableOutcome::Unchanged
175 }
176 } else {
177 TableOutcome::Continue
178 }
179 } else if self.header_area.contains((*column, *row).into()) {
180 if let Some(col) = self.column_at_clicked((*column, *row)) {
181 TableOutcome::Header(col)
182 } else {
183 TableOutcome::Continue
184 }
185 } else if self.footer_area.contains((*column, *row).into()) {
186 if let Some(col) = self.column_at_clicked((*column, *row)) {
187 TableOutcome::Footer(col)
188 } else {
189 TableOutcome::Continue
190 }
191 } else {
192 TableOutcome::Continue
193 }
194 }
195 ct_event!(mouse down ALT-Left for column, row) => {
196 let pos = (*column, *row);
197 if self.area.contains(pos.into()) {
198 if let Some(new_row) = self.row_at_clicked(pos) {
199 if self.move_to(new_row, true) {
200 TableOutcome::Selected
201 } else {
202 TableOutcome::Unchanged
203 }
204 } else {
205 TableOutcome::Continue
206 }
207 } else {
208 TableOutcome::Continue
209 }
210 }
211 ct_event!(mouse down CONTROL-Left for column, row) => {
212 let pos = (*column, *row);
213 if self.area.contains(pos.into()) {
214 if let Some(new_row) = self.row_at_clicked(pos) {
215 self.retire_selection();
216 if self.selection.is_selected_row(new_row) {
217 self.selection.remove(new_row);
218 } else {
219 self.move_to(new_row, true);
220 }
221 TableOutcome::Selected
222 } else {
223 TableOutcome::Continue
224 }
225 } else {
226 TableOutcome::Continue
227 }
228 }
229 _ => TableOutcome::Continue,
230 });
231
232 let mut sas = ScrollAreaState::new()
233 .area(self.inner)
234 .h_scroll(&mut self.hscroll)
235 .v_scroll(&mut self.vscroll);
236
237 match sas.handle(event, MouseOnly) {
238 ScrollOutcome::Up(v) => {
239 if self.scroll_up(v) {
240 TableOutcome::Changed
241 } else {
242 TableOutcome::Unchanged
243 }
244 }
245 ScrollOutcome::Down(v) => {
246 if self.scroll_down(v) {
247 TableOutcome::Changed
248 } else {
249 TableOutcome::Unchanged
250 }
251 }
252 ScrollOutcome::VPos(v) => {
253 if self.set_row_offset(self.vscroll.limited_offset(v)) {
254 TableOutcome::Changed
255 } else {
256 TableOutcome::Unchanged
257 }
258 }
259 ScrollOutcome::Left(v) => {
260 if self.scroll_left(v) {
261 TableOutcome::Changed
262 } else {
263 TableOutcome::Unchanged
264 }
265 }
266 ScrollOutcome::Right(v) => {
267 if self.scroll_right(v) {
268 TableOutcome::Changed
269 } else {
270 TableOutcome::Unchanged
271 }
272 }
273 ScrollOutcome::HPos(v) => {
274 if self.set_x_offset(self.hscroll.limited_offset(v)) {
275 TableOutcome::Changed
276 } else {
277 TableOutcome::Unchanged
278 }
279 }
280
281 ScrollOutcome::Continue => TableOutcome::Continue,
282 ScrollOutcome::Unchanged => TableOutcome::Unchanged,
283 ScrollOutcome::Changed => TableOutcome::Changed,
284 }
285 }
286}