zcatgui/docs/PROPUESTA_WIDGETS_BROWSER.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

6.9 KiB

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

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

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:

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