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(
ctx: *Context,
@ -585,11 +588,15 @@ fn handleKeyboard(
const config = table_schema.config;
const col_count = table_schema.columns.len;
// Use navKeyPressed for navigation (includes key repeats)
if (ctx.input.navKeyPressed()) |nav_key| {
switch (nav_key) {
.up => {
if (table_state.selected_row > 0) {
// =========================================================================
// BRAIN-IN-CORE: Delegar toda la lógica de decisión al Core
// =========================================================================
const events = table_core.processTableEvents(ctx, table_state.isEditing());
// =========================================================================
// 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_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col);
@ -597,9 +604,8 @@ fn handleKeyboard(
result.selected_row = new_row;
result.selected_col = new_col;
}
},
.down => {
if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
if (events.move_down and table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
const new_row: usize = @intCast(table_state.selected_row + 1);
const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col);
@ -607,9 +613,8 @@ fn handleKeyboard(
result.selected_row = new_row;
result.selected_col = new_col;
}
},
.left => {
if (table_state.selected_col > 0) {
if (events.move_left and table_state.selected_col > 0) {
const new_row: usize = @intCast(@max(0, table_state.selected_row));
const new_col: usize = @intCast(table_state.selected_col - 1);
table_state.selectCell(new_row, new_col);
@ -617,9 +622,8 @@ fn handleKeyboard(
result.selected_row = new_row;
result.selected_col = new_col;
}
},
.right => {
if (table_state.selected_col < @as(i32, @intCast(col_count)) - 1) {
if (events.move_right and table_state.selected_col < @as(i32, @intCast(col_count)) - 1) {
const new_row: usize = @intCast(@max(0, table_state.selected_row));
const new_col: usize = @intCast(table_state.selected_col + 1);
table_state.selectCell(new_row, new_col);
@ -627,16 +631,17 @@ fn handleKeyboard(
result.selected_row = new_row;
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_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col);
result.selection_changed = true;
result.selected_row = new_row;
result.selected_col = new_col;
},
.page_down => {
}
if (events.page_down) {
const new_row: usize = @intCast(@min(
@as(i32, @intCast(row_count)) - 1,
table_state.selected_row + @as(i32, @intCast(visible_rows)),
@ -646,59 +651,46 @@ fn handleKeyboard(
result.selection_changed = true;
result.selected_row = new_row;
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);
result.selection_changed = true;
result.selected_row = new_row;
result.selected_col = new_col;
},
.end => {
var new_row: usize = undefined;
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;
}
} else if (events.go_to_last_row) {
const new_row: usize = if (row_count > 0) row_count - 1 else 0;
const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col);
result.selection_changed = true;
result.selected_row = new_row;
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)) {
const shift = ctx.input.modifiers.shift;
if (shift) {
// =========================================================================
// Tab navigation (usando lógica del Core + config local)
// =========================================================================
if (events.tab_out and config.handle_tab) {
if (events.tab_shift) {
// Shift+Tab: move left, wrap to previous row
if (table_state.selected_col > 0) {
table_state.selectCell(
@ -707,7 +699,6 @@ fn handleKeyboard(
);
result.selection_changed = true;
} else if (table_state.selected_row > 0 and config.wrap_navigation) {
// Wrap to end of previous row
table_state.selectCell(
@intCast(table_state.selected_row - 1),
col_count - 1,
@ -723,7 +714,6 @@ fn handleKeyboard(
);
result.selection_changed = true;
} 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(
@intCast(table_state.selected_row + 1),
0,
@ -733,22 +723,21 @@ fn handleKeyboard(
}
}
// Start editing with F2, Enter, or Space (empty)
if (config.allow_edit) {
const start_edit_key = ctx.input.keyPressed(.f2) or ctx.input.keyPressed(.enter);
const start_empty = ctx.input.keyPressed(.space);
if (start_edit_key or start_empty) {
// =========================================================================
// Inicio de edición (F2, Space, o tecla alfanumérica desde el Core)
// =========================================================================
if (events.start_editing and config.allow_edit) {
if (table_state.selected_row >= 0 and table_state.selected_col >= 0) {
const col_idx: usize = @intCast(table_state.selected_col);
if (col_idx < table_schema.columns.len and table_schema.columns[col_idx].editable) {
if (table_state.getRow(@intCast(table_state.selected_row))) |row| {
const value = row.get(table_schema.columns[col_idx].name);
if (start_empty) {
// Espacio: empezar vacío
table_state.startEditing("");
if (events.initial_char) |ch| {
// Tecla alfanumérica: empezar con ese caracter
var char_buf: [1]u8 = .{ch};
table_state.startEditing(&char_buf);
} else {
// F2/Enter: empezar con valor actual
// F2/Space: empezar con valor actual
var format_buf: [128]u8 = undefined;
const text = value.format(&format_buf);
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) {
// Ctrl+N: Insert row at current position
if (ctx.input.keyPressed(.n) and ctx.input.modifiers.ctrl) {
// Ctrl+N: Insert row
if (events.insert_row) {
const insert_idx: usize = if (table_state.selected_row >= 0)
@intCast(table_state.selected_row)
else
@ -776,8 +766,8 @@ fn handleKeyboard(
} else |_| {}
}
// Ctrl+Delete: Delete current row
if (ctx.input.keyPressed(.delete) and ctx.input.modifiers.ctrl) {
// Ctrl+Delete o Ctrl+B: Delete row
if (events.delete_row) {
if (table_state.selected_row >= 0) {
const delete_idx: usize = @intCast(table_state.selected_row);
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) {
table_state.selectAllRows();
result.selection_changed = true;
}
// Type-to-edit or incremental search
// Behavior: If current cell is editable start editing with typed char
// If not editable incremental search in first column
if (!ctx.input.modifiers.ctrl and !ctx.input.modifiers.alt) {
// =========================================================================
// Búsqueda incremental (solo si NO se inició edición)
// Solo para celdas no editables - lógica específica de AdvancedTable
// =========================================================================
if (!events.start_editing and !ctx.input.modifiers.ctrl and !ctx.input.modifiers.alt) {
if (ctx.input.text_input_len > 0) {
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: {
if (!config.allow_edit) 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;
};
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 {
if (!current_cell_editable) {
// Incremental search (type-to-search) in first column
for (text) |char| {
if (char >= 32 and char < 127) {