zcatgui/docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md
reugenio bd95013ffc fix(advanced_table): Teclado funciona - result.selected_row/col
Bug: Las flechas no movían la selección en AdvancedTable.

Causa raíz:
- handleKeyboard seteaba result.selection_changed = true
- PERO NO seteaba result.selected_row / result.selected_col
- zsimifactu sincroniza selección desde DataManager cada frame
- Sin esos valores, DataManager no se actualizaba
- Siguiente frame: selección se reseteaba al valor anterior

Solución:
- Añadir result.selected_row y result.selected_col a todas
  las teclas de navegación (up, down, left, right, page_up,
  page_down, home, end)

Cambios visuales:
- Celda seleccionada: borde + tinte sutil (15%) en lugar
  de fondo sólido azul

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 20:06:17 +01:00

116 lines
3.3 KiB
Markdown

# Bug: AdvancedTable Keyboard Navigation No Funciona
> **Fecha:** 2025-12-17
> **Estado:** ✅ RESUELTO
> **Severidad:** ALTA
---
## Síntoma
Las flechas de teclado no mueven la selección en AdvancedTable cuando se usa en zsimifactu.
---
## Causa Raíz (ENCONTRADA)
El problema era una combinación de dos factores:
### 1. `handleKeyboard` no seteaba `result.selected_row` / `result.selected_col`
En el código original:
```zig
.down => {
if (table_state.selected_row < row_count - 1) {
table_state.selectCell(...);
result.selection_changed = true;
// FALTABA: result.selected_row = new_row;
// FALTABA: result.selected_col = new_col;
}
},
```
### 2. zsimifactu sincroniza la selección desde DataManager cada frame
En `who_list_advanced.zig` líneas 199-205:
```zig
// Sincronizar selección con DataManager
if (dm.getSelectedWhoIndex()) |idx| {
const idx_i32: i32 = @intCast(idx);
if (self.table_state.selected_row != idx_i32) {
self.table_state.selected_row = idx_i32; // ← RESETEA cada frame
}
}
```
### Flujo del bug:
1. Usuario presiona flecha abajo
2. `handleKeyboard` detecta la tecla y ejecuta `selectCell(new_row, new_col)`
3. `selected_row` cambia de 1 a 2 ✓
4. `result.selection_changed = true`
5. **PERO** `result.selected_row` es `null`
6. zsimifactu verifica `if (result.selected_row) |row_idx|` → es null → no actualiza DataManager
7. Siguiente frame: zsimifactu sincroniza desde DataManager → `selected_row` vuelve a 1
---
## Solución
Añadir `result.selected_row` y `result.selected_col` a todas las teclas de navegación en `handleKeyboard`:
```zig
.down => {
if (table_state.selected_row < @as(i32, @intCast(row_count)) - 1) {
const new_row: usize = @intCast(table_state.selected_row + 1);
const new_col: usize = @intCast(@max(0, table_state.selected_col));
table_state.selectCell(new_row, new_col);
result.selection_changed = true;
result.selected_row = new_row; // ← AÑADIDO
result.selected_col = new_col; // ← AÑADIDO
}
},
```
Teclas corregidas:
- `.up`
- `.down`
- `.left`
- `.right`
- `.page_up`
- `.page_down`
- `.home` (y Ctrl+Home)
- `.end` (y Ctrl+End)
---
## Verificación
Debug añadido temporalmente mostró:
```
[ADV-TABLE] DOWN: after selectCell, selected_row=2 ← SÍ cambia
[ADV-TABLE] navKey detected: down, selected_row=1 ← Pero vuelve a 1 en siguiente frame
```
Después del fix, las flechas funcionan correctamente.
---
## Archivos modificados
- `src/widgets/advanced_table/advanced_table.zig` - handleKeyboard corregido
---
## Lecciones aprendidas
1. **El resultado de un widget debe ser completo** - Si `selection_changed = true`, también debe informar QUÉ cambió (`selected_row`, `selected_col`).
2. **Cuidado con la sincronización bidireccional** - Cuando un widget y un data manager ambos pueden modificar el mismo estado, hay que asegurar que los cambios del widget se propaguen al data manager antes de que éste resetee el estado.
3. **Debug incremental** - Añadir debug DENTRO de la función problemática (no antes) para ver el flujo real.
---
*Documentado por: Claude Code (Opus 4.5)*
*Fecha resolución: 2025-12-17 ~19:30*