feat(table_core): Selection on focus Excel-style
- Añade selection_start/selection_end a CellEditState - F2/Space selecciona todo el texto al entrar en edición - Typing con selección reemplaza texto seleccionado - Backspace/Delete borra selección si existe - Flechas/Home/End limpian selección - Dibuja highlight azul en ambas tablas (Advanced + Virtual)
This commit is contained in:
parent
91570368cc
commit
dc82340381
4 changed files with 178 additions and 25 deletions
|
|
@ -561,11 +561,28 @@ fn drawEditingOverlay(
|
||||||
// Draw edit text
|
// Draw edit text
|
||||||
const edit_text = table_state.getEditText();
|
const edit_text = table_state.getEditText();
|
||||||
const text_y = cell_y + @as(i32, @intCast((cell_h - 8) / 2));
|
const text_y = cell_y + @as(i32, @intCast((cell_h - 8) / 2));
|
||||||
|
|
||||||
|
// Draw selection highlight if exists (Excel-style)
|
||||||
|
const sel_start = table_state.cell_edit.selection_start;
|
||||||
|
const sel_end = table_state.cell_edit.selection_end;
|
||||||
|
if (sel_start != sel_end and edit_text.len > 0) {
|
||||||
|
const sel_min = @min(sel_start, sel_end);
|
||||||
|
const sel_max = @min(@max(sel_start, sel_end), edit_text.len);
|
||||||
|
if (sel_max > sel_min) {
|
||||||
|
const sel_x = col_x + 4 + @as(i32, @intCast(sel_min * 8));
|
||||||
|
const sel_width = @as(u32, @intCast((sel_max - sel_min) * 8));
|
||||||
|
ctx.pushCommand(Command.rect(sel_x, text_y, sel_width, 8, colors.cell_selection_bg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text (on top of selection)
|
||||||
ctx.pushCommand(Command.text(col_x + 4, text_y, edit_text, colors.text_selected));
|
ctx.pushCommand(Command.text(col_x + 4, text_y, edit_text, colors.text_selected));
|
||||||
|
|
||||||
// Draw cursor
|
// Draw cursor only if no selection
|
||||||
const cursor_x = col_x + 4 + @as(i32, @intCast(table_state.cell_edit.edit_cursor * 8));
|
if (sel_start == sel_end) {
|
||||||
ctx.pushCommand(Command.rect(cursor_x, text_y, 1, 8, colors.text_selected));
|
const cursor_x = col_x + 4 + @as(i32, @intCast(table_state.cell_edit.edit_cursor * 8));
|
||||||
|
ctx.pushCommand(Command.rect(cursor_x, text_y, 1, 8, colors.text_selected));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -881,7 +898,7 @@ fn handleEditingKeyboard(
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
|
||||||
// Usar table_core para procesamiento de teclado (DRY)
|
// Usar table_core para procesamiento de teclado (DRY) con soporte selección
|
||||||
const kb_result = table_core.handleEditingKeyboard(
|
const kb_result = table_core.handleEditingKeyboard(
|
||||||
ctx,
|
ctx,
|
||||||
&table_state.cell_edit.edit_buffer,
|
&table_state.cell_edit.edit_buffer,
|
||||||
|
|
@ -889,6 +906,8 @@ fn handleEditingKeyboard(
|
||||||
&table_state.cell_edit.edit_cursor,
|
&table_state.cell_edit.edit_cursor,
|
||||||
&table_state.cell_edit.escape_count,
|
&table_state.cell_edit.escape_count,
|
||||||
original_text,
|
original_text,
|
||||||
|
&table_state.cell_edit.selection_start,
|
||||||
|
&table_state.cell_edit.selection_end,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Si no se procesó ningún evento, salir
|
// Si no se procesó ningún evento, salir
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,7 @@ pub const TableColors = struct {
|
||||||
// Cell editing
|
// Cell editing
|
||||||
cell_editing_bg: Style.Color = Style.Color.rgb(60, 60, 80),
|
cell_editing_bg: Style.Color = Style.Color.rgb(60, 60, 80),
|
||||||
cell_editing_border: Style.Color = Style.Color.primary,
|
cell_editing_border: Style.Color = Style.Color.primary,
|
||||||
|
cell_selection_bg: Style.Color = Style.Color.rgb(0, 120, 215), // Azul para selección
|
||||||
|
|
||||||
// Borders
|
// Borders
|
||||||
border: Style.Color = Style.Color.rgb(60, 60, 60),
|
border: Style.Color = Style.Color.rgb(60, 60, 60),
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ pub const TableColors = struct {
|
||||||
cell_editing_bg: Style.Color = Style.Color.rgb(255, 255, 255),
|
cell_editing_bg: Style.Color = Style.Color.rgb(255, 255, 255),
|
||||||
cell_editing_border: Style.Color = Style.Color.rgb(0, 120, 215),
|
cell_editing_border: Style.Color = Style.Color.rgb(0, 120, 215),
|
||||||
cell_editing_text: Style.Color = Style.Color.rgb(0, 0, 0),
|
cell_editing_text: Style.Color = Style.Color.rgb(0, 0, 0),
|
||||||
|
cell_selection_bg: Style.Color = Style.Color.rgb(0, 120, 215), // Azul para selección
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
header_bg: Style.Color = Style.Color.rgb(45, 45, 50),
|
header_bg: Style.Color = Style.Color.rgb(45, 45, 50),
|
||||||
|
|
@ -138,6 +139,11 @@ pub const CellEditState = struct {
|
||||||
/// Flag: el valor cambió respecto al original
|
/// Flag: el valor cambió respecto al original
|
||||||
value_changed: bool = false,
|
value_changed: bool = false,
|
||||||
|
|
||||||
|
/// Selección de texto (Excel-style: todo seleccionado al entrar con F2)
|
||||||
|
/// Si selection_start == selection_end, no hay selección (solo cursor)
|
||||||
|
selection_start: usize = 0,
|
||||||
|
selection_end: usize = 0,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
/// Inicia edición de una celda
|
/// Inicia edición de una celda
|
||||||
|
|
@ -155,15 +161,20 @@ pub const CellEditState = struct {
|
||||||
|
|
||||||
// Inicializar buffer de edición
|
// Inicializar buffer de edición
|
||||||
if (initial_char) |c| {
|
if (initial_char) |c| {
|
||||||
// Tecla alfanumérica: empezar con ese caracter
|
// Tecla alfanumérica: empezar con ese caracter, sin selección
|
||||||
self.edit_buffer[0] = c;
|
self.edit_buffer[0] = c;
|
||||||
self.edit_len = 1;
|
self.edit_len = 1;
|
||||||
self.edit_cursor = 1;
|
self.edit_cursor = 1;
|
||||||
|
self.selection_start = 0;
|
||||||
|
self.selection_end = 0;
|
||||||
} else {
|
} else {
|
||||||
// F2/Space/DoubleClick: mostrar valor actual
|
// F2/Space/DoubleClick: mostrar valor actual con TODO seleccionado (Excel-style)
|
||||||
@memcpy(self.edit_buffer[0..orig_len], current_value[0..orig_len]);
|
@memcpy(self.edit_buffer[0..orig_len], current_value[0..orig_len]);
|
||||||
self.edit_len = orig_len;
|
self.edit_len = orig_len;
|
||||||
self.edit_cursor = orig_len;
|
self.edit_cursor = orig_len;
|
||||||
|
// Seleccionar todo el texto
|
||||||
|
self.selection_start = 0;
|
||||||
|
self.selection_end = orig_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,12 +195,25 @@ pub const CellEditState = struct {
|
||||||
return !std.mem.eql(u8, current, original);
|
return !std.mem.eql(u8, current, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verifica si hay texto seleccionado
|
||||||
|
pub fn hasSelection(self: *const Self) bool {
|
||||||
|
return self.selection_start != self.selection_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Limpia la selección (pero mantiene el cursor)
|
||||||
|
pub fn clearSelection(self: *Self) void {
|
||||||
|
self.selection_start = 0;
|
||||||
|
self.selection_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Revierte al valor original (Escape 1)
|
/// Revierte al valor original (Escape 1)
|
||||||
pub fn revertToOriginal(self: *Self) void {
|
pub fn revertToOriginal(self: *Self) void {
|
||||||
const orig = self.getOriginalValue();
|
const orig = self.getOriginalValue();
|
||||||
@memcpy(self.edit_buffer[0..orig.len], orig);
|
@memcpy(self.edit_buffer[0..orig.len], orig);
|
||||||
self.edit_len = orig.len;
|
self.edit_len = orig.len;
|
||||||
self.edit_cursor = orig.len;
|
self.edit_cursor = orig.len;
|
||||||
|
// Limpiar selección al revertir
|
||||||
|
self.clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finaliza edición
|
/// Finaliza edición
|
||||||
|
|
@ -198,6 +222,7 @@ pub const CellEditState = struct {
|
||||||
self.edit_len = 0;
|
self.edit_len = 0;
|
||||||
self.edit_cursor = 0;
|
self.edit_cursor = 0;
|
||||||
self.escape_count = 0;
|
self.escape_count = 0;
|
||||||
|
self.clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resultado de handleEscape
|
/// Resultado de handleEscape
|
||||||
|
|
@ -348,6 +373,8 @@ pub fn drawEditingOverlay(
|
||||||
height: u32,
|
height: u32,
|
||||||
edit_text: []const u8,
|
edit_text: []const u8,
|
||||||
cursor_pos: usize,
|
cursor_pos: usize,
|
||||||
|
selection_start: usize,
|
||||||
|
selection_end: usize,
|
||||||
colors: *const TableColors,
|
colors: *const TableColors,
|
||||||
) void {
|
) void {
|
||||||
// Fondo blanco
|
// Fondo blanco
|
||||||
|
|
@ -359,12 +386,26 @@ pub fn drawEditingOverlay(
|
||||||
// Texto
|
// Texto
|
||||||
const text_y = y + @as(i32, @intCast((height -| 16) / 2));
|
const text_y = y + @as(i32, @intCast((height -| 16) / 2));
|
||||||
const text_to_show = if (edit_text.len > 0) edit_text else "";
|
const text_to_show = if (edit_text.len > 0) edit_text else "";
|
||||||
|
|
||||||
|
// Dibujar selección si existe (Excel-style highlight)
|
||||||
|
if (selection_start != selection_end) {
|
||||||
|
const sel_min = @min(selection_start, selection_end);
|
||||||
|
const sel_max = @max(selection_start, selection_end);
|
||||||
|
const sel_x = x + 4 + @as(i32, @intCast(sel_min * 8)); // 8px por caracter (monospace)
|
||||||
|
const sel_width = @as(u32, @intCast((sel_max - sel_min) * 8));
|
||||||
|
// Color azul semitransparente para selección
|
||||||
|
ctx.pushCommand(Command.rect(sel_x, text_y, sel_width, 16, colors.cell_selection_bg));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texto (encima de la selección)
|
||||||
ctx.pushCommand(Command.text(x + 4, text_y, text_to_show, colors.cell_editing_text));
|
ctx.pushCommand(Command.text(x + 4, text_y, text_to_show, colors.cell_editing_text));
|
||||||
|
|
||||||
// Cursor parpadeante (simplificado: siempre visible)
|
// Cursor parpadeante (simplificado: siempre visible)
|
||||||
// Calcular posición X del cursor basado en caracteres
|
// Solo mostrar cursor si NO hay selección completa
|
||||||
const cursor_x = x + 4 + @as(i32, @intCast(cursor_pos * 8)); // Asumiendo fuente monospace 8px
|
if (selection_start == selection_end) {
|
||||||
ctx.pushCommand(Command.rect(cursor_x, text_y, 2, 16, colors.cell_editing_border));
|
const cursor_x = x + 4 + @as(i32, @intCast(cursor_pos * 8)); // Asumiendo fuente monospace 8px
|
||||||
|
ctx.pushCommand(Command.rect(cursor_x, text_y, 2, 16, colors.cell_editing_border));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dibuja el texto de una celda
|
/// Dibuja el texto de una celda
|
||||||
|
|
@ -716,6 +757,7 @@ pub const EditKeyboardResult = struct {
|
||||||
|
|
||||||
/// Procesa teclado en modo edición
|
/// Procesa teclado en modo edición
|
||||||
/// Modifica edit_buffer, edit_len, edit_cursor según las teclas
|
/// Modifica edit_buffer, edit_len, edit_cursor según las teclas
|
||||||
|
/// Soporta selección Excel-style: typing reemplaza selección
|
||||||
/// Retorna resultado con flags de navegación y si se procesó algún evento
|
/// Retorna resultado con flags de navegación y si se procesó algún evento
|
||||||
pub fn handleEditingKeyboard(
|
pub fn handleEditingKeyboard(
|
||||||
ctx: *Context,
|
ctx: *Context,
|
||||||
|
|
@ -724,9 +766,41 @@ pub fn handleEditingKeyboard(
|
||||||
edit_cursor: *usize,
|
edit_cursor: *usize,
|
||||||
escape_count: *u8,
|
escape_count: *u8,
|
||||||
original_text: ?[]const u8,
|
original_text: ?[]const u8,
|
||||||
|
selection_start: ?*usize,
|
||||||
|
selection_end: ?*usize,
|
||||||
) EditKeyboardResult {
|
) EditKeyboardResult {
|
||||||
var result = EditKeyboardResult{};
|
var result = EditKeyboardResult{};
|
||||||
|
|
||||||
|
// Helper para eliminar texto seleccionado
|
||||||
|
const deleteSelection = struct {
|
||||||
|
fn f(buf: []u8, len: *usize, cursor: *usize, sel_start: *usize, sel_end: *usize) bool {
|
||||||
|
if (sel_start.* == sel_end.*) return false;
|
||||||
|
const min_pos = @min(sel_start.*, sel_end.*);
|
||||||
|
const max_pos = @min(@max(sel_start.*, sel_end.*), len.*);
|
||||||
|
if (max_pos <= min_pos) return false;
|
||||||
|
|
||||||
|
// Mover caracteres después de la selección hacia atrás
|
||||||
|
const chars_to_delete = max_pos - min_pos;
|
||||||
|
var i: usize = min_pos;
|
||||||
|
while (i + chars_to_delete < len.*) : (i += 1) {
|
||||||
|
buf[i] = buf[i + chars_to_delete];
|
||||||
|
}
|
||||||
|
len.* -= chars_to_delete;
|
||||||
|
cursor.* = min_pos;
|
||||||
|
sel_start.* = 0;
|
||||||
|
sel_end.* = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.f;
|
||||||
|
|
||||||
|
// Helper para limpiar selección
|
||||||
|
const clearSelection = struct {
|
||||||
|
fn f(sel_start: ?*usize, sel_end: ?*usize) void {
|
||||||
|
if (sel_start) |s| s.* = 0;
|
||||||
|
if (sel_end) |e| e.* = 0;
|
||||||
|
}
|
||||||
|
}.f;
|
||||||
|
|
||||||
// Procesar eventos de tecla
|
// Procesar eventos de tecla
|
||||||
for (ctx.input.getKeyEvents()) |event| {
|
for (ctx.input.getKeyEvents()) |event| {
|
||||||
if (!event.pressed) continue;
|
if (!event.pressed) continue;
|
||||||
|
|
@ -774,29 +848,41 @@ pub fn handleEditingKeyboard(
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
.left => {
|
.left => {
|
||||||
|
clearSelection(selection_start, selection_end);
|
||||||
if (edit_cursor.* > 0) edit_cursor.* -= 1;
|
if (edit_cursor.* > 0) edit_cursor.* -= 1;
|
||||||
result.handled = true;
|
result.handled = true;
|
||||||
// Reset escape count
|
|
||||||
escape_count.* = 0;
|
escape_count.* = 0;
|
||||||
},
|
},
|
||||||
.right => {
|
.right => {
|
||||||
|
clearSelection(selection_start, selection_end);
|
||||||
if (edit_cursor.* < edit_len.*) edit_cursor.* += 1;
|
if (edit_cursor.* < edit_len.*) edit_cursor.* += 1;
|
||||||
result.handled = true;
|
result.handled = true;
|
||||||
escape_count.* = 0;
|
escape_count.* = 0;
|
||||||
},
|
},
|
||||||
.home => {
|
.home => {
|
||||||
|
clearSelection(selection_start, selection_end);
|
||||||
edit_cursor.* = 0;
|
edit_cursor.* = 0;
|
||||||
result.handled = true;
|
result.handled = true;
|
||||||
escape_count.* = 0;
|
escape_count.* = 0;
|
||||||
},
|
},
|
||||||
.end => {
|
.end => {
|
||||||
|
clearSelection(selection_start, selection_end);
|
||||||
edit_cursor.* = edit_len.*;
|
edit_cursor.* = edit_len.*;
|
||||||
result.handled = true;
|
result.handled = true;
|
||||||
escape_count.* = 0;
|
escape_count.* = 0;
|
||||||
},
|
},
|
||||||
.backspace => {
|
.backspace => {
|
||||||
|
// Si hay selección, borrar selección
|
||||||
|
if (selection_start != null and selection_end != null) {
|
||||||
|
if (deleteSelection(edit_buffer, edit_len, edit_cursor, selection_start.?, selection_end.?)) {
|
||||||
|
result.text_changed = true;
|
||||||
|
result.handled = true;
|
||||||
|
escape_count.* = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sin selección: borrar caracter antes del cursor
|
||||||
if (edit_cursor.* > 0 and edit_len.* > 0) {
|
if (edit_cursor.* > 0 and edit_len.* > 0) {
|
||||||
// Shift characters left
|
|
||||||
const pos = edit_cursor.* - 1;
|
const pos = edit_cursor.* - 1;
|
||||||
var i: usize = pos;
|
var i: usize = pos;
|
||||||
while (i < edit_len.* - 1) : (i += 1) {
|
while (i < edit_len.* - 1) : (i += 1) {
|
||||||
|
|
@ -810,6 +896,16 @@ pub fn handleEditingKeyboard(
|
||||||
escape_count.* = 0;
|
escape_count.* = 0;
|
||||||
},
|
},
|
||||||
.delete => {
|
.delete => {
|
||||||
|
// Si hay selección, borrar selección
|
||||||
|
if (selection_start != null and selection_end != null) {
|
||||||
|
if (deleteSelection(edit_buffer, edit_len, edit_cursor, selection_start.?, selection_end.?)) {
|
||||||
|
result.text_changed = true;
|
||||||
|
result.handled = true;
|
||||||
|
escape_count.* = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sin selección: borrar caracter después del cursor
|
||||||
if (edit_cursor.* < edit_len.*) {
|
if (edit_cursor.* < edit_len.*) {
|
||||||
var i: usize = edit_cursor.*;
|
var i: usize = edit_cursor.*;
|
||||||
while (i < edit_len.* - 1) : (i += 1) {
|
while (i < edit_len.* - 1) : (i += 1) {
|
||||||
|
|
@ -828,6 +924,13 @@ pub fn handleEditingKeyboard(
|
||||||
// Procesar texto ingresado (caracteres imprimibles)
|
// Procesar texto ingresado (caracteres imprimibles)
|
||||||
const text_input = ctx.input.getTextInput();
|
const text_input = ctx.input.getTextInput();
|
||||||
if (text_input.len > 0) {
|
if (text_input.len > 0) {
|
||||||
|
// Si hay selección, borrarla primero (comportamiento Excel/Word)
|
||||||
|
if (selection_start != null and selection_end != null) {
|
||||||
|
if (selection_start.?.* != selection_end.?.*) {
|
||||||
|
_ = deleteSelection(edit_buffer, edit_len, edit_cursor, selection_start.?, selection_end.?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (text_input) |ch| {
|
for (text_input) |ch| {
|
||||||
if (edit_len.* < edit_buffer.len - 1) {
|
if (edit_len.* < edit_buffer.len - 1) {
|
||||||
// Hacer espacio moviendo caracteres hacia la derecha
|
// Hacer espacio moviendo caracteres hacia la derecha
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,31 @@ pub fn drawCellEditor(
|
||||||
// Texto actual
|
// Texto actual
|
||||||
const text = state.getEditText();
|
const text = state.getEditText();
|
||||||
const text_y = geom.y + @as(i32, @intCast((geom.h -| 16) / 2)); // Centrado vertical
|
const text_y = geom.y + @as(i32, @intCast((geom.h -| 16) / 2)); // Centrado vertical
|
||||||
|
|
||||||
|
// Dibujar selección si existe (Excel-style: todo seleccionado al entrar con F2)
|
||||||
|
const sel_start = state.cell_edit.selection_start;
|
||||||
|
const sel_end = state.cell_edit.selection_end;
|
||||||
|
if (sel_start != sel_end and text.len > 0) {
|
||||||
|
const sel_min = @min(sel_start, sel_end);
|
||||||
|
const sel_max = @min(@max(sel_start, sel_end), text.len);
|
||||||
|
if (sel_max > sel_min) {
|
||||||
|
// Calcular posición X del inicio de selección
|
||||||
|
const sel_x_offset = ctx.measureTextToCursor(text, sel_min);
|
||||||
|
const sel_end_offset = ctx.measureTextToCursor(text, sel_max);
|
||||||
|
const sel_width = sel_end_offset - sel_x_offset;
|
||||||
|
if (sel_width > 0) {
|
||||||
|
ctx.pushCommand(Command.rect(
|
||||||
|
geom.x + padding + @as(i32, @intCast(sel_x_offset)),
|
||||||
|
text_y,
|
||||||
|
@intCast(sel_width),
|
||||||
|
16,
|
||||||
|
colors.selection,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texto (encima de la selección)
|
||||||
ctx.pushCommand(Command.text(
|
ctx.pushCommand(Command.text(
|
||||||
geom.x + padding,
|
geom.x + padding,
|
||||||
text_y,
|
text_y,
|
||||||
|
|
@ -88,24 +113,27 @@ pub fn drawCellEditor(
|
||||||
colors.text,
|
colors.text,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Cursor: posición calculada con measureTextToCursor (TTF-aware)
|
// Cursor: solo si NO hay selección activa
|
||||||
const cursor_offset = ctx.measureTextToCursor(text, state.cell_edit.edit_cursor);
|
const has_selection = sel_start != sel_end;
|
||||||
const cursor_x = geom.x + padding + @as(i32, @intCast(cursor_offset));
|
if (!has_selection) {
|
||||||
|
const cursor_offset = ctx.measureTextToCursor(text, state.cell_edit.edit_cursor);
|
||||||
|
const cursor_x = geom.x + padding + @as(i32, @intCast(cursor_offset));
|
||||||
|
|
||||||
// Visibilidad del cursor usando función compartida de Context
|
// Visibilidad del cursor usando función compartida de Context
|
||||||
const cursor_visible = ctx.isCursorVisible(state.last_edit_time_ms);
|
const cursor_visible = ctx.isCursorVisible(state.last_edit_time_ms);
|
||||||
|
|
||||||
if (cursor_visible) {
|
if (cursor_visible) {
|
||||||
ctx.pushCommand(Command.rect(
|
ctx.pushCommand(Command.rect(
|
||||||
cursor_x,
|
cursor_x,
|
||||||
text_y,
|
text_y,
|
||||||
2, // 2px de ancho (más visible)
|
2, // 2px de ancho (más visible)
|
||||||
16, // Altura del texto
|
16, // Altura del texto
|
||||||
colors.cursor,
|
colors.cursor,
|
||||||
));
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Procesar input de teclado usando table_core
|
// Procesar input de teclado usando table_core (con soporte selección)
|
||||||
const original_text = state.getOriginalValue();
|
const original_text = state.getOriginalValue();
|
||||||
const kb_result = table_core.handleEditingKeyboard(
|
const kb_result = table_core.handleEditingKeyboard(
|
||||||
ctx,
|
ctx,
|
||||||
|
|
@ -114,6 +142,8 @@ pub fn drawCellEditor(
|
||||||
&state.cell_edit.edit_cursor,
|
&state.cell_edit.edit_cursor,
|
||||||
&state.cell_edit.escape_count,
|
&state.cell_edit.escape_count,
|
||||||
if (original_text.len > 0) original_text else null,
|
if (original_text.len > 0) original_text else null,
|
||||||
|
&state.cell_edit.selection_start,
|
||||||
|
&state.cell_edit.selection_end,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mapear resultado de table_core a CellEditorResult
|
// Mapear resultado de table_core a CellEditorResult
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue