refactor(cell_editor): Use table_core.handleEditingKeyboard instead of duplicated code

- Import and use table_core for keyboard handling
- Re-export NavigateDirection from table_core
- Map table_core.EditKeyboardResult to CellEditorResult
- Remove ~100 lines of duplicated keyboard handling code
- Add 'handled' field to CellEditorResult
This commit is contained in:
reugenio 2025-12-27 12:10:59 +01:00
parent 49cf12f7b9
commit 9b2cf2a3dd

View file

@ -1,19 +1,22 @@
//! CellEditor - Editor de celda overlay para edición inline //! CellEditor - Editor de celda overlay para edición inline
//! //!
//! Dibuja un campo de texto sobre una celda para edición estilo Excel. //! Dibuja un campo de texto sobre una celda para edición estilo Excel.
//! Utiliza el edit_buffer del VirtualAdvancedTableState. //! Utiliza table_core.handleEditingKeyboard() para procesar teclado.
const std = @import("std"); const std = @import("std");
const Context = @import("../../core/context.zig").Context; const Context = @import("../../core/context.zig").Context;
const Command = @import("../../core/command.zig"); const Command = @import("../../core/command.zig");
const Style = @import("../../core/style.zig"); const Style = @import("../../core/style.zig");
const Input = @import("../../core/input.zig");
const types = @import("types.zig"); const types = @import("types.zig");
const state_mod = @import("state.zig"); const state_mod = @import("state.zig");
const table_core = @import("../table_core.zig");
const CellGeometry = types.CellGeometry; const CellGeometry = types.CellGeometry;
const VirtualAdvancedTableState = state_mod.VirtualAdvancedTableState; const VirtualAdvancedTableState = state_mod.VirtualAdvancedTableState;
// Re-exportar NavigateDirection desde table_core para compatibilidad
pub const NavigateDirection = table_core.NavigateDirection;
/// Colores del editor de celda /// Colores del editor de celda
pub const CellEditorColors = struct { pub const CellEditorColors = struct {
background: Style.Color = Style.Color.rgb(255, 255, 255), background: Style.Color = Style.Color.rgb(255, 255, 255),
@ -24,8 +27,9 @@ pub const CellEditorColors = struct {
}; };
/// Resultado del procesamiento del CellEditor /// Resultado del procesamiento del CellEditor
/// Usa table_core.NavigateDirection para navegación
pub const CellEditorResult = struct { pub const CellEditorResult = struct {
/// El usuario presionó Enter o Tab (commit) /// El usuario presionó Enter, Tab, o flechas (commit)
committed: bool = false, committed: bool = false,
/// El usuario presionó Escape /// El usuario presionó Escape
@ -37,13 +41,8 @@ pub const CellEditorResult = struct {
/// Navegación solicitada después de commit /// Navegación solicitada después de commit
navigate: NavigateDirection = .none, navigate: NavigateDirection = .none,
pub const NavigateDirection = enum { /// Se procesó algún evento de teclado
none, handled: bool = false,
next_cell, // Tab
prev_cell, // Shift+Tab
next_row, // Enter o
prev_row, //
};
}; };
/// Dibuja el editor de celda overlay /// Dibuja el editor de celda overlay
@ -106,8 +105,28 @@ pub fn drawCellEditor(
)); ));
} }
// Procesar input de teclado // Procesar input de teclado usando table_core
result = handleCellEditorInput(ctx, state); const original_text = state.getOriginalValue();
const kb_result = table_core.handleEditingKeyboard(
ctx,
&state.edit_buffer,
&state.edit_buffer_len,
&state.edit_cursor,
&state.escape_count,
if (original_text.len > 0) original_text else null,
);
// Mapear resultado de table_core a CellEditorResult
result.committed = kb_result.committed;
result.escaped = kb_result.cancelled;
result.text_changed = kb_result.text_changed;
result.navigate = kb_result.navigate;
result.handled = kb_result.handled;
// Escape con revert no es "escaped" sino solo revertir texto
if (kb_result.reverted) {
result.escaped = false; // No cerrar editor, solo revertir
}
// Actualizar tiempo de última edición si hubo cambios // Actualizar tiempo de última edición si hubo cambios
if (result.text_changed) { if (result.text_changed) {
@ -117,116 +136,6 @@ pub fn drawCellEditor(
return result; return result;
} }
/// Procesa input de teclado para el editor
fn handleCellEditorInput(ctx: *Context, state: *VirtualAdvancedTableState) CellEditorResult {
var result = CellEditorResult{};
// Procesar eventos de tecla
for (ctx.input.getKeyEvents()) |event| {
if (!event.pressed) continue;
switch (event.key) {
.escape => {
result.escaped = true;
return result;
},
.enter => {
result.committed = true;
result.navigate = .next_row;
return result;
},
.tab => {
result.committed = true;
if (event.modifiers.shift) {
result.navigate = .prev_cell;
} else {
result.navigate = .next_cell;
}
return result;
},
.up => {
result.committed = true;
result.navigate = .prev_row;
return result;
},
.down => {
result.committed = true;
result.navigate = .next_row;
return result;
},
.left => {
// Mover cursor a la izquierda
if (state.edit_cursor > 0) {
state.edit_cursor -= 1;
}
},
.right => {
// Mover cursor a la derecha
if (state.edit_cursor < state.edit_buffer_len) {
state.edit_cursor += 1;
}
},
.home => {
state.edit_cursor = 0;
},
.end => {
state.edit_cursor = state.edit_buffer_len;
},
.backspace => {
if (state.edit_cursor > 0 and state.edit_buffer_len > 0) {
// Eliminar caracter antes del cursor
const pos = state.edit_cursor - 1;
// Mover caracteres hacia la izquierda
std.mem.copyForwards(
u8,
state.edit_buffer[pos .. state.edit_buffer_len - 1],
state.edit_buffer[pos + 1 .. state.edit_buffer_len],
);
state.edit_buffer_len -= 1;
state.edit_cursor -= 1;
result.text_changed = true;
}
},
.delete => {
if (state.edit_cursor < state.edit_buffer_len) {
// Eliminar caracter en el cursor
std.mem.copyForwards(
u8,
state.edit_buffer[state.edit_cursor .. state.edit_buffer_len - 1],
state.edit_buffer[state.edit_cursor + 1 .. state.edit_buffer_len],
);
state.edit_buffer_len -= 1;
result.text_changed = true;
}
},
else => {},
}
}
// Procesar texto ingresado (caracteres imprimibles)
const text_input = ctx.input.getTextInput();
if (text_input.len > 0) {
// Insertar caracteres en la posición del cursor
for (text_input) |c| {
if (state.edit_buffer_len < state.edit_buffer.len - 1) {
// Hacer espacio moviendo caracteres hacia la derecha
if (state.edit_cursor < state.edit_buffer_len) {
var i = state.edit_buffer_len;
while (i > state.edit_cursor) : (i -= 1) {
state.edit_buffer[i] = state.edit_buffer[i - 1];
}
}
state.edit_buffer[state.edit_cursor] = c;
state.edit_buffer_len += 1;
state.edit_cursor += 1;
result.text_changed = true;
}
}
}
return result;
}
// ============================================================================= // =============================================================================
// Tests // Tests
// ============================================================================= // =============================================================================