refactor(advanced_table): Brain-in-Core pattern - usar processTableEvents()

Completa la limpieza del patrón Brain-in-Core:
- AdvancedTable ahora usa table_core.processTableEvents() igual que VirtualAdvancedTable
- Eliminada lógica duplicada de navegación (flechas, Home, End, PageUp/Down)
- Eliminada lógica duplicada de atajos (Ctrl+Home/End, Ctrl+N, Ctrl+Delete)
- Ctrl+B ahora funciona en ambas tablas (alias de Ctrl+Delete)
- Mantiene lógica específica: búsqueda incremental, Ctrl+A select all

Checklist Gemini completado:
[x] Manejo de flechas en Core
[x] Manejo de Ctrl+N en Core
[x] Ctrl+B implementado
[x] Ctrl+Shift+1 activa ordenación
This commit is contained in:
reugenio 2025-12-27 21:16:06 +01:00
parent aed811a102
commit 0ca97c2ba3

View file

@ -569,8 +569,11 @@ fn drawEditingOverlay(
} }
// ============================================================================= // =============================================================================
// Keyboard Handling // Keyboard Handling (Brain-in-Core pattern)
// ============================================================================= // =============================================================================
//
// Arquitectura: TODA la lógica de decisión está en table_core.processTableEvents()
// Este handler solo aplica flags y maneja lógica específica de AdvancedTable.
fn handleKeyboard( fn handleKeyboard(
ctx: *Context, ctx: *Context,
@ -585,11 +588,15 @@ fn handleKeyboard(
const config = table_schema.config; const config = table_schema.config;
const col_count = table_schema.columns.len; const col_count = table_schema.columns.len;
// Use navKeyPressed for navigation (includes key repeats) // =========================================================================
if (ctx.input.navKeyPressed()) |nav_key| { // BRAIN-IN-CORE: Delegar toda la lógica de decisión al Core
switch (nav_key) { // =========================================================================
.up => { const events = table_core.processTableEvents(ctx, table_state.isEditing());
if (table_state.selected_row > 0) {
// =========================================================================
// Aplicar navegación desde el Core
// =========================================================================
if (events.move_up and table_state.selected_row > 0) {
const new_row: usize = @intCast(table_state.selected_row - 1); const new_row: usize = @intCast(table_state.selected_row - 1);
const new_col: usize = @intCast(@max(0, table_state.selected_col)); const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
@ -597,9 +604,8 @@ fn handleKeyboard(
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
} }
},
.down => { if (events.move_down and table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
const new_row: usize = @intCast(table_state.selected_row + 1); const new_row: usize = @intCast(table_state.selected_row + 1);
const new_col: usize = @intCast(@max(0, table_state.selected_col)); const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
@ -607,9 +613,8 @@ fn handleKeyboard(
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
} }
},
.left => { if (events.move_left and table_state.selected_col > 0) {
if (table_state.selected_col > 0) {
const new_row: usize = @intCast(@max(0, table_state.selected_row)); const new_row: usize = @intCast(@max(0, table_state.selected_row));
const new_col: usize = @intCast(table_state.selected_col - 1); const new_col: usize = @intCast(table_state.selected_col - 1);
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
@ -617,9 +622,8 @@ fn handleKeyboard(
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
} }
},
.right => { if (events.move_right and table_state.selected_col < @as(i32, @intCast(col_count)) - 1) {
if (table_state.selected_col < @as(i32, @intCast(col_count)) - 1) {
const new_row: usize = @intCast(@max(0, table_state.selected_row)); const new_row: usize = @intCast(@max(0, table_state.selected_row));
const new_col: usize = @intCast(table_state.selected_col + 1); const new_col: usize = @intCast(table_state.selected_col + 1);
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
@ -627,16 +631,17 @@ fn handleKeyboard(
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
} }
},
.page_up => { if (events.page_up) {
const new_row: usize = @intCast(@max(0, table_state.selected_row - @as(i32, @intCast(visible_rows)))); const new_row: usize = @intCast(@max(0, table_state.selected_row - @as(i32, @intCast(visible_rows))));
const new_col: usize = @intCast(@max(0, table_state.selected_col)); const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
result.selection_changed = true; result.selection_changed = true;
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
}, }
.page_down => {
if (events.page_down) {
const new_row: usize = @intCast(@min( const new_row: usize = @intCast(@min(
@as(i32, @intCast(row_count)) - 1, @as(i32, @intCast(row_count)) - 1,
table_state.selected_row + @as(i32, @intCast(visible_rows)), table_state.selected_row + @as(i32, @intCast(visible_rows)),
@ -646,59 +651,46 @@ fn handleKeyboard(
result.selection_changed = true; result.selection_changed = true;
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
},
.home => {
var new_row: usize = undefined;
var new_col: usize = undefined;
if (ctx.input.modifiers.ctrl) {
// Ctrl+Home: first cell
new_row = 0;
new_col = 0;
} else {
// Home: first column
new_row = @intCast(@max(0, table_state.selected_row));
new_col = 0;
} }
if (events.go_to_first_col) {
const new_row: usize = if (events.go_to_first_row) 0 else @intCast(@max(0, table_state.selected_row));
table_state.selectCell(new_row, 0);
result.selection_changed = true;
result.selected_row = new_row;
result.selected_col = 0;
} else if (events.go_to_first_row) {
const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(0, new_col);
result.selection_changed = true;
result.selected_row = 0;
result.selected_col = new_col;
}
if (events.go_to_last_col) {
const new_row: usize = if (events.go_to_last_row)
(if (row_count > 0) row_count - 1 else 0)
else
@intCast(@max(0, table_state.selected_row));
const new_col: usize = col_count - 1;
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
result.selection_changed = true; result.selection_changed = true;
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
}, } else if (events.go_to_last_row) {
.end => { const new_row: usize = if (row_count > 0) row_count - 1 else 0;
var new_row: usize = undefined; const new_col: usize = @intCast(@max(0, table_state.selected_col));
var new_col: usize = undefined;
if (ctx.input.modifiers.ctrl) {
// Ctrl+End: last cell
new_row = if (row_count > 0) row_count - 1 else 0;
new_col = col_count - 1;
} else {
// End: last column
new_row = @intCast(@max(0, table_state.selected_row));
new_col = col_count - 1;
}
table_state.selectCell(new_row, new_col); table_state.selectCell(new_row, new_col);
result.selection_changed = true; result.selection_changed = true;
result.selected_row = new_row; result.selected_row = new_row;
result.selected_col = new_col; result.selected_col = new_col;
},
.tab => {
if (config.handle_tab) {
// Tab navigation handled below
}
},
.enter => {
// Enter to start editing handled below
},
.escape => {},
else => {},
}
} }
// Tab navigation (if handle_tab is enabled) // =========================================================================
if (config.handle_tab and ctx.input.keyPressed(.tab)) { // Tab navigation (usando lógica del Core + config local)
const shift = ctx.input.modifiers.shift; // =========================================================================
if (events.tab_out and config.handle_tab) {
if (shift) { if (events.tab_shift) {
// Shift+Tab: move left, wrap to previous row // Shift+Tab: move left, wrap to previous row
if (table_state.selected_col > 0) { if (table_state.selected_col > 0) {
table_state.selectCell( table_state.selectCell(
@ -707,7 +699,6 @@ fn handleKeyboard(
); );
result.selection_changed = true; result.selection_changed = true;
} else if (table_state.selected_row > 0 and config.wrap_navigation) { } else if (table_state.selected_row > 0 and config.wrap_navigation) {
// Wrap to end of previous row
table_state.selectCell( table_state.selectCell(
@intCast(table_state.selected_row - 1), @intCast(table_state.selected_row - 1),
col_count - 1, col_count - 1,
@ -723,7 +714,6 @@ fn handleKeyboard(
); );
result.selection_changed = true; result.selection_changed = true;
} else if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1 and config.wrap_navigation) { } else if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1 and config.wrap_navigation) {
// Wrap to beginning of next row
table_state.selectCell( table_state.selectCell(
@intCast(table_state.selected_row + 1), @intCast(table_state.selected_row + 1),
0, 0,
@ -733,22 +723,21 @@ fn handleKeyboard(
} }
} }
// Start editing with F2, Enter, or Space (empty) // =========================================================================
if (config.allow_edit) { // Inicio de edición (F2, Space, o tecla alfanumérica desde el Core)
const start_edit_key = ctx.input.keyPressed(.f2) or ctx.input.keyPressed(.enter); // =========================================================================
const start_empty = ctx.input.keyPressed(.space); if (events.start_editing and config.allow_edit) {
if (start_edit_key or start_empty) {
if (table_state.selected_row >= 0 and table_state.selected_col >= 0) { if (table_state.selected_row >= 0 and table_state.selected_col >= 0) {
const col_idx: usize = @intCast(table_state.selected_col); const col_idx: usize = @intCast(table_state.selected_col);
if (col_idx < table_schema.columns.len and table_schema.columns[col_idx].editable) { if (col_idx < table_schema.columns.len and table_schema.columns[col_idx].editable) {
if (table_state.getRow(@intCast(table_state.selected_row))) |row| { if (table_state.getRow(@intCast(table_state.selected_row))) |row| {
const value = row.get(table_schema.columns[col_idx].name); const value = row.get(table_schema.columns[col_idx].name);
if (start_empty) { if (events.initial_char) |ch| {
// Espacio: empezar vacío // Tecla alfanumérica: empezar con ese caracter
table_state.startEditing(""); var char_buf: [1]u8 = .{ch};
table_state.startEditing(&char_buf);
} else { } else {
// F2/Enter: empezar con valor actual // F2/Space: empezar con valor actual
var format_buf: [128]u8 = undefined; var format_buf: [128]u8 = undefined;
const text = value.format(&format_buf); const text = value.format(&format_buf);
table_state.startEditing(text); table_state.startEditing(text);
@ -759,12 +748,13 @@ fn handleKeyboard(
} }
} }
} }
}
// Row operations (if allowed) // =========================================================================
// Operaciones CRUD (Ctrl+N, Ctrl+Delete, Ctrl+B desde el Core)
// =========================================================================
if (config.allow_row_operations) { if (config.allow_row_operations) {
// Ctrl+N: Insert row at current position // Ctrl+N: Insert row
if (ctx.input.keyPressed(.n) and ctx.input.modifiers.ctrl) { if (events.insert_row) {
const insert_idx: usize = if (table_state.selected_row >= 0) const insert_idx: usize = if (table_state.selected_row >= 0)
@intCast(table_state.selected_row) @intCast(table_state.selected_row)
else else
@ -776,8 +766,8 @@ fn handleKeyboard(
} else |_| {} } else |_| {}
} }
// Ctrl+Delete: Delete current row // Ctrl+Delete o Ctrl+B: Delete row
if (ctx.input.keyPressed(.delete) and ctx.input.modifiers.ctrl) { if (events.delete_row) {
if (table_state.selected_row >= 0) { if (table_state.selected_row >= 0) {
const delete_idx: usize = @intCast(table_state.selected_row); const delete_idx: usize = @intCast(table_state.selected_row);
table_state.deleteRow(delete_idx); table_state.deleteRow(delete_idx);
@ -795,20 +785,23 @@ fn handleKeyboard(
} }
} }
// Ctrl+A: Select all rows (if multi-select enabled) // =========================================================================
// Ctrl+A: Select all (lógica específica de AdvancedTable)
// =========================================================================
if (config.allow_multi_select and ctx.input.keyPressed(.a) and ctx.input.modifiers.ctrl) { if (config.allow_multi_select and ctx.input.keyPressed(.a) and ctx.input.modifiers.ctrl) {
table_state.selectAllRows(); table_state.selectAllRows();
result.selection_changed = true; result.selection_changed = true;
} }
// Type-to-edit or incremental search // =========================================================================
// Behavior: If current cell is editable start editing with typed char // Búsqueda incremental (solo si NO se inició edición)
// If not editable incremental search in first column // Solo para celdas no editables - lógica específica de AdvancedTable
if (!ctx.input.modifiers.ctrl and !ctx.input.modifiers.alt) { // =========================================================================
if (!events.start_editing and !ctx.input.modifiers.ctrl and !ctx.input.modifiers.alt) {
if (ctx.input.text_input_len > 0) { if (ctx.input.text_input_len > 0) {
const text = ctx.input.text_input[0..ctx.input.text_input_len]; const text = ctx.input.text_input[0..ctx.input.text_input_len];
// Check if current cell is editable // Solo búsqueda si la celda actual NO es editable
const current_cell_editable = blk: { const current_cell_editable = blk: {
if (!config.allow_edit) break :blk false; if (!config.allow_edit) break :blk false;
if (table_state.selected_row < 0 or table_state.selected_col < 0) break :blk false; if (table_state.selected_row < 0 or table_state.selected_col < 0) break :blk false;
@ -817,19 +810,7 @@ fn handleKeyboard(
break :blk table_schema.columns[col_idx].editable; break :blk table_schema.columns[col_idx].editable;
}; };
if (current_cell_editable) { if (!current_cell_editable) {
// Start editing with first typed character
if (text.len > 0 and text[0] >= 32 and text[0] < 127) {
if (table_state.getRow(@intCast(table_state.selected_row))) |row| {
const col_idx: usize = @intCast(table_state.selected_col);
const value = row.get(table_schema.columns[col_idx].name);
// Start with the typed text (replaces content)
table_state.startEditing(text);
table_state.original_value = value;
result.edit_started = true;
}
}
} else {
// Incremental search (type-to-search) in first column // Incremental search (type-to-search) in first column
for (text) |char| { for (text) |char| {
if (char >= 32 and char < 127) { if (char >= 32 and char < 127) {