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.as_mut().map(|vm| vm.navigate_row_down())
55 };
56
57 if let Some(nav_result) = nav_result {
58 self.apply_row_navigation_result(nav_result);
59 }
60 }
61
62 fn previous_row(&mut self) {
63 let nav_result = {
64 let mut viewport_borrow = self.viewport_manager().borrow_mut();
65 viewport_borrow.as_mut().map(|vm| vm.navigate_row_up())
66 };
67
68 if let Some(nav_result) = nav_result {
69 self.apply_row_navigation_result(nav_result);
70 }
71 }
72
73 fn goto_first_row(&mut self) {
74 let total_rows = self.get_row_count();
75 if total_rows > 0 {
76 let nav_result = {
77 let mut viewport_borrow = self.viewport_manager().borrow_mut();
78 viewport_borrow
79 .as_mut()
80 .map(|vm| vm.navigate_to_first_row(total_rows))
81 };
82
83 if let Some(nav_result) = nav_result {
84 self.apply_row_navigation_result(nav_result);
85 }
86 }
87 }
88
89 fn goto_last_row(&mut self) {
90 let total_rows = self.get_row_count();
91 if total_rows > 0 {
92 let nav_result = {
93 let mut viewport_borrow = self.viewport_manager().borrow_mut();
94 viewport_borrow
95 .as_mut()
96 .map(|vm| vm.navigate_to_last_row(total_rows))
97 };
98
99 if let Some(nav_result) = nav_result {
100 self.apply_row_navigation_result(nav_result);
101 }
102 }
103 }
104
105 fn page_down(&mut self) {
106 let nav_result = {
107 let mut viewport_borrow = self.viewport_manager().borrow_mut();
108 viewport_borrow.as_mut().map(|vm| vm.page_down())
109 };
110
111 if let Some(nav_result) = nav_result {
112 self.apply_row_navigation_result(nav_result);
113 }
114 }
115
116 fn page_up(&mut self) {
117 let nav_result = {
118 let mut viewport_borrow = self.viewport_manager().borrow_mut();
119 viewport_borrow.as_mut().map(|vm| vm.page_up())
120 };
121
122 if let Some(nav_result) = nav_result {
123 self.apply_row_navigation_result(nav_result);
124 }
125 }
126
127 fn half_page_down(&mut self) {
128 let nav_result = {
129 let mut viewport_borrow = self.viewport_manager().borrow_mut();
130 viewport_borrow.as_mut().map(|vm| vm.half_page_down())
131 };
132
133 if let Some(nav_result) = nav_result {
134 self.apply_row_navigation_result(nav_result);
135 }
136 }
137
138 fn half_page_up(&mut self) {
139 let nav_result = {
140 let mut viewport_borrow = self.viewport_manager().borrow_mut();
141 viewport_borrow.as_mut().map(|vm| vm.half_page_up())
142 };
143
144 if let Some(nav_result) = nav_result {
145 self.apply_row_navigation_result(nav_result);
146 }
147 }
148
149 fn goto_line(&mut self, line_number: usize) {
150 let total_rows = self.get_row_count();
151 if line_number > 0 && line_number <= total_rows {
152 let target_row = line_number - 1; let nav_result = {
154 let mut viewport_borrow = self.viewport_manager().borrow_mut();
155 viewport_borrow.as_mut().map(|vm| vm.goto_line(target_row))
156 };
157
158 if let Some(nav_result) = nav_result {
159 self.apply_row_navigation_result(nav_result);
160 self.state_container_mut()
161 .set_status_message(format!("Jumped to row {} (centered)", line_number));
162 }
163 } else {
164 self.state_container_mut().set_status_message(format!(
165 "Row {} out of range (max: {})",
166 line_number, total_rows
167 ));
168 }
169 }
170
171 fn goto_viewport_top(&mut self) {
173 let nav_result = {
174 let mut viewport_borrow = self.viewport_manager().borrow_mut();
175 viewport_borrow
176 .as_mut()
177 .map(|vm| vm.navigate_to_viewport_top())
178 };
179
180 if let Some(nav_result) = nav_result {
181 self.apply_row_navigation_result(nav_result);
182 }
183 }
184
185 fn goto_viewport_middle(&mut self) {
187 let nav_result = {
188 let mut viewport_borrow = self.viewport_manager().borrow_mut();
189 viewport_borrow
190 .as_mut()
191 .map(|vm| vm.navigate_to_viewport_middle())
192 };
193
194 if let Some(nav_result) = nav_result {
195 self.apply_row_navigation_result(nav_result);
196 }
197 }
198
199 fn goto_viewport_bottom(&mut self) {
201 let nav_result = {
202 let mut viewport_borrow = self.viewport_manager().borrow_mut();
203 viewport_borrow
204 .as_mut()
205 .map(|vm| vm.navigate_to_viewport_bottom())
206 };
207
208 if let Some(nav_result) = nav_result {
209 self.apply_row_navigation_result(nav_result);
210 }
211 }
212
213 fn complete_jump_to_row(&mut self, input: &str) {
215 if let Ok(row_num) = input.parse::<usize>() {
216 self.goto_line(row_num);
217 } else {
218 self.state_container_mut()
219 .set_status_message("Invalid row number".to_string());
220 }
221
222 self.set_mode_with_sync(AppMode::Results, "jump_to_row_completed");
224
225 let jump_state = self.state_container_mut().jump_to_row_mut();
227 jump_state.input.clear();
228 jump_state.is_active = false;
229 }
230}