sql_cli/ui/traits/
column_ops.rs1use crate::app_state_container::AppStateContainer;
2use crate::buffer::{AppMode, BufferAPI};
3use crate::ui::viewport_manager::{ColumnOperationResult, NavigationResult, ViewportManager};
4use std::cell::RefCell;
5pub trait ColumnBehavior {
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
16 fn is_in_results_mode(&self) -> bool {
18 self.buffer().get_mode() == AppMode::Results
20 }
21
22 fn apply_column_navigation_result(&mut self, result: NavigationResult, direction: &str) {
24 let visual_position = result.column_position;
27
28 tracing::debug!(
29 "[COLUMN_OPS] apply_column_navigation_result: direction={}, visual_position={}",
30 direction,
31 visual_position
32 );
33
34 self.buffer_mut().set_current_column(visual_position);
36 tracing::debug!(
37 "[COLUMN_OPS] apply_column_navigation_result: set buffer column to {}",
38 visual_position
39 );
40
41 self.state_container().navigation_mut().selected_column = visual_position;
43 tracing::debug!(
44 "[COLUMN_OPS] apply_column_navigation_result: set navigation column to {}",
45 visual_position
46 );
47
48 if result.viewport_changed {
50 let mut offset = self.buffer().get_scroll_offset();
51 offset.1 = result.scroll_offset;
52 self.buffer_mut().set_scroll_offset(offset);
53
54 self.state_container().navigation_mut().scroll_offset.1 = result.scroll_offset;
56 }
57
58 let message = match direction {
60 "first" => "Moved to first column".to_string(),
61 "last" => "Moved to last column".to_string(),
62 _ => format!("Moved to column {}", visual_position),
63 };
64 self.buffer_mut().set_status_message(message);
65 }
66
67 fn apply_column_operation_result(&mut self, result: ColumnOperationResult) {
69 if !result.success {
70 if !result.description.is_empty() {
71 self.buffer_mut().set_status_message(result.description);
72 }
73 return;
74 }
75
76 if let Some(dataview) = result.updated_dataview {
78 self.buffer_mut().set_dataview(Some(dataview));
79 }
80
81 if let Some(new_col) = result.new_column_position {
83 self.state_container().navigation_mut().selected_column = new_col;
85
86 if let Some(viewport) = result.new_viewport {
88 let pinned_count = self
89 .buffer()
90 .get_dataview()
91 .as_ref()
92 .map(|dv| dv.get_pinned_columns().len())
93 .unwrap_or(0);
94 self.state_container().navigation_mut().scroll_offset.1 =
95 viewport.start.saturating_sub(pinned_count);
96 }
97
98 self.buffer_mut().set_current_column(new_col);
99 }
100
101 self.buffer_mut().set_status_message(result.description);
103 }
104
105 fn hide_current_column(&mut self) {
109 if !self.is_in_results_mode() {
110 return;
111 }
112
113 let result = self
114 .viewport_manager()
115 .borrow_mut()
116 .as_mut()
117 .map(|vm| vm.hide_current_column_with_result())
118 .unwrap_or_else(|| ColumnOperationResult::failure("No viewport manager"));
119
120 self.apply_column_operation_result(result);
121 }
122
123 fn unhide_all_columns(&mut self) {
125 let result = self
126 .viewport_manager()
127 .borrow_mut()
128 .as_mut()
129 .map(|vm| vm.unhide_all_columns_with_result())
130 .unwrap_or_else(|| ColumnOperationResult::failure("No viewport manager"));
131
132 self.apply_column_operation_result(result);
133 }
134
135 fn move_current_column_left(&mut self) {
137 if !self.is_in_results_mode() {
138 return;
139 }
140
141 let result = self
142 .viewport_manager()
143 .borrow_mut()
144 .as_mut()
145 .map(|vm| vm.reorder_column_left_with_result())
146 .unwrap_or_else(|| ColumnOperationResult::failure("No viewport manager"));
147
148 self.apply_column_operation_result(result);
149 }
150
151 fn move_current_column_right(&mut self) {
153 if !self.is_in_results_mode() {
154 return;
155 }
156
157 let result = self
158 .viewport_manager()
159 .borrow_mut()
160 .as_mut()
161 .map(|vm| vm.reorder_column_right_with_result())
162 .unwrap_or_else(|| ColumnOperationResult::failure("No viewport manager"));
163
164 self.apply_column_operation_result(result);
165 }
166
167 fn move_column_left(&mut self) {
169 let nav_result = {
171 let mut viewport_borrow = self.viewport_manager().borrow_mut();
172 let vm = viewport_borrow
173 .as_mut()
174 .expect("ViewportManager must exist for navigation");
175 let current_visual = vm.get_crosshair_col();
176 vm.navigate_column_left(current_visual)
177 };
178
179 self.apply_column_navigation_result(nav_result, "left");
180 }
181
182 fn move_column_right(&mut self) {
184 let nav_result = {
186 let mut viewport_borrow = self.viewport_manager().borrow_mut();
187 let vm = viewport_borrow
188 .as_mut()
189 .expect("ViewportManager must exist for navigation");
190 let current_visual = vm.get_crosshair_col();
191 tracing::debug!(
192 "[COLUMN_OPS] move_column_right: current_visual from VM = {}",
193 current_visual
194 );
195 let result = vm.navigate_column_right(current_visual);
196 tracing::debug!(
197 "[COLUMN_OPS] move_column_right: navigation result column_position = {}",
198 result.column_position
199 );
200 result
201 };
202
203 tracing::debug!(
204 "[COLUMN_OPS] move_column_right: applying result with column_position = {}",
205 nav_result.column_position
206 );
207 self.apply_column_navigation_result(nav_result, "right");
208 }
209
210 fn goto_first_column(&mut self) {
212 let nav_result = {
214 let mut viewport_borrow = self.viewport_manager().borrow_mut();
215 viewport_borrow
216 .as_mut()
217 .expect("ViewportManager must exist for navigation")
218 .navigate_to_first_column()
219 };
220
221 self.apply_column_navigation_result(nav_result, "first");
223 }
224
225 fn goto_last_column(&mut self) {
227 let nav_result = {
229 let mut viewport_borrow = self.viewport_manager().borrow_mut();
230 viewport_borrow
231 .as_mut()
232 .expect("ViewportManager must exist for navigation")
233 .navigate_to_last_column()
234 };
235
236 self.apply_column_navigation_result(nav_result, "last");
238 }
239}