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(
|
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) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue