fix(virtual_table): PagedDataSource en frameAllocator
- PagedDataSource ahora se crea en ctx.frameAllocator() - Memoria estable durante todo el frame de rendering - Eliminado cached_paged_datasource del state (punteros auto-ref peligrosos) - Fix secundario para estabilidad (no era causa del crash Ctrl+N)
This commit is contained in:
parent
b3a33ec4f3
commit
3a6398e90d
2 changed files with 48 additions and 8 deletions
|
|
@ -1703,6 +1703,13 @@ pub fn planTabNavigation(
|
|||
const current_row_id = buffer.row_id;
|
||||
const new_row_id = row_id_getter.getRowId(pos.row);
|
||||
|
||||
std.debug.print("[PLAN-TAB] current_row={} current_col={} -> new_row={} new_col={}\n", .{
|
||||
current_row, current_col, pos.row, pos.col,
|
||||
});
|
||||
std.debug.print("[PLAN-TAB] buffer.row_id={} getter.getRowId({})={} has_changes={}\n", .{
|
||||
current_row_id, pos.row, new_row_id, buffer.has_changes,
|
||||
});
|
||||
|
||||
if (current_row_id != new_row_id and buffer.has_changes) {
|
||||
// Cambió de fila con cambios pendientes → commit
|
||||
const info = buildCommitInfo(buffer, changes_out);
|
||||
|
|
|
|||
|
|
@ -197,6 +197,11 @@ pub fn virtualAdvancedTableRect(
|
|||
) 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;
|
||||
|
||||
// Reset frame flags
|
||||
|
|
@ -453,17 +458,27 @@ pub fn virtualAdvancedTableRect(
|
|||
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) return table_core.NEW_ROW_ID;
|
||||
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;
|
||||
return self.prov.getRowId(adjusted_row) orelse 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
|
||||
if (row >= self.total) return table_core.NEW_ROW_ID;
|
||||
return self.prov.getRowId(row) orelse table_core.NEW_ROW_ID;
|
||||
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;
|
||||
}
|
||||
const id = self.prov.getRowId(row) orelse table_core.NEW_ROW_ID;
|
||||
std.debug.print("[ROW-ID-GETTER] row={} normal -> id={}\n", .{ row, id });
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -512,8 +527,13 @@ pub fn virtualAdvancedTableRect(
|
|||
}
|
||||
|
||||
// Si hay commit, establecer flags
|
||||
if (plan.action == .move_with_commit) {
|
||||
// IMPORTANTE: Solo hacer commit si REALMENTE cambió de fila
|
||||
// Tab dentro de la misma fila NO debe triggerar commit (Excel-style)
|
||||
if (plan.action == .move_with_commit and plan.new_row != current_row) {
|
||||
if (plan.commit_info) |info| {
|
||||
std.debug.print("[VT-TAB] Commit real: row {} -> {}, is_insert={}\n", .{
|
||||
current_row, plan.new_row, info.is_insert,
|
||||
});
|
||||
result.row_committed = true;
|
||||
result.row_commit_id = info.row_id;
|
||||
result.row_commit_is_insert = info.is_insert;
|
||||
|
|
@ -526,6 +546,9 @@ pub fn virtualAdvancedTableRect(
|
|||
result.injection_row_idx = info.injection_index;
|
||||
}
|
||||
}
|
||||
} 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});
|
||||
// NO limpiar el buffer - mantener cambios pendientes
|
||||
}
|
||||
|
||||
// Indicar al panel que debe auto-editar la nueva celda
|
||||
|
|
@ -985,9 +1008,14 @@ fn drawRows(
|
|||
) void {
|
||||
_ = result;
|
||||
|
||||
// Crear PagedDataSource para acceso unificado a datos
|
||||
var datasource = paged_datasource.PagedDataSource.init(list_state, config.columns, null);
|
||||
const table_ds = datasource.toDataSource();
|
||||
// Crear PagedDataSource en memoria estable del frame (frame arena)
|
||||
// Esto evita punteros inválidos cuando el stack se destruye
|
||||
const pds_ptr = ctx.frameAllocator().create(paged_datasource.PagedDataSource) catch {
|
||||
std.debug.print("[VT-ERROR] No se pudo crear PagedDataSource en frame arena\n", .{});
|
||||
return;
|
||||
};
|
||||
pds_ptr.* = paged_datasource.PagedDataSource.init(list_state, config.columns, null);
|
||||
const table_ds = pds_ptr.toDataSource();
|
||||
|
||||
// Convertir selected_id a selected_row (índice global)
|
||||
// Si hay una fila inyectada activa, esa es la seleccionada
|
||||
|
|
@ -1277,6 +1305,7 @@ fn handleKeyboard(
|
|||
// Ctrl+N: Inyección local (insertar fila debajo de la actual)
|
||||
// =========================================================================
|
||||
if (events.insert_row) {
|
||||
std.debug.print("[VT-CTRL-N] insert_row event, hasInjection={}\n", .{list_state.hasInjection()});
|
||||
// Solo permitir si no hay ya una inyección activa
|
||||
if (!list_state.hasInjection()) {
|
||||
// Calcular índice de inyección (debajo de la fila actual)
|
||||
|
|
@ -1286,9 +1315,11 @@ fn handleKeyboard(
|
|||
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
|
||||
|
|
@ -1299,8 +1330,10 @@ fn handleKeyboard(
|
|||
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