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:
parent
49cf12f7b9
commit
9b2cf2a3dd
1 changed files with 31 additions and 122 deletions
|
|
@ -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
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue