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>
201 lines
6.9 KiB
Markdown
201 lines
6.9 KiB
Markdown
# Propuesta: Widgets Browser Especializados
|
|
|
|
**Fecha:** 2025-12-17
|
|
**Origen:** Conversación zsimifactu sobre extracción de patrones reutilizables
|
|
**Estado:** PROPUESTA - Pendiente de implementación
|
|
|
|
---
|
|
|
|
## Resumen Ejecutivo
|
|
|
|
Se propone crear widgets especializados para navegación de datos tabulares que encapsulen patrones comunes identificados en zsimifactu. Estos widgets combinarían tabla + controles de navegación + filtros en componentes cohesivos.
|
|
|
|
---
|
|
|
|
## Widgets Propuestos
|
|
|
|
### 1. TableBrowser
|
|
|
|
Widget compuesto que integra:
|
|
- Tabla con scroll y selección
|
|
- Barra de estado con posición (ej: "15/520")
|
|
- Botones de navegación (|< < > >|)
|
|
- Soporte para filtros (opcional)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────┐
|
|
│ [Filtro: ___________] [Tipo: v] │ ← Zona filtros (opcional)
|
|
├─────────────────────────────────────────────┤
|
|
│ Codigo │ Nombre │ Ciudad │ ← Header tabla
|
|
├────────┼─────────────────┼─────────────────┤
|
|
│ C0001 │ Empresa ABC │ Valencia │
|
|
│ C0002 │ Empresa XYZ │ Madrid │
|
|
│ ... │ ... │ ... │
|
|
├─────────────────────────────────────────────┤
|
|
│ [|<] [<] 15/520 [>] [>|] │ ← Navegación integrada
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Caso de uso:** Panel de lista en aplicaciones CRUD (WhoListPanel, DocListPanel, etc.)
|
|
|
|
### 2. ConfigBrowser
|
|
|
|
Widget especializado para visualizar/editar configuración:
|
|
- Lista de variables agrupadas por categoría
|
|
- Editor inline según tipo (checkbox, input, color picker)
|
|
- Búsqueda/filtro de variables
|
|
- Indicador de cambios pendientes
|
|
|
|
```
|
|
┌─────────────────────────────────────────────┐
|
|
│ [Buscar: ___________] │
|
|
├─────────────────────────────────────────────┤
|
|
│ ▼ General │
|
|
│ auto_guardar_cada [15 ] minutos │
|
|
│ backup_automatico [✓] │
|
|
├─────────────────────────────────────────────┤
|
|
│ ▼ Apariencia │
|
|
│ color_azul_empresa [■] RGB(40,80,120) │
|
|
│ font_size [14 ] │
|
|
├─────────────────────────────────────────────┤
|
|
│ ▶ Comportamiento (click para expandir) │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Caso de uso:** Panel de configuración de aplicación
|
|
|
|
---
|
|
|
|
## Justificación Técnica
|
|
|
|
### Patrón Repetido en zsimifactu
|
|
|
|
En `WhoListPanel` y futuros paneles de lista se repite:
|
|
1. Tabla con datos
|
|
2. Callback para obtener celdas
|
|
3. Botones navegación (First/Prev/Next/Last)
|
|
4. Indicador posición
|
|
5. Manejo de selección → DataManager
|
|
|
|
Este código se duplicaría en cada panel de lista (DocListPanel, ProdListPanel, etc.).
|
|
|
|
### Beneficios de Encapsular
|
|
|
|
| Aspecto | Sin widget | Con TableBrowser |
|
|
|---------|------------|------------------|
|
|
| Líneas por panel | ~200 | ~50 |
|
|
| Bugs de navegación | Duplicados | Corregidos una vez |
|
|
| Consistencia UX | Manual | Automática |
|
|
| Nuevos paneles | Copy-paste | Instanciar widget |
|
|
|
|
---
|
|
|
|
## API Propuesta
|
|
|
|
### TableBrowser
|
|
|
|
```zig
|
|
const TableBrowser = struct {
|
|
table_state: widgets.table.TableState,
|
|
nav_state: NavState,
|
|
filter_state: ?FilterState,
|
|
|
|
pub const Config = struct {
|
|
columns: []const Column,
|
|
show_navigation: bool = true,
|
|
show_filters: bool = false,
|
|
row_height: u16 = 18,
|
|
};
|
|
|
|
pub const Callbacks = struct {
|
|
getCellData: *const fn (row: usize, col: usize) []const u8,
|
|
getRowCount: *const fn () usize,
|
|
onSelectionChanged: ?*const fn (row: usize) void = null,
|
|
};
|
|
|
|
pub fn init(config: Config) TableBrowser;
|
|
pub fn draw(self: *Self, ctx: *Context, rect: Rect, callbacks: Callbacks) DrawResult;
|
|
pub fn handleEvent(self: *Self, event: Event) bool;
|
|
|
|
// Navegación programática
|
|
pub fn goFirst(self: *Self) void;
|
|
pub fn goPrev(self: *Self) void;
|
|
pub fn goNext(self: *Self) void;
|
|
pub fn goLast(self: *Self) void;
|
|
pub fn getPosition(self: *Self) struct { current: usize, total: usize };
|
|
};
|
|
```
|
|
|
|
### ConfigBrowser
|
|
|
|
```zig
|
|
const ConfigBrowser = struct {
|
|
pub const Config = struct {
|
|
variables: []const ConfigVariable, // De zcatconfig
|
|
show_search: bool = true,
|
|
group_by_category: bool = true,
|
|
};
|
|
|
|
pub fn init(config: Config) ConfigBrowser;
|
|
pub fn draw(self: *Self, ctx: *Context, rect: Rect, config_ptr: anytype) DrawResult;
|
|
pub fn handleEvent(self: *Self, event: Event) bool;
|
|
|
|
// Estado
|
|
pub fn hasChanges(self: *Self) bool;
|
|
pub fn getChangedVariables(self: *Self) []const []const u8;
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## Integración con zcatconfig
|
|
|
|
El `ConfigBrowser` se integraría naturalmente con la nueva librería `zcatconfig`:
|
|
|
|
```zig
|
|
const zcatconfig = @import("zcatconfig");
|
|
const ConfigBrowser = zcatgui.widgets.ConfigBrowser;
|
|
|
|
// En el proyecto consumidor:
|
|
const variables = @import("config/variables.zig");
|
|
const Config = @import("config/structures.zig").Config;
|
|
|
|
var config = Config{};
|
|
var browser = ConfigBrowser.init(.{
|
|
.variables = &variables.config_variables,
|
|
});
|
|
|
|
// En draw:
|
|
const result = browser.draw(ctx, rect, &config);
|
|
if (result.value_changed) {
|
|
try zcatconfig.save(&variables.config_variables, Config, &config, allocator, "config.txt");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Priorización Sugerida
|
|
|
|
| Widget | Prioridad | Razón |
|
|
|--------|-----------|-------|
|
|
| TableBrowser | Alta | Necesario para DocListPanel, ProdListPanel |
|
|
| ConfigBrowser | Media | Panel config es nice-to-have, no bloqueante |
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
- **TableBrowser**: Ninguna externa, usa widgets existentes (table, button)
|
|
- **ConfigBrowser**: Requiere `zcatconfig` como dependencia opcional
|
|
|
|
---
|
|
|
|
## Siguiente Paso
|
|
|
|
1. Revisar esta propuesta
|
|
2. Decidir si proceder con implementación
|
|
3. Crear issue/tarea en zcatgui
|
|
|
|
---
|
|
|
|
*Documento generado desde conversación zsimifactu 2025-12-17*
|