diff --git a/client/src/functions/modes/navigation/add_table_nav.rs b/client/src/functions/modes/navigation/add_table_nav.rs index dd545a8..e7720a4 100644 --- a/client/src/functions/modes/navigation/add_table_nav.rs +++ b/client/src/functions/modes/navigation/add_table_nav.rs @@ -12,11 +12,32 @@ use crate::services::GrpcClient; use tokio::sync::mpsc; use anyhow::Result; -// Define a type for the save result channel pub type SaveTableResultSender = mpsc::Sender>; -/// Handles navigation events specifically for the Add Table view. -/// Returns true if the event was handled, false otherwise. +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 } + } + None => { table_state.select(Some(0)); true } + } +} + +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 } + } + None => { table_state.select(Some(0)); true } + } +} + pub fn handle_add_table_navigation( key: KeyEvent, config: &Config, @@ -28,61 +49,52 @@ pub fn handle_add_table_navigation( ) -> 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 + let mut handled = true; + let mut new_focus = current_focus; + + if matches!(current_focus, AddTableFocus::InsideColumnsTable | AddTableFocus::InsideIndexesTable | AddTableFocus::InsideLinksTable) { + if matches!(action.as_deref(), Some("next_option") | Some("previous_option")) { + *command_message = "Press Esc to exit table item navigation first.".to_string(); + return true; + } + } match action.as_deref() { - // --- Handle Exiting Table Scroll Mode --- Some("exit_table_scroll") => { match current_focus { AddTableFocus::InsideColumnsTable => { add_table_state.column_table_state.select(None); new_focus = AddTableFocus::ColumnsTable; - *command_message = "Exited Columns Table".to_string(); + // *command_message = "Exited Columns Table".to_string(); // Minimal change: remove message } AddTableFocus::InsideIndexesTable => { add_table_state.index_table_state.select(None); new_focus = AddTableFocus::IndexesTable; - *command_message = "Exited Indexes Table".to_string(); + // *command_message = "Exited Indexes Table".to_string(); } AddTableFocus::InsideLinksTable => { add_table_state.link_table_state.select(None); new_focus = AddTableFocus::LinksTable; - *command_message = "Exited Links Table".to_string(); - } - _ => { - // Action triggered but not applicable in this focus state - handled = false; + // *command_message = "Exited Links Table".to_string(); } + _ => handled = false, } - // If handled (i.e., focus changed), handled remains true. - // If not handled, handled becomes false. } - - // --- Vertical Navigation (Up/Down) --- Some("move_up") => { match current_focus { - AddTableFocus::InputTableName => new_focus = AddTableFocus::CancelButton, + AddTableFocus::InputTableName => { + // MINIMAL CHANGE: Do nothing, new_focus remains current_focus + // *command_message = "At top of form.".to_string(); // Remove message + } AddTableFocus::InputColumnName => new_focus = AddTableFocus::InputTableName, AddTableFocus::InputColumnType => new_focus = AddTableFocus::InputColumnName, AddTableFocus::AddColumnButton => new_focus = AddTableFocus::InputColumnType, - // Navigate between blocks when focus is on the table block itself - AddTableFocus::ColumnsTable => new_focus = AddTableFocus::AddColumnButton, // Move up to right pane + AddTableFocus::ColumnsTable => new_focus = AddTableFocus::AddColumnButton, AddTableFocus::IndexesTable => new_focus = AddTableFocus::ColumnsTable, AddTableFocus::LinksTable => new_focus = AddTableFocus::IndexesTable, - // Scroll inside the table when focus is internal - AddTableFocus::InsideColumnsTable => { - navigate_table_up(&mut add_table_state.column_table_state, add_table_state.columns.len()); - // Stay inside the table, don't change new_focus - } - AddTableFocus::InsideIndexesTable => { - navigate_table_up(&mut add_table_state.index_table_state, add_table_state.indexes.len()); - // Stay inside the table - } - AddTableFocus::InsideLinksTable => { - navigate_table_up(&mut add_table_state.link_table_state, add_table_state.links.len()); - // Stay inside the table - } + AddTableFocus::InsideColumnsTable => { navigate_table_up(&mut add_table_state.column_table_state, add_table_state.columns.len()); } + AddTableFocus::InsideIndexesTable => { navigate_table_up(&mut add_table_state.index_table_state, add_table_state.indexes.len()); } + AddTableFocus::InsideLinksTable => { navigate_table_up(&mut add_table_state.link_table_state, add_table_state.links.len()); } AddTableFocus::SaveButton => new_focus = AddTableFocus::LinksTable, AddTableFocus::DeleteSelectedButton => new_focus = AddTableFocus::SaveButton, AddTableFocus::CancelButton => new_focus = AddTableFocus::DeleteSelectedButton, @@ -94,304 +106,97 @@ pub fn handle_add_table_navigation( AddTableFocus::InputColumnName => new_focus = AddTableFocus::InputColumnType, AddTableFocus::InputColumnType => new_focus = AddTableFocus::AddColumnButton, AddTableFocus::AddColumnButton => new_focus = AddTableFocus::ColumnsTable, - // Navigate between blocks when focus is on the table block itself AddTableFocus::ColumnsTable => new_focus = AddTableFocus::IndexesTable, AddTableFocus::IndexesTable => new_focus = AddTableFocus::LinksTable, - AddTableFocus::LinksTable => new_focus = AddTableFocus::SaveButton, // Move down to right pane - // Scroll inside the table when focus is internal - AddTableFocus::InsideColumnsTable => { - navigate_table_down(&mut add_table_state.column_table_state, add_table_state.columns.len()); - // Stay inside the table - } - AddTableFocus::InsideIndexesTable => { - navigate_table_down(&mut add_table_state.index_table_state, add_table_state.indexes.len()); - // Stay inside the table - } - AddTableFocus::InsideLinksTable => { - navigate_table_down(&mut add_table_state.link_table_state, add_table_state.links.len()); - // Stay inside the table - } + AddTableFocus::LinksTable => new_focus = AddTableFocus::SaveButton, + AddTableFocus::InsideColumnsTable => { navigate_table_down(&mut add_table_state.column_table_state, add_table_state.columns.len()); } + AddTableFocus::InsideIndexesTable => { navigate_table_down(&mut add_table_state.index_table_state, add_table_state.indexes.len()); } + AddTableFocus::InsideLinksTable => { navigate_table_down(&mut add_table_state.link_table_state, add_table_state.links.len()); } AddTableFocus::SaveButton => new_focus = AddTableFocus::DeleteSelectedButton, AddTableFocus::DeleteSelectedButton => new_focus = AddTableFocus::CancelButton, - AddTableFocus::CancelButton => new_focus = AddTableFocus::InputTableName, + AddTableFocus::CancelButton => { + // MINIMAL CHANGE: Do nothing, new_focus remains current_focus + // *command_message = "At bottom of form.".to_string(); // Remove message + } } } - - // --- Horizontal Navigation (Left/Right) --- - Some("next_option") => { // 'l' or Right: Move from Left Pane to Right Pane - // Horizontal nav within bottom buttons - if current_focus == AddTableFocus::SaveButton { - new_focus = AddTableFocus::DeleteSelectedButton; - } else if current_focus == AddTableFocus::DeleteSelectedButton { - new_focus = AddTableFocus::CancelButton; - } + Some("next_option") => { // This logic should already be non-wrapping + match current_focus { + AddTableFocus::InputTableName | AddTableFocus::InputColumnName | AddTableFocus::InputColumnType => + { new_focus = AddTableFocus::AddColumnButton; } + AddTableFocus::AddColumnButton => new_focus = AddTableFocus::ColumnsTable, + AddTableFocus::ColumnsTable => new_focus = AddTableFocus::IndexesTable, + AddTableFocus::IndexesTable => new_focus = AddTableFocus::LinksTable, + AddTableFocus::LinksTable => new_focus = AddTableFocus::SaveButton, + AddTableFocus::SaveButton => new_focus = AddTableFocus::DeleteSelectedButton, + AddTableFocus::DeleteSelectedButton => new_focus = AddTableFocus::CancelButton, + AddTableFocus::CancelButton => { /* *command_message = "At last focusable area.".to_string(); */ } // No change in focus + _ => handled = false, + } } - Some("previous_option") => { // 'h' or Left: Move from Right Pane to Left Pane - // Horizontal nav within bottom buttons - if current_focus == AddTableFocus::CancelButton { - new_focus = AddTableFocus::DeleteSelectedButton; - } else if current_focus == AddTableFocus::DeleteSelectedButton { - new_focus = AddTableFocus::SaveButton; - } + Some("previous_option") => { // This logic should already be non-wrapping + match current_focus { + AddTableFocus::InputTableName | AddTableFocus::InputColumnName | AddTableFocus::InputColumnType => + { /* *command_message = "At first focusable area.".to_string(); */ } // No change in focus + AddTableFocus::AddColumnButton => new_focus = AddTableFocus::InputColumnType, + AddTableFocus::ColumnsTable => new_focus = AddTableFocus::AddColumnButton, + AddTableFocus::IndexesTable => new_focus = AddTableFocus::ColumnsTable, + AddTableFocus::LinksTable => new_focus = AddTableFocus::IndexesTable, + AddTableFocus::SaveButton => new_focus = AddTableFocus::LinksTable, + AddTableFocus::DeleteSelectedButton => new_focus = AddTableFocus::SaveButton, + AddTableFocus::CancelButton => new_focus = AddTableFocus::DeleteSelectedButton, + _ => handled = false, + } } - - // --- Tab / Shift+Tab Navigation (Keep as vertical cycle) --- - Some("next_field") => { // Tab + Some("next_field") => { new_focus = match current_focus { - AddTableFocus::InputTableName => AddTableFocus::InputColumnName, - AddTableFocus::InputColumnName => AddTableFocus::InputColumnType, - AddTableFocus::InputColumnType => AddTableFocus::AddColumnButton, - AddTableFocus::AddColumnButton => AddTableFocus::ColumnsTable, - // Treat Inside* same as block focus for tabbing out - AddTableFocus::ColumnsTable | AddTableFocus::InsideColumnsTable => AddTableFocus::IndexesTable, - AddTableFocus::IndexesTable | AddTableFocus::InsideIndexesTable => AddTableFocus::LinksTable, - AddTableFocus::LinksTable | AddTableFocus::InsideLinksTable => AddTableFocus::SaveButton, - AddTableFocus::SaveButton => AddTableFocus::DeleteSelectedButton, - AddTableFocus::DeleteSelectedButton => AddTableFocus::CancelButton, - AddTableFocus::CancelButton => AddTableFocus::InputTableName, // Wrap + AddTableFocus::InputTableName => AddTableFocus::InputColumnName, AddTableFocus::InputColumnName => AddTableFocus::InputColumnType, AddTableFocus::InputColumnType => AddTableFocus::AddColumnButton, AddTableFocus::AddColumnButton => AddTableFocus::ColumnsTable, + AddTableFocus::ColumnsTable | AddTableFocus::InsideColumnsTable => AddTableFocus::IndexesTable, AddTableFocus::IndexesTable | AddTableFocus::InsideIndexesTable => AddTableFocus::LinksTable, AddTableFocus::LinksTable | AddTableFocus::InsideLinksTable => AddTableFocus::SaveButton, + AddTableFocus::SaveButton => AddTableFocus::DeleteSelectedButton, AddTableFocus::DeleteSelectedButton => AddTableFocus::CancelButton, AddTableFocus::CancelButton => AddTableFocus::InputTableName, }; } - Some("prev_field") => { // Shift+Tab + Some("prev_field") => { new_focus = match current_focus { - AddTableFocus::InputTableName => AddTableFocus::CancelButton, // Wrap - AddTableFocus::InputColumnName => AddTableFocus::InputTableName, - AddTableFocus::InputColumnType => AddTableFocus::InputColumnName, - AddTableFocus::AddColumnButton => AddTableFocus::InputColumnType, - // Treat Inside* same as block focus for tabbing out - AddTableFocus::ColumnsTable | AddTableFocus::InsideColumnsTable => AddTableFocus::AddColumnButton, - AddTableFocus::IndexesTable | AddTableFocus::InsideIndexesTable => AddTableFocus::ColumnsTable, - AddTableFocus::LinksTable | AddTableFocus::InsideLinksTable => AddTableFocus::IndexesTable, - AddTableFocus::SaveButton => AddTableFocus::LinksTable, - AddTableFocus::DeleteSelectedButton => AddTableFocus::SaveButton, - AddTableFocus::CancelButton => AddTableFocus::DeleteSelectedButton, + AddTableFocus::InputTableName => AddTableFocus::CancelButton, AddTableFocus::InputColumnName => AddTableFocus::InputTableName, AddTableFocus::InputColumnType => AddTableFocus::InputColumnName, AddTableFocus::AddColumnButton => AddTableFocus::InputColumnType, + AddTableFocus::ColumnsTable | AddTableFocus::InsideColumnsTable => AddTableFocus::AddColumnButton, AddTableFocus::IndexesTable | AddTableFocus::InsideIndexesTable => AddTableFocus::ColumnsTable, AddTableFocus::LinksTable | AddTableFocus::InsideLinksTable => AddTableFocus::IndexesTable, + AddTableFocus::SaveButton => AddTableFocus::LinksTable, AddTableFocus::DeleteSelectedButton => AddTableFocus::SaveButton, AddTableFocus::CancelButton => AddTableFocus::DeleteSelectedButton, }; } - - // --- Selection --- Some("select") => { match current_focus { - // --- Enter/Exit Table Focus --- - AddTableFocus::ColumnsTable => { - new_focus = AddTableFocus::InsideColumnsTable; - // Select first item if none selected when entering - 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)); - } - *command_message = "Entered Columns Table (Scroll with Up/Down, Select to exit)".to_string(); - } - AddTableFocus::IndexesTable => { - new_focus = AddTableFocus::InsideIndexesTable; - 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)); - } - *command_message = "Entered Indexes Table (Scroll with Up/Down, Select to exit)".to_string(); - } - AddTableFocus::LinksTable => { - new_focus = AddTableFocus::InsideLinksTable; - 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)); - } - *command_message = "Entered Links Table (Scroll with Up/Down, Select to toggle/exit)".to_string(); - } - AddTableFocus::InsideColumnsTable => { - // Toggle selection when pressing select *inside* the columns table - if let Some(index) = add_table_state.column_table_state.selected() { - if let Some(col) = add_table_state.columns.get_mut(index) { - col.selected = !col.selected; - add_table_state.has_unsaved_changes = true; - *command_message = format!( - "Toggled selection for column: {} to {}", - col.name, col.selected - ); - } - } else { - *command_message = "No column highlighted to toggle selection".to_string(); - } - } - AddTableFocus::InsideIndexesTable => { - // Select does nothing here anymore, only Esc exits. - if let Some(index) = add_table_state.index_table_state.selected() { - if let Some(idx_def) = add_table_state.indexes.get_mut(index) { - idx_def.selected = !idx_def.selected; - add_table_state.has_unsaved_changes = true; - *command_message = format!( - "Toggled selection for index: {} to {}", - idx_def.name, idx_def.selected - ); - } else { - *command_message = "Error: Selected index out of bounds".to_string(); - } - } else { - *command_message = "No index selected (Press Esc to exit scroll mode)".to_string(); - } - } - AddTableFocus::InsideLinksTable => { - // Toggle selection when pressing select *inside* the links table - if let Some(index) = add_table_state.link_table_state.selected() { - if let Some(link) = add_table_state.links.get_mut(index) { - link.selected = !link.selected; // Toggle the selected state - add_table_state.has_unsaved_changes = true; // Mark changes - *command_message = format!( - "Toggled selection for link: {} to {}", - link.linked_table_name, link.selected - ); - } else { - *command_message = "Error: Selected link index out of bounds".to_string(); - } - } else { - *command_message = "No link selected to toggle".to_string(); - } - // Stay inside the links table after toggling - new_focus = AddTableFocus::InsideLinksTable; - // Alternative: Exit after toggle: - // new_focus = AddTableFocus::LinksTable; - // *command_message = format!("{} - Exited Links Table", command_message); - } - // --- Other Select Actions --- - AddTableFocus::AddColumnButton => { - if let Some(focus_after_add) = handle_add_column_action(add_table_state, command_message) { - new_focus = focus_after_add; - } - } - AddTableFocus::SaveButton => { - // --- Initiate Async Save --- - if add_table_state.table_name.is_empty() { - *command_message = "Cannot save: Table name is empty.".to_string(); - } else if add_table_state.columns.is_empty() { - *command_message = "Cannot save: No columns defined.".to_string(); - } else { - *command_message = "Saving table...".to_string(); - app_state.show_loading_dialog("Saving", "Please wait..."); - - let mut client_clone = grpc_client.clone(); - let state_clone = add_table_state.clone(); - let sender_clone = save_result_sender.clone(); - - tokio::spawn(async move { - let result = handle_save_table_action(&mut client_clone, &state_clone).await; - let _ = sender_clone.send(result).await; // Send result back - }); - } - // --- End Initiate Async Save --- - } - AddTableFocus::DeleteSelectedButton => { - // --- Show Confirmation Dialog --- - // Collect tuples of (index, name, type) for selected columns - let columns_to_delete: Vec<(usize, String, String)> = add_table_state - .columns - .iter() - .enumerate() // Get index along with the column - .filter(|(_index, col)| col.selected) // Filter based on selection - .map(|(index, col)| (index, col.name.clone(), col.data_type.clone())) // Map to (index, name, type) - .collect(); - - if columns_to_delete.is_empty() { - *command_message = "No columns selected for deletion.".to_string(); - } else { - // Format the message to include index, name, and type - let column_details: String = columns_to_delete - .iter() - // Add 1 to index for 1-based numbering for user display - .map(|(index, name, dtype)| format!("{}. {} ({})", index + 1, name, dtype)) - .collect::>() - .join("\n"); - - // Use the formatted column_details string in the message - let message = format!( - "Delete the following columns?\n\n{}", - column_details - ); - let buttons = vec!["Confirm".to_string(), "Cancel".to_string()]; - app_state.show_dialog( - "Confirm Deletion", - &message, - buttons, - DialogPurpose::ConfirmDeleteColumns, - ); - } - } - AddTableFocus::CancelButton => { - *command_message = "Action: Cancel Add Table".to_string(); - // TODO: Implement logic - } - _ => { // Input fields - *command_message = format!("Select on {:?}", current_focus); - handled = false; // Let main loop handle edit mode toggle maybe - } + AddTableFocus::ColumnsTable => { new_focus = AddTableFocus::InsideColumnsTable; 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)); } /* Message removed */ } + AddTableFocus::IndexesTable => { new_focus = AddTableFocus::InsideIndexesTable; 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)); } /* Message removed */ } + AddTableFocus::LinksTable => { new_focus = AddTableFocus::InsideLinksTable; 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)); } /* Message removed */ } + AddTableFocus::InsideColumnsTable => { if let Some(index) = add_table_state.column_table_state.selected() { if let Some(col) = add_table_state.columns.get_mut(index) { col.selected = !col.selected; add_table_state.has_unsaved_changes = true; /* Message removed */ }} /* else { Message removed } */ } + AddTableFocus::InsideIndexesTable => { if let Some(index) = add_table_state.index_table_state.selected() { if let Some(idx_def) = add_table_state.indexes.get_mut(index) { idx_def.selected = !idx_def.selected; add_table_state.has_unsaved_changes = true; /* Message removed */ }} /* else { Message removed } */ } + AddTableFocus::InsideLinksTable => { if let Some(index) = add_table_state.link_table_state.selected() { if let Some(link) = add_table_state.links.get_mut(index) { link.selected = !link.selected; add_table_state.has_unsaved_changes = true; /* Message removed */ }} /* else { Message removed } */ } + AddTableFocus::AddColumnButton => { if let Some(focus_after_add) = handle_add_column_action(add_table_state, command_message) { new_focus = focus_after_add; } else { /* Message already set by handle_add_column_action */ }} + AddTableFocus::SaveButton => { if add_table_state.table_name.is_empty() { *command_message = "Cannot save: Table name is empty.".to_string(); } else if add_table_state.columns.is_empty() { *command_message = "Cannot save: No columns defined.".to_string(); } else { *command_message = "Saving table...".to_string(); app_state.show_loading_dialog("Saving", "Please wait..."); let mut client_clone = grpc_client.clone(); let state_clone = add_table_state.clone(); let sender_clone = save_result_sender.clone(); tokio::spawn(async move { let result = handle_save_table_action(&mut client_clone, &state_clone).await; let _ = sender_clone.send(result).await; }); }} + AddTableFocus::DeleteSelectedButton => { let columns_to_delete: Vec<(usize, String, String)> = add_table_state.columns.iter().enumerate().filter(|(_, col)| col.selected).map(|(index, col)| (index, col.name.clone(), col.data_type.clone())).collect(); if columns_to_delete.is_empty() { *command_message = "No columns selected for deletion.".to_string(); } else { let column_details: String = columns_to_delete.iter().map(|(index, name, dtype)| format!("{}. {} ({})", index + 1, name, dtype)).collect::>().join("\n"); let message = format!("Delete the following columns?\n\n{}", column_details); app_state.show_dialog("Confirm Deletion", &message, vec!["Confirm".to_string(), "Cancel".to_string()], DialogPurpose::ConfirmDeleteColumns); }} + AddTableFocus::CancelButton => { *command_message = "Action: Cancel Add Table (Not Implemented)".to_string(); } + _ => { handled = false; } } - // 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; - // Avoid overwriting specific messages set during 'select' handling - if command_message.is_empty() || command_message.starts_with("Focus set to") { - *command_message = format!("Focus set to {:?}", add_table_state.current_focus); + // Minimal change: Command message update logic can be simplified or removed if not desired + // For now, let's keep it minimal and only update if it was truly a focus change, + // and not a boundary message. + if !command_message.starts_with("At ") && current_focus != new_focus { // Avoid overwriting boundary messages + // *command_message = format!("Focus: {:?}", add_table_state.current_focus); // Optional: restore if needed } - // 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 ); - // Focus is outside canvas if it's not an input field app_state.ui.focus_outside_canvas = !new_is_canvas_input_focus; - } else if !handled { - // command_message.clear(); // Optional: Clear message if not handled here } + // If not handled, command_message remains as it was (e.g., from a deeper function call or previous event) + // or can be cleared if that's the desired default. For minimal change, we leave it. 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 // Navigation happened - } else { - false // Was at the top - } - } - None => { // No item selected, select the last one - table_state.select(Some(item_count - 1)); - true // Navigation happened (selection set) - } - } -} - -// 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 // Navigation happened - } else { - false // Was at the bottom - } - } - None => { // No item selected, select the first one - table_state.select(Some(0)); - true // Navigation happened (selection set) - } - } -} -