// src/functions/modes/navigation/add_table_nav.rs use crate::config::binds::config::Config; use crate::state::{ app::state::AppState, pages::add_table::{AddTableFocus, AddTableState}, }; use crossterm::event::{KeyEvent}; use ratatui::widgets::TableState; use crate::tui::functions::common::add_table::handle_add_column_action; /// Handles navigation events specifically for the Add Table view. /// Returns true if the event was handled, false otherwise. pub fn handle_add_table_navigation( key: KeyEvent, config: &Config, app_state: &mut AppState, add_table_state: &mut AddTableState, command_message: &mut String, ) -> bool { let action = config.get_general_action(key.code, key.modifiers); let current_focus = add_table_state.current_focus; let mut handled = true; // Assume handled unless logic determines otherwise let mut new_focus = current_focus; // Initialize new_focus // Define focus groups for horizontal navigation let is_left_pane_focus = matches!(current_focus, AddTableFocus::ColumnsTable | AddTableFocus::IndexesTable | AddTableFocus::LinksTable ); let is_right_pane_general_focus = matches!(current_focus, // Non-canvas elements in right pane AddTableFocus::AddColumnButton | AddTableFocus::SaveButton | AddTableFocus::CancelButton ); let is_canvas_input_focus = matches!(current_focus, AddTableFocus::InputTableName | AddTableFocus::InputColumnName | AddTableFocus::InputColumnType ); match action.as_deref() { // --- Vertical Navigation (Up/Down) --- Some("move_up") => { match current_focus { AddTableFocus::InputTableName => new_focus = AddTableFocus::CancelButton, // Wrap top (right pane) AddTableFocus::InputColumnName => new_focus = AddTableFocus::InputTableName, AddTableFocus::InputColumnType => new_focus = AddTableFocus::InputColumnName, AddTableFocus::AddColumnButton => new_focus = AddTableFocus::InputColumnType, AddTableFocus::ColumnsTable => { // Left pane navigation if !navigate_table_up(&mut add_table_state.column_table_state, add_table_state.columns.len()) { // If at top of columns, potentially wrap to bottom of left pane (LinksTable) or stay? Let's stay for now. // Or maybe move to AddColumnButton? Let's try moving up from right pane instead. new_focus = AddTableFocus::AddColumnButton; // Tentative: move focus up from right pane } } AddTableFocus::IndexesTable => { if !navigate_table_up(&mut add_table_state.index_table_state, add_table_state.indexes.len()) { new_focus = AddTableFocus::ColumnsTable; } } AddTableFocus::LinksTable => { if !navigate_table_up(&mut add_table_state.link_table_state, add_table_state.links.len()) { new_focus = AddTableFocus::IndexesTable; } } AddTableFocus::SaveButton => new_focus = AddTableFocus::LinksTable, // Move up to left pane bottom AddTableFocus::CancelButton => new_focus = AddTableFocus::SaveButton, } } Some("move_down") => { match current_focus { AddTableFocus::InputTableName => new_focus = AddTableFocus::InputColumnName, AddTableFocus::InputColumnName => new_focus = AddTableFocus::InputColumnType, AddTableFocus::InputColumnType => new_focus = AddTableFocus::AddColumnButton, AddTableFocus::AddColumnButton => new_focus = AddTableFocus::ColumnsTable, // Move down to left pane top AddTableFocus::ColumnsTable => { // Left pane navigation if !navigate_table_down(&mut add_table_state.column_table_state, add_table_state.columns.len()) { new_focus = AddTableFocus::IndexesTable; // Move to next left pane item } } AddTableFocus::IndexesTable => { if !navigate_table_down(&mut add_table_state.index_table_state, add_table_state.indexes.len()) { new_focus = AddTableFocus::LinksTable; } } AddTableFocus::LinksTable => { if !navigate_table_down(&mut add_table_state.link_table_state, add_table_state.links.len()) { new_focus = AddTableFocus::SaveButton; // Move down to right pane bottom } } AddTableFocus::SaveButton => new_focus = AddTableFocus::CancelButton, AddTableFocus::CancelButton => new_focus = AddTableFocus::InputTableName, // Wrap bottom (right pane) } } // --- Horizontal Navigation (Left/Right) --- Some("next_option") => { // 'l' or Right: Move from Left Pane to Right Pane if is_left_pane_focus { new_focus = match current_focus { // Map left pane items to corresponding right pane items (approximate vertical alignment) AddTableFocus::ColumnsTable => AddTableFocus::InputTableName, AddTableFocus::IndexesTable => AddTableFocus::InputColumnName, // Or AddColumnButton? AddTableFocus::LinksTable => AddTableFocus::SaveButton, _ => current_focus, // Should not happen based on is_left_pane_focus }; } else if is_right_pane_general_focus || is_canvas_input_focus { // If already in right pane, maybe wrap Save -> Cancel or stay? Let's handle Save->Cancel only. if current_focus == AddTableFocus::SaveButton { new_focus = AddTableFocus::CancelButton; } } } Some("previous_option") => { // 'h' or Left: Move from Right Pane to Left Pane if is_right_pane_general_focus { new_focus = match current_focus { // Map right pane items back to left pane items (approximate vertical alignment) AddTableFocus::InputTableName | AddTableFocus::InputColumnName | AddTableFocus::InputColumnType | AddTableFocus::AddColumnButton => AddTableFocus::ColumnsTable, // Go to top of left pane AddTableFocus::SaveButton | AddTableFocus::CancelButton => AddTableFocus::LinksTable, // Go to bottom of left pane _ => current_focus, // Should not happen }; } else if is_left_pane_focus { // If already in left pane, pressing 'h' could wrap to Cancel button? new_focus = AddTableFocus::CancelButton; // Wrap left-to-right bottom } } // --- Tab / Shift+Tab Navigation (Keep as vertical cycle) --- Some("next_field") => { // Tab new_focus = match current_focus { AddTableFocus::InputTableName => AddTableFocus::InputColumnName, AddTableFocus::InputColumnName => AddTableFocus::InputColumnType, AddTableFocus::InputColumnType => AddTableFocus::AddColumnButton, AddTableFocus::AddColumnButton => AddTableFocus::ColumnsTable, AddTableFocus::ColumnsTable => AddTableFocus::IndexesTable, AddTableFocus::IndexesTable => AddTableFocus::LinksTable, AddTableFocus::LinksTable => AddTableFocus::SaveButton, AddTableFocus::SaveButton => AddTableFocus::CancelButton, AddTableFocus::CancelButton => AddTableFocus::InputTableName, // Wrap }; } Some("prev_field") => { // Shift+Tab new_focus = match current_focus { AddTableFocus::InputTableName => AddTableFocus::CancelButton, // Wrap AddTableFocus::InputColumnName => AddTableFocus::InputTableName, AddTableFocus::InputColumnType => AddTableFocus::InputColumnName, AddTableFocus::AddColumnButton => AddTableFocus::InputColumnType, AddTableFocus::ColumnsTable => AddTableFocus::AddColumnButton, AddTableFocus::IndexesTable => AddTableFocus::ColumnsTable, AddTableFocus::LinksTable => AddTableFocus::IndexesTable, AddTableFocus::SaveButton => AddTableFocus::LinksTable, AddTableFocus::CancelButton => AddTableFocus::SaveButton, }; } // --- Selection --- Some("select") => { match current_focus { AddTableFocus::AddColumnButton => { if let Some(focus_after_add) = handle_add_column_action(add_table_state, command_message) { new_focus = focus_after_add; } } AddTableFocus::SaveButton => { *command_message = "Action: Save Table (Not Implemented)".to_string(); // TODO: Implement logic } AddTableFocus::CancelButton => { *command_message = "Action: Cancel Add Table".to_string(); // TODO: Implement logic } AddTableFocus::ColumnsTable => { if let Some(index) = add_table_state.column_table_state.selected() { *command_message = format!("Selected column index {}", index); } else { *command_message = "No column selected".to_string(); } } AddTableFocus::IndexesTable => { if let Some(index) = add_table_state.index_table_state.selected() { *command_message = format!("Selected index index {}", index); } else { *command_message = "No index selected".to_string(); } } AddTableFocus::LinksTable => { if let Some(index) = add_table_state.link_table_state.selected() { *command_message = format!("Selected link index {}", index); } else { *command_message = "No link selected".to_string(); } } _ => { // Input fields *command_message = format!("Select on {:?}", current_focus); handled = false; // Let main loop handle edit mode toggle maybe } } // Keep handled = true for select actions unless specifically set to false } // --- Other General Keys --- Some("toggle_sidebar") | Some("toggle_buffer_list") => { handled = false; } // --- No matching action --- _ => handled = false, } // Update focus state if it changed and was handled if handled && current_focus != new_focus { add_table_state.current_focus = new_focus; *command_message = format!("Focus set to {:?}", add_table_state.current_focus); // --- THIS IS THE KEY PART --- // Check if the *new* focus target is one of the canvas input fields let new_is_canvas_input_focus = matches!(new_focus, AddTableFocus::InputTableName | AddTableFocus::InputColumnName | AddTableFocus::InputColumnType ); // Set focus_outside_canvas based on whether the new focus is NOT an input field app_state.ui.focus_outside_canvas = !new_is_canvas_input_focus; // <--- Sets the flag correctly // --- END KEY PART --- // Select first item when focusing a table match add_table_state.current_focus { AddTableFocus::ColumnsTable if add_table_state.column_table_state.selected().is_none() && !add_table_state.columns.is_empty() => { add_table_state.column_table_state.select(Some(0)); } AddTableFocus::IndexesTable if add_table_state.index_table_state.selected().is_none() && !add_table_state.indexes.is_empty() => { add_table_state.index_table_state.select(Some(0)); } AddTableFocus::LinksTable if add_table_state.link_table_state.selected().is_none() && !add_table_state.links.is_empty() => { add_table_state.link_table_state.select(Some(0)); }_ => {} } } else if !handled { // ... } handled } // Helper function for navigating up within a table state // Returns true if navigation happened within the table, false if it reached the top fn navigate_table_up(table_state: &mut TableState, item_count: usize) -> bool { if item_count == 0 { return false; } let current_selection = table_state.selected(); match current_selection { Some(index) => { if index > 0 { table_state.select(Some(index - 1)); true } else { false // Was at the top } } None => { table_state.select(Some(item_count - 1)); // Select last item true } } } // Helper function for navigating down within a table state // Returns true if navigation happened within the table, false if it reached the bottom fn navigate_table_down(table_state: &mut TableState, item_count: usize) -> bool { if item_count == 0 { return false; } let current_selection = table_state.selected(); match current_selection { Some(index) => { if index < item_count - 1 { table_state.select(Some(index + 1)); true } else { false // Was at the bottom } } None => { table_state.select(Some(0)); // Select first item true } } }