sql_cli/ui/traits/
navigation.rs1use crate::app_state_container::AppStateContainer;
2use crate::buffer::{AppMode, BufferAPI};
3use crate::ui::viewport_manager::{RowNavigationResult, ViewportManager};
4use std::cell::RefCell;
5pub trait NavigationBehavior {
10 fn viewport_manager(&self) -> &RefCell<Option<ViewportManager>>;
12 fn buffer_mut(&mut self) -> &mut dyn BufferAPI;
13 fn buffer(&self) -> &dyn BufferAPI;
14 fn state_container(&self) -> &AppStateContainer;
15 fn state_container_mut(&mut self) -> &mut AppStateContainer; fn get_row_count(&self) -> usize;
17
18 fn set_mode_with_sync(&mut self, mode: AppMode, trigger: &str);
20
21 fn apply_row_navigation_result(&mut self, result: RowNavigationResult) {
23 self.sync_row_state(result.row_position);
25
26 if result.viewport_changed {
28 let mut offset = self.buffer().get_scroll_offset();
29 offset.0 = result.row_scroll_offset;
30 self.buffer_mut().set_scroll_offset(offset);
31 self.state_container().navigation_mut().scroll_offset.0 = result.row_scroll_offset;
32 }
33 }
34
35 fn sync_row_state(&mut self, row: usize) {
38 self.buffer_mut().set_selected_row(Some(row));
40
41 self.state_container().navigation_mut().selected_row = row;
43
44 self.state_container().set_table_selected_row(Some(row));
47 }
48
49 fn next_row(&mut self) {
52 let nav_result = {
53 let mut viewport_borrow = self.viewport_manager().borrow_mut();
54 viewport_borrow
55 .as_mut()
56 .map(crate::ui::viewport_manager::ViewportManager::navigate_row_down)
57 };
58
59 if let Some(nav_result) = nav_result {
60 self.apply_row_navigation_result(nav_result);
61 }
62 }
63
64 fn previous_row(&mut self) {
65 let nav_result = {
66 let mut viewport_borrow = self.viewport_manager().borrow_mut();
67 viewport_borrow
68 .as_mut()
69 .map(crate::ui::viewport_manager::ViewportManager::navigate_row_up)
70 };
71
72 if let Some(nav_result) = nav_result {
73 self.apply_row_navigation_result(nav_result);
74 }
75 }
76
77 fn goto_first_row(&mut self) {
78 let total_rows = self.get_row_count();
79 if total_rows > 0 {
80 let nav_result = {
81 let mut viewport_borrow = self.viewport_manager().borrow_mut();
82 viewport_borrow
83 .as_mut()
84 .map(|vm| vm.navigate_to_first_row(total_rows))
85 };
86
87 if let Some(nav_result) = nav_result {
88 self.apply_row_navigation_result(nav_result);
89 }
90 }
91 }
92
93 fn goto_last_row(&mut self) {
94 let total_rows = self.get_row_count();
95 if total_rows > 0 {
96 let nav_result = {
97 let mut viewport_borrow = self.viewport_manager().borrow_mut();
98 viewport_borrow
99 .as_mut()
100 .map(|vm| vm.navigate_to_last_row(total_rows))
101 };
102
103 if let Some(nav_result) = nav_result {
104 self.apply_row_navigation_result(nav_result);
105 }
106 }
107 }
108
109 fn page_down(&mut self) {
110 let nav_result = {
111 let mut viewport_borrow = self.viewport_manager().borrow_mut();
112 viewport_borrow
113 .as_mut()
114 .map(crate::ui::viewport_manager::ViewportManager::page_down)
115 };
116
117 if let Some(nav_result) = nav_result {
118 self.apply_row_navigation_result(nav_result);
119 }
120 }
121
122 fn page_up(&mut self) {
123 let nav_result = {
124 let mut viewport_borrow = self.viewport_manager().borrow_mut();
125 viewport_borrow
126 .as_mut()
127 .map(crate::ui::viewport_manager::ViewportManager::page_up)
128 };
129
130 if let Some(nav_result) = nav_result {
131 self.apply_row_navigation_result(nav_result);
132 }
133 }
134
135 fn half_page_down(&mut self) {
136 let nav_result = {
137 let mut viewport_borrow = self.viewport_manager().borrow_mut();
138 viewport_borrow
139 .as_mut()
140 .map(crate::ui::viewport_manager::ViewportManager::half_page_down)
141 };
142
143 if let Some(nav_result) = nav_result {
144 self.apply_row_navigation_result(nav_result);
145 }
146 }
147
148 fn half_page_up(&mut self) {
149 let nav_result = {
150 let mut viewport_borrow = self.viewport_manager().borrow_mut();
151 viewport_borrow
152 .as_mut()
153 .map(crate::ui::viewport_manager::ViewportManager::half_page_up)
154 };
155
156 if let Some(nav_result) = nav_result {
157 self.apply_row_navigation_result(nav_result);
158 }
159 }
160
161 fn goto_line(&mut self, line_number: usize) {
162 let total_rows = self.get_row_count();
163 if line_number > 0 && line_number <= total_rows {
164 let target_row = line_number - 1; let nav_result = {
166 let mut viewport_borrow = self.viewport_manager().borrow_mut();
167 viewport_borrow.as_mut().map(|vm| vm.goto_line(target_row))
168 };
169
170 if let Some(nav_result) = nav_result {
171 self.apply_row_navigation_result(nav_result);
172 self.state_container_mut()
173 .set_status_message(format!("Jumped to row {line_number} (centered)"));
174 }
175 } else {
176 self.state_container_mut().set_status_message(format!(
177 "Row {line_number} out of range (max: {total_rows})"
178 ));
179 }
180 }
181
182 fn goto_viewport_top(&mut self) {
184 let nav_result = {
185 let mut viewport_borrow = self.viewport_manager().borrow_mut();
186 viewport_borrow
187 .as_mut()
188 .map(crate::ui::viewport_manager::ViewportManager::navigate_to_viewport_top)
189 };
190
191 if let Some(nav_result) = nav_result {
192 self.apply_row_navigation_result(nav_result);
193 }
194 }
195
196 fn goto_viewport_middle(&mut self) {
198 let nav_result = {
199 let mut viewport_borrow = self.viewport_manager().borrow_mut();
200 viewport_borrow
201 .as_mut()
202 .map(crate::ui::viewport_manager::ViewportManager::navigate_to_viewport_middle)
203 };
204
205 if let Some(nav_result) = nav_result {
206 self.apply_row_navigation_result(nav_result);
207 }
208 }
209
210 fn goto_viewport_bottom(&mut self) {
212 let nav_result = {
213 let mut viewport_borrow = self.viewport_manager().borrow_mut();
214 viewport_borrow
215 .as_mut()
216 .map(crate::ui::viewport_manager::ViewportManager::navigate_to_viewport_bottom)
217 };
218
219 if let Some(nav_result) = nav_result {
220 self.apply_row_navigation_result(nav_result);
221 }
222 }
223
224 fn complete_jump_to_row(&mut self, input: &str) {
226 if let Ok(row_num) = input.parse::<usize>() {
227 self.goto_line(row_num);
228 } else {
229 self.state_container_mut()
230 .set_status_message("Invalid row number".to_string());
231 }
232
233 self.set_mode_with_sync(AppMode::Results, "jump_to_row_completed");
235
236 let jump_state = self.state_container_mut().jump_to_row_mut();
238 jump_state.input.clear();
239 jump_state.is_active = false;
240 }
241}