refactor: Remove injection logic, prepare for Modo Inserción Cronológico
- Remove injected_row_idx, injected_committed from VirtualAdvancedTableState - Remove is_injected, injection_index from RowEditBuffer and RowCommitInfo - Remove startInjectedEdit() method - Simplify PagedDataSource (no injection offset) - Simplify drawRowsWithDataSource (no injection handling) - Add is_insertion_mode, insertion_session_active to State - Add enterInsertionMode(), exitInsertionMode(), isInInsertionMode() methods - Ctrl+N now emits insert_row_requested for Panel to handle Part of Modo Inserción Cronológico implementation.
This commit is contained in:
parent
3a6398e90d
commit
c9bdf56a80
5 changed files with 41 additions and 253 deletions
|
|
@ -807,8 +807,8 @@ fn handleKeyboard(
|
||||||
0;
|
0;
|
||||||
if (table_state.insertRow(insert_idx)) |new_idx| {
|
if (table_state.insertRow(insert_idx)) |new_idx| {
|
||||||
table_state.selectCell(new_idx, 0);
|
table_state.selectCell(new_idx, 0);
|
||||||
// Inicializar buffer para fila inyectada (Excel-style)
|
// Inicializar buffer para nueva fila (Excel-style)
|
||||||
table_state.row_edit_buffer.startInjectedEdit(new_idx);
|
table_state.row_edit_buffer.startEdit(table_core.NEW_ROW_ID, new_idx, true);
|
||||||
result.row_inserted = true;
|
result.row_inserted = true;
|
||||||
result.selection_changed = true;
|
result.selection_changed = true;
|
||||||
} else |_| {}
|
} else |_| {}
|
||||||
|
|
|
||||||
|
|
@ -678,10 +678,12 @@ pub fn drawRowsWithDataSource(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtener texto de la celda
|
// Obtener texto de la celda
|
||||||
// PRIORIDAD 1: Valor pendiente en RowEditBuffer (lo que el usuario tecleó)
|
// PRIORIDAD 1: Fila con cambios pendientes → leer del buffer
|
||||||
// PRIORIDAD 2: Valor del DataSource (BD o memoria)
|
// PRIORIDAD 2: Leer del DataSource (BD o memoria)
|
||||||
var cell_text: []const u8 = "";
|
var cell_text: []const u8 = "";
|
||||||
const row_id = datasource.getRowId(row_idx);
|
const row_id = datasource.getRowId(row_idx);
|
||||||
|
|
||||||
|
// Intentar leer del buffer si tiene cambios pendientes
|
||||||
if (config.edit_buffer) |eb| {
|
if (config.edit_buffer) |eb| {
|
||||||
if (eb.row_id == row_id) {
|
if (eb.row_id == row_id) {
|
||||||
if (eb.getPendingValue(col_idx)) |pending| {
|
if (eb.getPendingValue(col_idx)) |pending| {
|
||||||
|
|
@ -689,6 +691,8 @@ pub fn drawRowsWithDataSource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ir al datasource si no tenemos texto del buffer
|
||||||
if (cell_text.len == 0) {
|
if (cell_text.len == 0) {
|
||||||
cell_text = datasource.getCellValueInto(row_idx, col_idx, cell_buffer);
|
cell_text = datasource.getCellValueInto(row_idx, col_idx, cell_buffer);
|
||||||
}
|
}
|
||||||
|
|
@ -1309,12 +1313,6 @@ pub const RowEditBuffer = struct {
|
||||||
/// Hay cambios pendientes
|
/// Hay cambios pendientes
|
||||||
has_changes: bool = false,
|
has_changes: bool = false,
|
||||||
|
|
||||||
/// True si es una fila inyectada (Ctrl+N entre líneas)
|
|
||||||
is_injected: bool = false,
|
|
||||||
|
|
||||||
/// Índice donde se insertó la fila inyectada (null si no es inyección)
|
|
||||||
injection_index: ?usize = null,
|
|
||||||
|
|
||||||
/// Buffers de valores por columna (almacenamiento fijo)
|
/// Buffers de valores por columna (almacenamiento fijo)
|
||||||
value_buffers: [MAX_PENDING_COLUMNS][MAX_CELL_VALUE_LEN]u8 = undefined,
|
value_buffers: [MAX_PENDING_COLUMNS][MAX_CELL_VALUE_LEN]u8 = undefined,
|
||||||
|
|
||||||
|
|
@ -1333,24 +1331,6 @@ pub const RowEditBuffer = struct {
|
||||||
self.row_index = row_index;
|
self.row_index = row_index;
|
||||||
self.is_new_row = is_new;
|
self.is_new_row = is_new;
|
||||||
self.has_changes = false;
|
self.has_changes = false;
|
||||||
self.is_injected = false;
|
|
||||||
self.injection_index = null;
|
|
||||||
self.change_count = 0;
|
|
||||||
for (0..MAX_PENDING_COLUMNS) |i| {
|
|
||||||
self.changed_cols[i] = false;
|
|
||||||
self.value_lens[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inicializa buffer para una fila inyectada (Ctrl+N entre líneas)
|
|
||||||
/// insertion_idx es el índice visual donde aparece la fila nueva
|
|
||||||
pub fn startInjectedEdit(self: *RowEditBuffer, insertion_idx: usize) void {
|
|
||||||
self.row_id = NEW_ROW_ID;
|
|
||||||
self.row_index = insertion_idx;
|
|
||||||
self.is_new_row = true;
|
|
||||||
self.has_changes = false;
|
|
||||||
self.is_injected = true;
|
|
||||||
self.injection_index = insertion_idx;
|
|
||||||
self.change_count = 0;
|
self.change_count = 0;
|
||||||
for (0..MAX_PENDING_COLUMNS) |i| {
|
for (0..MAX_PENDING_COLUMNS) |i| {
|
||||||
self.changed_cols[i] = false;
|
self.changed_cols[i] = false;
|
||||||
|
|
@ -1389,8 +1369,6 @@ pub const RowEditBuffer = struct {
|
||||||
self.row_index = 0;
|
self.row_index = 0;
|
||||||
self.is_new_row = false;
|
self.is_new_row = false;
|
||||||
self.has_changes = false;
|
self.has_changes = false;
|
||||||
self.is_injected = false;
|
|
||||||
self.injection_index = null;
|
|
||||||
self.change_count = 0;
|
self.change_count = 0;
|
||||||
for (0..MAX_PENDING_COLUMNS) |i| {
|
for (0..MAX_PENDING_COLUMNS) |i| {
|
||||||
self.changed_cols[i] = false;
|
self.changed_cols[i] = false;
|
||||||
|
|
@ -1413,12 +1391,6 @@ pub const RowCommitInfo = struct {
|
||||||
|
|
||||||
/// Número de cambios
|
/// Número de cambios
|
||||||
change_count: usize,
|
change_count: usize,
|
||||||
|
|
||||||
/// True si era una fila inyectada (Ctrl+N entre líneas)
|
|
||||||
is_injected: bool = false,
|
|
||||||
|
|
||||||
/// Índice visual donde fue inyectada (válido si is_injected = true)
|
|
||||||
injection_index: ?usize = null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Construye la info de commit desde un RowEditBuffer
|
/// Construye la info de commit desde un RowEditBuffer
|
||||||
|
|
@ -1445,8 +1417,6 @@ pub fn buildCommitInfo(
|
||||||
.is_insert = buffer.is_new_row,
|
.is_insert = buffer.is_new_row,
|
||||||
.changes = changes_out[0..count],
|
.changes = changes_out[0..count],
|
||||||
.change_count = count,
|
.change_count = count,
|
||||||
.is_injected = buffer.is_injected,
|
|
||||||
.injection_index = buffer.injection_index,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,51 +51,16 @@ pub const PagedDataSource = struct {
|
||||||
// Implementación de TableDataSource
|
// Implementación de TableDataSource
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
/// Retorna el número total de filas (filtered count + inyección)
|
/// Retorna el número total de filas (filtered count + inyección visual)
|
||||||
|
/// Retorna el número de filas disponibles
|
||||||
pub fn getRowCount(self: *Self) usize {
|
pub fn getRowCount(self: *Self) usize {
|
||||||
// Usar conteo filtrado si está disponible
|
|
||||||
const count_info = self.state.getDisplayCount();
|
const count_info = self.state.getDisplayCount();
|
||||||
var count = count_info.value;
|
return count_info.value;
|
||||||
|
|
||||||
// Si hay una fila inyectada, sumar 1 al conteo visual
|
|
||||||
if (self.state.injected_row_idx != null) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Escribe el valor de una celda en el buffer proporcionado.
|
/// Escribe el valor de una celda en el buffer proporcionado.
|
||||||
/// El row es índice global, se convierte a índice de ventana.
|
|
||||||
/// Maneja filas inyectadas (Ctrl+N entre líneas).
|
|
||||||
/// Retorna slice del buffer con el contenido.
|
|
||||||
pub fn getCellValueInto(self: *Self, row: usize, col: usize, buf: []u8) []const u8 {
|
pub fn getCellValueInto(self: *Self, row: usize, col: usize, buf: []u8) []const u8 {
|
||||||
// Validar columna
|
|
||||||
if (col >= self.columns.len) return "";
|
if (col >= self.columns.len) return "";
|
||||||
|
|
||||||
// =====================================================================
|
|
||||||
// Manejo de fila inyectada
|
|
||||||
// =====================================================================
|
|
||||||
if (self.state.injected_row_idx) |inj_idx| {
|
|
||||||
if (row == inj_idx) {
|
|
||||||
// Esta es la fila inyectada - leer del edit buffer
|
|
||||||
if (self.state.row_edit_buffer.getPendingValue(col)) |pending| {
|
|
||||||
std.debug.print("[PDS-DEBUG] injected row={} col={} pending=\"{s}\"\n", .{ row, col, pending });
|
|
||||||
const copy_len = @min(pending.len, buf.len);
|
|
||||||
@memcpy(buf[0..copy_len], pending[0..copy_len]);
|
|
||||||
return buf[0..copy_len];
|
|
||||||
}
|
|
||||||
// Sin valor pendiente - retornar vacío (celda nueva)
|
|
||||||
std.debug.print("[PDS-DEBUG] injected row={} col={} NO pending\n", .{ row, col });
|
|
||||||
return "";
|
|
||||||
} else if (row > inj_idx) {
|
|
||||||
// Fila después de la inyección - ajustar índice (-1)
|
|
||||||
return self.getCellValueFromProvider(row - 1, col, buf);
|
|
||||||
}
|
|
||||||
// row < inj_idx: continuar normal
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flujo normal (sin inyección o row < inj_idx)
|
|
||||||
return self.getCellValueFromProvider(row, col, buf);
|
return self.getCellValueFromProvider(row, col, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,21 +87,7 @@ pub const PagedDataSource = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retorna el ID único de una fila.
|
/// Retorna el ID único de una fila.
|
||||||
/// Si está en ventana, usa window data. Si no, consulta al provider.
|
|
||||||
/// Maneja filas inyectadas (Ctrl+N entre líneas).
|
|
||||||
pub fn getRowId(self: *Self, row: usize) i64 {
|
pub fn getRowId(self: *Self, row: usize) i64 {
|
||||||
// Manejo de fila inyectada
|
|
||||||
if (self.state.injected_row_idx) |inj_idx| {
|
|
||||||
if (row == inj_idx) {
|
|
||||||
// Esta es la fila inyectada
|
|
||||||
return self.state.injected_row_id;
|
|
||||||
} else if (row > inj_idx) {
|
|
||||||
// Fila después de la inyección - ajustar índice
|
|
||||||
return self.getRowIdFromProvider(row - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flujo normal
|
|
||||||
return self.getRowIdFromProvider(row);
|
return self.getRowIdFromProvider(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,17 +164,15 @@ pub const VirtualAdvancedTableState = struct {
|
||||||
row_edit_buffer: table_core.RowEditBuffer = .{},
|
row_edit_buffer: table_core.RowEditBuffer = .{},
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Estado de inyección local (Ctrl+N entre líneas)
|
// Modo Inserción Cronológico (reemplaza inyección local)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
/// Índice visual donde está la fila inyectada (null = sin inyección)
|
/// True si estamos en modo inserción (Ctrl+N activo)
|
||||||
injected_row_idx: ?usize = null,
|
is_insertion_mode: bool = false,
|
||||||
|
|
||||||
/// ID de la fila inyectada tras commit (NEW_ROW_ID si aún no guardada)
|
/// IDs de filas insertadas en esta sesión (para ORDER BY cronológico)
|
||||||
injected_row_id: i64 = table_core.NEW_ROW_ID,
|
/// El Panel gestiona esta lista via el DataProvider
|
||||||
|
insertion_session_active: bool = false,
|
||||||
/// True si la fila inyectada ya fue guardada en BD (tiene ID real)
|
|
||||||
injected_committed: bool = false,
|
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
|
@ -730,43 +728,24 @@ pub const VirtualAdvancedTableState = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Métodos de inyección local (Ctrl+N entre líneas)
|
// Métodos de Modo Inserción Cronológico
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
/// Verifica si hay una fila inyectada activa
|
/// Entra en modo inserción
|
||||||
pub fn hasInjection(self: *const Self) bool {
|
pub fn enterInsertionMode(self: *Self) void {
|
||||||
return self.injected_row_idx != null;
|
self.is_insertion_mode = true;
|
||||||
|
self.insertion_session_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inicia una inyección en el índice especificado
|
/// Sale del modo inserción
|
||||||
pub fn startInjection(self: *Self, visual_idx: usize) void {
|
pub fn exitInsertionMode(self: *Self) void {
|
||||||
self.injected_row_idx = visual_idx;
|
self.is_insertion_mode = false;
|
||||||
self.injected_row_id = table_core.NEW_ROW_ID;
|
self.insertion_session_active = false;
|
||||||
self.injected_committed = false;
|
|
||||||
self.row_edit_buffer.startInjectedEdit(visual_idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marca la fila inyectada como guardada en BD
|
/// Verifica si estamos en modo inserción
|
||||||
pub fn markInjectionCommitted(self: *Self, real_id: i64) void {
|
pub fn isInInsertionMode(self: *const Self) bool {
|
||||||
self.injected_row_id = real_id;
|
return self.is_insertion_mode;
|
||||||
self.injected_committed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Limpia el estado de inyección (después de reload)
|
|
||||||
pub fn clearInjection(self: *Self) void {
|
|
||||||
self.injected_row_idx = null;
|
|
||||||
self.injected_row_id = table_core.NEW_ROW_ID;
|
|
||||||
self.injected_committed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verifica si la fila inyectada está visible en la ventana actual
|
|
||||||
pub fn isInjectionVisible(self: *const Self, visible_rows: usize) bool {
|
|
||||||
if (self.injected_row_idx) |idx| {
|
|
||||||
const scroll_start = self.nav.scroll_row;
|
|
||||||
const scroll_end = scroll_start + visible_rows;
|
|
||||||
return idx >= scroll_start and idx < scroll_end;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,19 +130,6 @@ pub const VirtualAdvancedTableResult = struct {
|
||||||
/// Shift estaba presionado con Tab (para tab_out inverso)
|
/// Shift estaba presionado con Tab (para tab_out inverso)
|
||||||
tab_shift: bool = false,
|
tab_shift: bool = false,
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
// Inyección local (Ctrl+N entre líneas)
|
|
||||||
// =========================================================================
|
|
||||||
|
|
||||||
/// Una fila inyectada fue guardada en BD (el panel debe hacer INSERT)
|
|
||||||
injection_committed: bool = false,
|
|
||||||
|
|
||||||
/// Índice visual donde se inyectó la fila
|
|
||||||
injection_row_idx: ?usize = null,
|
|
||||||
|
|
||||||
/// La tabla necesita recargarse desde BD (fila inyectada salió del viewport)
|
|
||||||
needs_reload: bool = false,
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Compatibilidad (DEPRECADO - usar row_committed)
|
// Compatibilidad (DEPRECADO - usar row_committed)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
@ -197,11 +184,6 @@ pub fn virtualAdvancedTableRect(
|
||||||
) VirtualAdvancedTableResult {
|
) VirtualAdvancedTableResult {
|
||||||
var result = VirtualAdvancedTableResult{};
|
var result = VirtualAdvancedTableResult{};
|
||||||
|
|
||||||
// Debug: verificar si hay inyección al inicio del frame
|
|
||||||
if (list_state.injected_row_idx != null) {
|
|
||||||
std.debug.print("[VT-FRAME] Frame con inyección activa: idx={}\n", .{list_state.injected_row_idx.?});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bounds.isEmpty() or config.columns.len == 0) return result;
|
if (bounds.isEmpty() or config.columns.len == 0) return result;
|
||||||
|
|
||||||
// Reset frame flags
|
// Reset frame flags
|
||||||
|
|
@ -348,12 +330,11 @@ pub fn virtualAdvancedTableRect(
|
||||||
const edited_cell = list_state.getEditingCell().?;
|
const edited_cell = list_state.getEditingCell().?;
|
||||||
const new_value = list_state.getEditText();
|
const new_value = list_state.getEditText();
|
||||||
|
|
||||||
std.debug.print("[VT-DEBUG] editor committed: cell=({},{}) value=\"{s}\" hasChanged={} is_injected={}\n", .{
|
std.debug.print("[VT-DEBUG] editor committed: cell=({},{}) value=\"{s}\" hasChanged={}\n", .{
|
||||||
edited_cell.row,
|
edited_cell.row,
|
||||||
edited_cell.col,
|
edited_cell.col,
|
||||||
new_value,
|
new_value,
|
||||||
list_state.hasValueChanged(),
|
list_state.hasValueChanged(),
|
||||||
list_state.row_edit_buffer.is_injected,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Añadir cambio al buffer de fila (NO commit inmediato)
|
// Añadir cambio al buffer de fila (NO commit inmediato)
|
||||||
|
|
@ -449,53 +430,28 @@ pub fn virtualAdvancedTableRect(
|
||||||
const is_tab = result.navigate_direction == .next_cell or result.navigate_direction == .prev_cell;
|
const is_tab = result.navigate_direction == .next_cell or result.navigate_direction == .prev_cell;
|
||||||
if (is_tab) {
|
if (is_tab) {
|
||||||
// Wrapper para DataProvider que implementa getRowId(usize) -> i64
|
// Wrapper para DataProvider que implementa getRowId(usize) -> i64
|
||||||
// Tiene en cuenta filas inyectadas (Ctrl+N) y ghost row
|
|
||||||
const RowIdGetter = struct {
|
const RowIdGetter = struct {
|
||||||
prov: DataProvider,
|
prov: DataProvider,
|
||||||
total: usize,
|
total: usize,
|
||||||
injected_idx: ?usize,
|
|
||||||
|
|
||||||
pub fn getRowId(self: @This(), row: usize) i64 {
|
pub fn getRowId(self: @This(), row: usize) i64 {
|
||||||
// Fila inyectada siempre retorna NEW_ROW_ID
|
|
||||||
if (self.injected_idx) |inj_idx| {
|
|
||||||
if (row == inj_idx) {
|
|
||||||
std.debug.print("[ROW-ID-GETTER] row={} == inj_idx={} -> NEW_ROW_ID\n", .{ row, inj_idx });
|
|
||||||
return table_core.NEW_ROW_ID;
|
|
||||||
}
|
|
||||||
// Filas después de inyección: ajustar índice hacia provider
|
|
||||||
if (row > inj_idx) {
|
|
||||||
const adjusted_row = row - 1;
|
|
||||||
if (adjusted_row >= self.total) return table_core.NEW_ROW_ID;
|
|
||||||
const id = self.prov.getRowId(adjusted_row) orelse table_core.NEW_ROW_ID;
|
|
||||||
std.debug.print("[ROW-ID-GETTER] row={} > inj_idx={}, adjusted={} -> id={}\n", .{ row, inj_idx, adjusted_row, id });
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Ghost row está al final
|
// Ghost row está al final
|
||||||
if (row >= self.total) {
|
if (row >= self.total) {
|
||||||
std.debug.print("[ROW-ID-GETTER] row={} >= total={} -> NEW_ROW_ID (ghost)\n", .{ row, self.total });
|
|
||||||
return table_core.NEW_ROW_ID;
|
return table_core.NEW_ROW_ID;
|
||||||
}
|
}
|
||||||
const id = self.prov.getRowId(row) orelse table_core.NEW_ROW_ID;
|
return self.prov.getRowId(row) orelse table_core.NEW_ROW_ID;
|
||||||
std.debug.print("[ROW-ID-GETTER] row={} normal -> id={}\n", .{ row, id });
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getter = RowIdGetter{
|
const getter = RowIdGetter{
|
||||||
.prov = provider,
|
.prov = provider,
|
||||||
.total = total_rows,
|
.total = total_rows,
|
||||||
.injected_idx = list_state.injected_row_idx,
|
|
||||||
};
|
};
|
||||||
const current_row = list_state.getSelectedRow() orelse 0;
|
const current_row = list_state.getSelectedRow() orelse 0;
|
||||||
const forward = result.navigate_direction == .next_cell;
|
const forward = result.navigate_direction == .next_cell;
|
||||||
const num_cols = config.columns.len;
|
const num_cols = config.columns.len;
|
||||||
// VirtualAdvancedTable siempre tiene ghost row disponible
|
// +1 para ghost row
|
||||||
// Si hay inyección, sumar 1 extra al conteo visual
|
const num_rows = total_rows + 1;
|
||||||
var num_rows = total_rows + 1; // +1 para ghost row
|
|
||||||
if (list_state.injected_row_idx != null) {
|
|
||||||
num_rows += 1; // +1 para fila inyectada
|
|
||||||
}
|
|
||||||
|
|
||||||
const plan = table_core.planTabNavigation(
|
const plan = table_core.planTabNavigation(
|
||||||
&list_state.row_edit_buffer,
|
&list_state.row_edit_buffer,
|
||||||
|
|
@ -539,12 +495,6 @@ pub fn virtualAdvancedTableRect(
|
||||||
result.row_commit_is_insert = info.is_insert;
|
result.row_commit_is_insert = info.is_insert;
|
||||||
result.row_changes_count = info.change_count;
|
result.row_changes_count = info.change_count;
|
||||||
result.row_changed = true;
|
result.row_changed = true;
|
||||||
|
|
||||||
// Propagar info de inyección si aplica
|
|
||||||
if (info.is_injected) {
|
|
||||||
result.injection_committed = true;
|
|
||||||
result.injection_row_idx = info.injection_index;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (plan.action == .move_with_commit and plan.new_row == current_row) {
|
} else if (plan.action == .move_with_commit and plan.new_row == current_row) {
|
||||||
std.debug.print("[VT-TAB] Commit SUPRIMIDO: misma fila {}, manteniendo buffer\n", .{current_row});
|
std.debug.print("[VT-TAB] Commit SUPRIMIDO: misma fila {}, manteniendo buffer\n", .{current_row});
|
||||||
|
|
@ -568,12 +518,6 @@ pub fn virtualAdvancedTableRect(
|
||||||
result.row_commit_is_insert = info.is_insert;
|
result.row_commit_is_insert = info.is_insert;
|
||||||
result.row_changes_count = info.change_count;
|
result.row_changes_count = info.change_count;
|
||||||
result.row_changed = true;
|
result.row_changed = true;
|
||||||
|
|
||||||
// Propagar info de inyección si aplica
|
|
||||||
if (info.is_injected) {
|
|
||||||
result.injection_committed = true;
|
|
||||||
result.injection_row_idx = info.injection_index;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -593,10 +537,6 @@ pub fn virtualAdvancedTableRect(
|
||||||
const new_row_idx = list_state.getSelectedRow() orelse 0;
|
const new_row_idx = list_state.getSelectedRow() orelse 0;
|
||||||
const is_ghost = table_core.isGhostRow(new_row_id);
|
const is_ghost = table_core.isGhostRow(new_row_id);
|
||||||
|
|
||||||
// Detectar si estamos abandonando una fila inyectada
|
|
||||||
const was_injected = list_state.row_edit_buffer.is_injected;
|
|
||||||
const injection_idx = list_state.row_edit_buffer.injection_index;
|
|
||||||
|
|
||||||
// checkRowChangeAndCommit compara row_ids y hace commit si son diferentes
|
// checkRowChangeAndCommit compara row_ids y hace commit si son diferentes
|
||||||
if (table_core.checkRowChangeAndCommit(
|
if (table_core.checkRowChangeAndCommit(
|
||||||
&list_state.row_edit_buffer,
|
&list_state.row_edit_buffer,
|
||||||
|
|
@ -609,32 +549,10 @@ pub fn virtualAdvancedTableRect(
|
||||||
result.row_commit_id = commit_info.row_id;
|
result.row_commit_id = commit_info.row_id;
|
||||||
result.row_commit_is_insert = commit_info.is_insert;
|
result.row_commit_is_insert = commit_info.is_insert;
|
||||||
result.row_changes_count = commit_info.change_count;
|
result.row_changes_count = commit_info.change_count;
|
||||||
|
|
||||||
// Si era una fila inyectada, señalar para que el panel haga INSERT
|
|
||||||
if (was_injected) {
|
|
||||||
result.injection_committed = true;
|
|
||||||
result.injection_row_idx = injection_idx;
|
|
||||||
// Mantener injected_row_idx en state para renderizado
|
|
||||||
// (se limpiará cuando el scroll la saque del viewport)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compatibilidad
|
|
||||||
result.row_changed = true;
|
result.row_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
// Detectar si la fila inyectada salió del viewport (requiere reload)
|
|
||||||
// =========================================================================
|
|
||||||
if (list_state.hasInjection()) {
|
|
||||||
// Solo hacer reload si la fila ya fue guardada (injected_committed)
|
|
||||||
// y ya no es visible en el viewport actual
|
|
||||||
if (list_state.injected_committed and !list_state.isInjectionVisible(visible_rows)) {
|
|
||||||
result.needs_reload = true;
|
|
||||||
list_state.clearInjection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Tips Proactivos (FASE I): Rotar tips cada ~10 segundos
|
// Tips Proactivos (FASE I): Rotar tips cada ~10 segundos
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
@ -1018,18 +936,14 @@ fn drawRows(
|
||||||
const table_ds = pds_ptr.toDataSource();
|
const table_ds = pds_ptr.toDataSource();
|
||||||
|
|
||||||
// Convertir selected_id a selected_row (índice global)
|
// Convertir selected_id a selected_row (índice global)
|
||||||
// Si hay una fila inyectada activa, esa es la seleccionada
|
const selected_row: i32 = if (list_state.findSelectedInWindow()) |window_idx|
|
||||||
const selected_row: i32 = if (list_state.injected_row_idx) |inj_idx|
|
|
||||||
@intCast(inj_idx)
|
|
||||||
else if (list_state.findSelectedInWindow()) |window_idx|
|
|
||||||
@intCast(list_state.windowToGlobalIndex(window_idx))
|
@intCast(list_state.windowToGlobalIndex(window_idx))
|
||||||
else
|
else
|
||||||
-1;
|
-1;
|
||||||
|
|
||||||
// Calcular rango de filas a dibujar
|
// Calcular rango de filas a dibujar
|
||||||
const first_row = list_state.nav.scroll_row;
|
const first_row = list_state.nav.scroll_row;
|
||||||
// Si hay inyección, hay una fila más en la ventana visual
|
const window_rows = list_state.current_window.len;
|
||||||
const window_rows = list_state.current_window.len + @as(usize, if (list_state.hasInjection()) 1 else 0);
|
|
||||||
const last_row = @min(
|
const last_row = @min(
|
||||||
list_state.nav.scroll_row + visible_rows,
|
list_state.nav.scroll_row + visible_rows,
|
||||||
list_state.window_start + window_rows,
|
list_state.window_start + window_rows,
|
||||||
|
|
@ -1302,40 +1216,14 @@ fn handleKeyboard(
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Ctrl+N: Inyección local (insertar fila debajo de la actual)
|
// Ctrl+N: Modo Inserción Cronológico (INSERT real en BD)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
if (events.insert_row) {
|
if (events.insert_row) {
|
||||||
std.debug.print("[VT-CTRL-N] insert_row event, hasInjection={}\n", .{list_state.hasInjection()});
|
std.debug.print("[VT-CTRL-N] insert_row event -> emitiendo insert_row_requested\n", .{});
|
||||||
// Solo permitir si no hay ya una inyección activa
|
// Emitir evento para que el Panel haga INSERT real en BD
|
||||||
if (!list_state.hasInjection()) {
|
result.insert_row_requested = true;
|
||||||
// Calcular índice de inyección (debajo de la fila actual)
|
// Entrar en modo inserción
|
||||||
const current_row: usize = if (list_state.findSelectedInWindow()) |window_idx|
|
list_state.enterInsertionMode();
|
||||||
list_state.windowToGlobalIndex(window_idx)
|
|
||||||
else
|
|
||||||
0;
|
|
||||||
|
|
||||||
const injection_idx = current_row + 1;
|
|
||||||
std.debug.print("[VT-CTRL-N] current_row={} injection_idx={}\n", .{ current_row, injection_idx });
|
|
||||||
|
|
||||||
// Iniciar inyección
|
|
||||||
list_state.startInjection(injection_idx);
|
|
||||||
std.debug.print("[VT-CTRL-N] startInjection OK\n", .{});
|
|
||||||
|
|
||||||
// Mover selección a la fila inyectada
|
|
||||||
list_state.selected_id = null; // La fila inyectada no tiene ID aún
|
|
||||||
// La selección visual se maneja por injected_row_idx
|
|
||||||
|
|
||||||
// Señalar que hay una nueva inyección
|
|
||||||
result.injection_row_idx = injection_idx;
|
|
||||||
result.selection_changed = true;
|
|
||||||
|
|
||||||
// Iniciar edición automática en primera columna
|
|
||||||
std.debug.print("[VT-CTRL-N] about to startEditing\n", .{});
|
|
||||||
list_state.cell_edit.startEditing(injection_idx, 0, "", null);
|
|
||||||
list_state.nav.active_col = 0;
|
|
||||||
std.debug.print("[VT-CTRL-N] DONE\n", .{});
|
|
||||||
}
|
|
||||||
// Nota: insert_row_requested ya NO se emite - la inyección es interna
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue