rat_ftable/
noselection.rs

1use crate::event::TableOutcome;
2use crate::{TableSelection, TableState};
3use rat_event::{ct_event, HandleEvent, MouseOnly, Regular};
4use rat_focus::HasFocus;
5use rat_scrolled::event::ScrollOutcome;
6use rat_scrolled::ScrollAreaState;
7use std::cmp::max;
8
9/// Doesn't do any selection for the table.
10///
11/// But it implements scrolling via mouse and keyboard.
12#[derive(Debug, Default, Clone)]
13pub struct NoSelection;
14
15impl TableSelection for NoSelection {
16    fn count(&self) -> usize {
17        0
18    }
19
20    fn is_selected_row(&self, _row: usize) -> bool {
21        false
22    }
23
24    fn is_selected_column(&self, _column: usize) -> bool {
25        false
26    }
27
28    fn is_selected_cell(&self, _column: usize, _row: usize) -> bool {
29        false
30    }
31
32    fn lead_selection(&self) -> Option<(usize, usize)> {
33        None
34    }
35}
36
37impl HandleEvent<crossterm::event::Event, Regular, TableOutcome> for TableState<NoSelection> {
38    fn handle(&mut self, event: &crossterm::event::Event, _keymap: Regular) -> TableOutcome {
39        let res = if self.is_focused() {
40            match event {
41                ct_event!(keycode press Up) => {
42                    if self.scroll_up(1) {
43                        TableOutcome::Changed
44                    } else {
45                        TableOutcome::Unchanged
46                    }
47                }
48                ct_event!(keycode press Down) => {
49                    if self.scroll_down(1) {
50                        TableOutcome::Changed
51                    } else {
52                        TableOutcome::Unchanged
53                    }
54                }
55                ct_event!(keycode press CONTROL-Up)
56                | ct_event!(keycode press CONTROL-Home)
57                | ct_event!(keycode press Home) => {
58                    if self.scroll_to_row(0) {
59                        TableOutcome::Changed
60                    } else {
61                        TableOutcome::Unchanged
62                    }
63                }
64                ct_event!(keycode press CONTROL-Down)
65                | ct_event!(keycode press CONTROL-End)
66                | ct_event!(keycode press End) => {
67                    if self.scroll_to_row(self.rows.saturating_sub(1)) {
68                        TableOutcome::Changed
69                    } else {
70                        TableOutcome::Unchanged
71                    }
72                }
73                ct_event!(keycode press PageUp) => {
74                    if self.scroll_up(max(1, self.page_len().saturating_sub(1))) {
75                        TableOutcome::Changed
76                    } else {
77                        TableOutcome::Unchanged
78                    }
79                }
80                ct_event!(keycode press PageDown) => {
81                    if self.scroll_down(max(1, self.page_len().saturating_sub(1))) {
82                        TableOutcome::Changed
83                    } else {
84                        TableOutcome::Unchanged
85                    }
86                }
87                ct_event!(keycode press Left) => {
88                    if self.scroll_left(1) {
89                        TableOutcome::Changed
90                    } else {
91                        TableOutcome::Unchanged
92                    }
93                }
94                ct_event!(keycode press Right) => {
95                    if self.scroll_right(1) {
96                        TableOutcome::Changed
97                    } else {
98                        TableOutcome::Unchanged
99                    }
100                }
101                ct_event!(keycode press CONTROL-Left) => {
102                    if self.scroll_to_x(0) {
103                        TableOutcome::Changed
104                    } else {
105                        TableOutcome::Unchanged
106                    }
107                }
108                ct_event!(keycode press CONTROL-Right) => {
109                    if self.scroll_to_x(self.x_max_offset()) {
110                        TableOutcome::Changed
111                    } else {
112                        TableOutcome::Unchanged
113                    }
114                }
115                _ => TableOutcome::Continue,
116            }
117        } else {
118            TableOutcome::Continue
119        };
120
121        if res == TableOutcome::Continue {
122            self.handle(event, MouseOnly)
123        } else {
124            res
125        }
126    }
127}
128
129impl HandleEvent<crossterm::event::Event, MouseOnly, TableOutcome> for TableState<NoSelection> {
130    fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> TableOutcome {
131        let mut sas = ScrollAreaState::new()
132            .area(self.inner)
133            .h_scroll(&mut self.hscroll)
134            .v_scroll(&mut self.vscroll);
135
136        match sas.handle(event, MouseOnly) {
137            ScrollOutcome::Up(v) => {
138                if self.scroll_up(v) {
139                    TableOutcome::Changed
140                } else {
141                    TableOutcome::Unchanged
142                }
143            }
144            ScrollOutcome::Down(v) => {
145                if self.scroll_down(v) {
146                    TableOutcome::Changed
147                } else {
148                    TableOutcome::Unchanged
149                }
150            }
151            ScrollOutcome::VPos(v) => {
152                if self.set_row_offset(v) {
153                    TableOutcome::Changed
154                } else {
155                    TableOutcome::Unchanged
156                }
157            }
158            ScrollOutcome::Left(v) => {
159                if self.scroll_left(v) {
160                    TableOutcome::Changed
161                } else {
162                    TableOutcome::Unchanged
163                }
164            }
165            ScrollOutcome::Right(v) => {
166                if self.scroll_right(v) {
167                    TableOutcome::Changed
168                } else {
169                    TableOutcome::Unchanged
170                }
171            }
172            ScrollOutcome::HPos(v) => {
173                if self.set_x_offset(v) {
174                    TableOutcome::Changed
175                } else {
176                    TableOutcome::Unchanged
177                }
178            }
179            ScrollOutcome::Continue => TableOutcome::Continue,
180            ScrollOutcome::Unchanged => TableOutcome::Unchanged,
181            ScrollOutcome::Changed => TableOutcome::Changed,
182        }
183    }
184}
185
186/// Handle all events.
187/// Table events are only processed if focus is true.
188/// Mouse events are processed if they are in range.
189pub fn handle_events(
190    state: &mut TableState<NoSelection>,
191    focus: bool,
192    event: &crossterm::event::Event,
193) -> TableOutcome {
194    state.focus.set(focus);
195    state.handle(event, Regular)
196}
197
198/// Handle only mouse-events.
199pub fn handle_mouse_events(
200    state: &mut TableState<NoSelection>,
201    event: &crossterm::event::Event,
202) -> TableOutcome {
203    state.handle(event, MouseOnly)
204}