diff --git a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig index 3792584..90cba28 100644 --- a/src/widgets/virtual_advanced_table/virtual_advanced_table.zig +++ b/src/widgets/virtual_advanced_table/virtual_advanced_table.zig @@ -391,7 +391,7 @@ pub fn virtualAdvancedTableRect( // Handle keyboard if (has_focus) { - handleKeyboard(ctx, list_state, provider, visible_rows, total_rows, max_scroll_x, config.columns.len, &result); + handleKeyboard(ctx, list_state, provider, visible_rows, total_rows, max_scroll_x, config.columns, bounds.w, &result); } // Handle mouse clicks on rows @@ -979,6 +979,46 @@ fn drawScrollbarH( }); } +// ============================================================================= +// Auto-scroll horizontal helper +// ============================================================================= + +/// Asegura que la columna activa sea visible ajustando scroll_x si es necesario +fn ensureColumnVisible( + list_state: *VirtualAdvancedTableState, + columns: []const types.ColumnDef, + visible_width: u32, + max_scroll_x: i32, +) void { + const active_col = list_state.nav.active_col; + if (active_col >= columns.len) return; + + // Calcular posición X de la columna activa + var col_start: i32 = 0; + for (columns, 0..) |col, i| { + if (i == active_col) break; + col_start += @as(i32, @intCast(col.width)); + } + const col_end = col_start + @as(i32, @intCast(columns[active_col].width)); + + // Posición visible (considerando scroll actual) + const visible_start = list_state.nav.scroll_x; + const visible_end = visible_start + @as(i32, @intCast(visible_width)); + + // Ajustar scroll si la columna está fuera de vista + if (col_start < visible_start) { + // Columna está a la izquierda: scroll para mostrar inicio de columna + list_state.nav.scroll_x = col_start; + } else if (col_end > visible_end) { + // Columna está a la derecha: scroll para mostrar final de columna + list_state.nav.scroll_x = col_end - @as(i32, @intCast(visible_width)); + } + + // Clamp scroll_x a límites válidos + if (list_state.nav.scroll_x < 0) list_state.nav.scroll_x = 0; + if (list_state.nav.scroll_x > max_scroll_x) list_state.nav.scroll_x = max_scroll_x; +} + // ============================================================================= // Handle: Keyboard (Brain-in-Core pattern) // ============================================================================= @@ -993,12 +1033,14 @@ fn handleKeyboard( visible_rows: usize, total_rows: usize, max_scroll_x: i32, - num_columns: usize, + columns: []const types.ColumnDef, + visible_width: u32, result: *VirtualAdvancedTableResult, ) void { _ = provider; const h_scroll_step: i32 = 40; // Pixels per arrow key press + const num_columns = columns.len; // ========================================================================= // BRAIN-IN-CORE: Delegar toda la lógica de decisión al Core @@ -1007,6 +1049,9 @@ fn handleKeyboard( if (!events.handled) return; + // Guardar columna activa antes del cambio para detectar movimiento + const prev_col = list_state.nav.active_col; + // ========================================================================= // Aplicar acciones de navegación // ========================================================================= @@ -1023,6 +1068,13 @@ fn handleKeyboard( if (events.scroll_left) list_state.scrollLeft(h_scroll_step); if (events.scroll_right) list_state.scrollRight(h_scroll_step, max_scroll_x); + // ========================================================================= + // Auto-scroll horizontal: asegurar que la columna activa sea visible + // ========================================================================= + if (list_state.nav.active_col != prev_col) { + ensureColumnVisible(list_state, columns, visible_width, max_scroll_x); + } + // ========================================================================= // Propagar acciones CRUD al result (el panel las manejará) // =========================================================================