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:
parent
aed811a102
commit
0ca97c2ba3
1 changed files with 141 additions and 160 deletions
|
|
@ -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,120 +588,109 @@ 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) {
|
||||
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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
},
|
||||
.down => {
|
||||
if (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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
},
|
||||
.left => {
|
||||
if (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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
},
|
||||
.right => {
|
||||
if (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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
},
|
||||
.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 => {
|
||||
const new_row: usize = @intCast(@min(
|
||||
@as(i32, @intCast(row_count)) - 1,
|
||||
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;
|
||||
},
|
||||
.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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 => {},
|
||||
}
|
||||
// =========================================================================
|
||||
// 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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
|
||||
// Tab navigation (if handle_tab is enabled)
|
||||
if (config.handle_tab and ctx.input.keyPressed(.tab)) {
|
||||
const shift = ctx.input.modifiers.shift;
|
||||
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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
|
||||
if (shift) {
|
||||
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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
|
||||
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);
|
||||
result.selection_changed = true;
|
||||
result.selected_row = new_row;
|
||||
result.selected_col = new_col;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)),
|
||||
));
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
} 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 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,38 +723,38 @@ 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) {
|
||||
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("");
|
||||
} else {
|
||||
// F2/Enter: empezar con valor actual
|
||||
var format_buf: [128]u8 = undefined;
|
||||
const text = value.format(&format_buf);
|
||||
table_state.startEditing(text);
|
||||
}
|
||||
table_state.original_value = value;
|
||||
result.edit_started = true;
|
||||
// =========================================================================
|
||||
// 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 (events.initial_char) |ch| {
|
||||
// Tecla alfanumérica: empezar con ese caracter
|
||||
var char_buf: [1]u8 = .{ch};
|
||||
table_state.startEditing(&char_buf);
|
||||
} else {
|
||||
// F2/Space: empezar con valor actual
|
||||
var format_buf: [128]u8 = undefined;
|
||||
const text = value.format(&format_buf);
|
||||
table_state.startEditing(text);
|
||||
}
|
||||
table_state.original_value = value;
|
||||
result.edit_started = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue