rat_ftable/
noselection.rs

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