- Añadida sección 🔴 BUG PENDIENTE con síntoma y pistas - Actualizado historial: v0.20.0 y v0.21.0 - Añadido docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md a Paso 3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
34 KiB
zcatgui - GUI Library para Zig
IMPORTANTE PARA CLAUDE: Lee la sección "PROTOCOLO DE INICIO" antes de hacer cualquier cosa.
PROTOCOLO DE INICIO (LEER PRIMERO)
Paso 1: Leer normas del equipo
/mnt/cello2/arno/re/recode/teamdocs/LAST_UPDATE.md
Paso 2: Leer normas completas si es necesario
/mnt/cello2/arno/re/recode/teamdocs/normas/NORMAS_TRABAJO_CONSENSUADAS.md
/mnt/cello2/arno/re/recode/teamdocs/QUICK_REFERENCE.md
/mnt/cello2/arno/re/recode/teamdocs/agenda/2025-12_diciembre.md # Trabajo diario
Paso 3: Leer documentación
REFERENCE.md # ⭐ MANUAL DE REFERENCIA COMPLETO
docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md # 🔴 BUG PENDIENTE - LEER PRIMERO
docs/ADVANCED_TABLE_MERGE_PLAN.md # Plan merge Table → AdvancedTable
docs/research/DVUI_AUDIT_2025-12-17.md # Auditoría DVUI
docs/DEVELOPMENT_PLAN.md # Plan de desarrollo por fases
docs/MOBILE_WEB_BACKENDS.md # Documentación backends mobile/web
docs/research/WIDGET_COMPARISON.md # Comparativa zcatgui vs DVUI vs Gio
docs/ARCHITECTURE.md # Arquitectura y decisiones de diseño
Paso 4: Verificar estado del proyecto
cd /mnt/cello2/arno/re/recode/zig/zcatgui
git status
git log --oneline -3
zig build test
Paso 5: Continuar trabajo
Una vez verificado el estado, continúa desde donde se dejó.
REGLA CRÍTICA: NO EJECUTAR BINARIOS GUI
NUNCA ejecutar programas GUI directamente con ./programa o en background
Los procesos GUI no terminan correctamente desde Claude Code y dejan shells zombie que:
- Consumen contexto de la conversación con mensajes "Background Bash running"
- Fuerzan compactaciones prematuras del contexto
- Degradan severamente la calidad de la sesión de trabajo
Alternativas:
- Para verificar que compila:
zig build(sin ejecutar) - Para probar muy brevemente:
timeout 2s ./programa 2>&1 || true - Mejor opción: Pedir al usuario que lo pruebe y reporte
Esta regla está documentada en teamdocs desde 2025-11-30.
DOCUMENTACIÓN EN TEAMDOCS
Al documentar trabajo en teamdocs/agenda/:
- Entrada en agenda: Máximo 5 líneas (QUÉ + CUÁNDO + link)
- Detalle técnico: Crear hito en
agenda/hitos/ - Protocolo completo: Ver
teamdocs/ESTRUCTURA_DOCUMENTACION.md
Formato de entrada:
## Fecha - Título ✅
Resumen breve (1-2 frases). Resultado principal.
→ [Detalle técnico](hitos/YYYY-MM-DD_tema.md)
⭐ Paridad Visual DVUI - FASES 1+2 COMPLETADAS ✅
Estado: Fases 1 y 2 completadas (2025-12-17) Auditoría original:
docs/research/DVUI_AUDIT_2025-12-17.md(570 líneas)
El Problema (RESUELTO)
zcatgui tenía MÁS widgets que DVUI pero DVUI se veía mejor por falta de:
- ✅ Esquinas redondeadas →
fillRoundedRectcon edge-fade AA - ✅ Anti-aliasing en bordes → edge-fade technique implementada
- ✅ Transiciones suaves → HoverTransition en Button/Select
- ✅ Sombras en paneles/modales → Panel/Modal con shadow
- ✅ Focus ring AA → 9 widgets con focus ring
Sistema Dual Implementado
// style.zig
pub const RenderMode = enum { simple, fancy };
var global_render_mode: RenderMode = .fancy; // Default: bonito
// Uso en widgets
if (Style.isFancy() and config.corner_radius > 0) {
ctx.pushCommand(Command.roundedRect(...));
} else {
ctx.pushCommand(Command.rect(...));
}
Widgets Actualizados
| Widget | corner_radius | shadow | Notas |
|---|---|---|---|
| Button | 4 | - | Esquinas redondeadas en fancy mode |
| Panel | 6 | ✅ offset 4px | Borde y shadow |
| TextInput | 3 | - | Esquinas sutiles |
| Select | 3 | - | Esquinas sutiles |
| Modal | 8 | ✅ offset 6px | Diálogo + botones + input |
Código Añadido
framebuffer.zig: +350 LOC (fillRoundedRect,drawRoundedRect, edge-fade AA)command.zig: +69 LOC (nuevos comandosrounded_rect,rounded_rect_outline)style.zig: +33 LOC (RenderMode system)- Widgets: ~120 LOC entre todos
Total: ~590 líneas nuevas/modificadas
Fase 2: Transiciones + Focus Ring ✅ COMPLETADA
HoverTransition helper (animation.zig):
update()yupdateWithPress()para animar hacia targetblend()yblendThree()para interpolar colores- Speed configurable (default ~125ms transición)
Focus ring helper (command.zig):
focusRing()yfocusRingColor()para indicador de foco- Dibuja 2px fuera del widget con AA
- Color primario semi-transparente (alpha 180)
Widgets con focus ring:
| Widget | Transiciones | Focus Ring | Esquinas |
|---|---|---|---|
| Button | ✅ buttonStateful() |
- | ✅ |
| Select | ✅ Automático | ✅ | ✅ |
| TextInput | - | ✅ | ✅ |
| NumberEntry | - | ✅ | ✅ |
| Radio | - | ✅ (opción) | ✅ |
| Slider | - | ✅ (thumb) | ✅ |
| Tabs | - | ✅ (tab) | ✅ |
| Table | - | ✅ (borde) | - |
| TextArea | - | ✅ | ✅ |
// Button con transiciones (opcional)
var btn_state = button.ButtonState{};
if (button.buttonStateful(&ctx, &btn_state, "Click me")) { ... }
// Focus ring se dibuja automáticamente cuando widget tiene foco
Fase 3: Efectos Avanzados (OPCIONAL)
- Mejorar uso de gradientes
- Blur effect para backdrops
Documentación de Referencia
docs/research/DVUI_AUDIT_2025-12-17.md- Auditoría completadocs/research/WIDGET_COMPARISON.md- Comparativa (actualizar después)
✅ TTF Rendering - RESUELTO (2025-12-17) ⭐⭐⭐
Estado: ✅ COMPLETADO - zcatttf v1.0 integrado y funcionando perfectamente Documentación:
/mnt/cello2/arno/re/recode/teamdocs/agenda/hitos/2025-12-17_zcatttf_v1.0.md
El Problema (16-17 Dic)
El texto TTF se renderizaba como garabatos ilegibles. 2 días de debugging con múltiples intentos fallidos.
Solución: zcatttf v1.0
TRADUCCIÓN LITERAL de stb_truetype.h, sin intentar "mejorar" o "reimaginar".
Bug final: y_offset = iy0 (negativo) → y_offset = -iy0 (positivo).
El bearing_y debe ser positivo para glyphs encima de la baseline.
Lección Clave
"No reimplementar, TRADUCIR" Si existe código C que funciona, traducirlo literalmente. La humildad técnica es fundamental.
| Campo | Valor |
|---|---|
| Librería | /mnt/cello2/arno/re/recode/zig/zcatttf/ |
| Versión | v1.0 |
| Algoritmo | Traducción literal stb_truetype (~1,200 LOC rasterize.zig) |
| Estado | ✅ FUNCIONA PERFECTAMENTE en zsimifactu |
Archivos clave
src/render/ttf.zig- Wrapper sobre zcatttf (API compatible)src/render/embedded_font.zig- Fuente DroidSans embebidabuild.zig.zon- Dependencia de zcatttf
Uso
var ttf = try TtfFont.initEmbedded(allocator);
defer ttf.deinit();
ttf.setSize(14);
ttf.drawText(fb, x, y, "Hola UTF-8: áéíóú ñ €", color, clip);
Fuentes TTF: Estado Técnico
Estado actual (v0.19.0) - FUNCIONAL
- ✅ Parsing TTF via zcatttf (cmap format 4 y 12)
- ✅ Rasterización con áreas trapezoidales (antialiasing)
- ✅ Fuente embebida (DroidSans)
- ✅ Soporte UTF-8 completo (áéíóú ñ €)
- ✅ Cache de glyphs renderizados
Uso actual
const ttf = @import("render/ttf.zig");
// Opción 1: Fuente embebida
var font = try ttf.TtfFont.initEmbedded(allocator);
// Opción 2: Cargar archivo
var font = try ttf.TtfFont.loadFromFile(allocator, "/path/to/font.ttf");
defer font.deinit();
font.setSize(14);
font.drawText(fb, x, y, "Texto con UTF-8: ñ €", color, clip);
INFORMACIÓN DEL PROYECTO
| Campo | Valor |
|---|---|
| Nombre | zcatgui |
| Versión | v0.19.0 |
| Fecha inicio | 2025-12-09 |
| Estado | ✅ COMPLETO - 37 widgets, ~35K LOC, 4 backends, TTF funcional |
| Lenguaje | Zig 0.15.2 |
| Paradigma | Immediate Mode GUI |
| Inspiración | Gio (Go), microui (C), DVUI (Zig), Dear ImGui (C++) |
| Proyecto hermano | zcatui (TUI library) |
Descripción
zcatgui es una librería GUI immediate-mode para Zig con las siguientes características:
- Software Rendering por defecto - Funciona en cualquier ordenador sin GPU
- Cross-platform - Linux, Windows, macOS, Web (WASM), Android, iOS
- SSH compatible - Funciona via X11 forwarding
- Sistema de Macros - Grabación/reproducción de acciones (piedra angular)
- Sin dependencias pesadas - Solo SDL2 para desktop, nativo para mobile/web
Filosofía
"Máxima compatibilidad, mínimas dependencias, control total del usuario"
- Funciona en cualquier ordenador (viejo HP, nuevo Lenovo, servidor SSH)
- Software rendering primero, GPU opcional después
- Sistema de macros integrado desde el diseño
- Immediate mode = estado explícito, sin threading hell
RUTAS IMPORTANTES
# Este proyecto
/mnt/cello2/arno/re/recode/zig/zcatgui/
# Proyecto hermano (TUI)
/mnt/cello2/arno/re/recode/zig/zcatui/
# Proyecto de referencia (usa Fyne, queremos replicar funcionalidad)
/mnt/cello2/arno/re/recode/go/simifactu/
# Normas del equipo
/mnt/cello2/arno/re/recode/teamdocs/
# Compilador Zig 0.15.2
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig
COMANDOS FRECUENTES
# Compilar (desktop)
zig build
# Tests
zig build test
# Ejemplos desktop
zig build hello
zig build macro-demo
zig build widgets-demo
zig build table-demo
# WASM (navegador)
zig build wasm # Genera web/zcatgui-demo.wasm
cd web && python3 -m http.server # Servir y abrir localhost:8000
# Android (requiere NDK)
zig build android # ARM64 para dispositivo
zig build android-x86 # x86_64 para emulador
# iOS (requiere Xcode en macOS)
zig build ios # ARM64 para dispositivo
zig build ios-sim # ARM64 para simulador
# Git
git status
git add -A && git commit -m "mensaje"
git push
ARQUITECTURA
Paradigma: Immediate Mode
┌─────────────────────────────────────────────────────────────┐
│ IMMEDIATE MODE │
├─────────────────────────────────────────────────────────────┤
│ while (running) { │
│ events = pollEvents(); // Input │
│ updateState(events); // TÚ manejas estado │
│ commands = drawUI(state); // Genera comandos │
│ render(commands); // Dibuja │
│ } │
└─────────────────────────────────────────────────────────────┘
vs Retained Mode (Fyne):
- Framework mantiene árbol de widgets
- Callbacks para cambios
- fyne.Do() para threading
- Estado oculto, sincronización compleja
Capas de la Librería
┌─────────────────────────────────────────────────────────────┐
│ Capa 4: Widgets de alto nivel │
│ (Table, Panel, Select, Modal, etc.) │
├─────────────────────────────────────────────────────────────┤
│ Capa 3: Sistema de Macros │
│ (Grabación, Reproducción, Inyección de teclas) │
├─────────────────────────────────────────────────────────────┤
│ Capa 2: Core UI │
│ (Context, Layout, Style, Input, Commands) │
├─────────────────────────────────────────────────────────────┤
│ Capa 1: Rendering │
│ (Software Rasterizer, Framebuffer, Fonts) │
├─────────────────────────────────────────────────────────────┤
│ Capa 0: Backend │
│ (SDL2 - ventanas, eventos, display) │
└─────────────────────────────────────────────────────────────┘
Estructura de Archivos (ACTUAL v0.16.0)
zcatgui/
├── src/
│ ├── zcatgui.zig # Entry point, re-exports, conditional backend imports
│ │
│ ├── core/
│ │ ├── context.zig # ✅ Context, ID system, command pool, FrameArena
│ │ ├── layout.zig # ✅ Rect, Constraint, LayoutState
│ │ ├── style.zig # ✅ Color, Style, Theme (5 themes)
│ │ ├── input.zig # ✅ Key, KeyEvent, MouseEvent, InputState
│ │ ├── command.zig # ✅ DrawCommand list
│ │ ├── clipboard.zig # ✅ Clipboard support
│ │ ├── dragdrop.zig # ✅ Drag & drop system
│ │ ├── shortcuts.zig # ✅ Keyboard shortcuts manager
│ │ ├── focus_group.zig # ✅ Focus groups
│ │ ├── accessibility.zig # ✅ Accessibility (ARIA roles)
│ │ └── gesture.zig # ✅ Gesture recognizer (tap, swipe, pinch, rotate)
│ │
│ ├── widgets/ # 37 widgets implementados
│ │ ├── widgets.zig # Re-exports
│ │ ├── label.zig, button.zig, text_input.zig, checkbox.zig
│ │ ├── select.zig, list.zig, focus.zig, table.zig
│ │ ├── split.zig, panel.zig, modal.zig, autocomplete.zig
│ │ ├── slider.zig, scroll.zig, tabs.zig, radio.zig, menu.zig
│ │ ├── progress.zig, tooltip.zig, toast.zig
│ │ ├── textarea.zig, tree.zig, badge.zig
│ │ ├── number_entry.zig, reorderable.zig
│ │ ├── breadcrumb.zig, image.zig, icon.zig
│ │ ├── color_picker.zig, date_picker.zig, chart.zig
│ │ └── calendar.zig
│ │
│ ├── render/
│ │ ├── software.zig # ✅ SoftwareRenderer
│ │ ├── framebuffer.zig # ✅ Framebuffer RGBA (u32 pixels)
│ │ ├── font.zig # ✅ Bitmap font 8x8
│ │ ├── ttf.zig # ✅ TTF font support (stb_truetype)
│ │ ├── animation.zig # ✅ Animation system, easing, springs
│ │ ├── effects.zig # ✅ Shadows, gradients, blur
│ │ └── antialiasing.zig # ✅ Anti-aliased rendering
│ │
│ ├── backend/
│ │ ├── backend.zig # ✅ Backend interface (VTable)
│ │ ├── sdl2.zig # ✅ SDL2 (desktop: Linux/Win/Mac)
│ │ ├── wasm.zig # ✅ WASM (navegador)
│ │ ├── android.zig # ✅ Android (ANativeActivity)
│ │ └── ios.zig # ✅ iOS (UIKit bridge)
│ │
│ ├── macro/
│ │ └── macro.zig # ✅ MacroRecorder, MacroPlayer, MacroStorage
│ │
│ ├── panels/
│ │ └── panels.zig # ✅ Lego Panels architecture
│ │
│ └── utils/
│ └── utils.zig # ✅ FrameArena, ObjectPool, Benchmark
│
├── examples/
│ ├── hello.zig # Ejemplo básico
│ ├── macro_demo.zig # Demo macros
│ ├── widgets_demo.zig # Demo widgets
│ ├── table_demo.zig # Demo Table/Split/Panel
│ ├── wasm_demo.zig # ✅ Demo WASM (navegador)
│ └── android_demo.zig # ✅ Demo Android
│
├── web/ # ✅ WASM support
│ ├── index.html # Demo HTML
│ ├── zcatgui.js # JavaScript glue code
│ └── zcatgui-demo.wasm # Compiled WASM (~18KB)
│
├── ios/ # ✅ iOS support
│ ├── ZcatguiBridge.h # Objective-C header
│ └── ZcatguiBridge.m # UIKit implementation
│
├── docs/
│ ├── ARCHITECTURE.md
│ ├── DEVELOPMENT_PLAN.md # ⭐ Plan maestro
│ ├── MOBILE_WEB_BACKENDS.md # ✅ Documentación mobile/web
│ └── research/
│ ├── GIO_UI_ANALYSIS.md
│ ├── IMMEDIATE_MODE_LIBS.md
│ ├── WIDGET_COMPARISON.md
│ └── SIMIFACTU_FYNE_ANALYSIS.md
│
├── build.zig # Build con targets: wasm, android, ios
├── build.zig.zon
├── CLAUDE.md # Este archivo
└── REFERENCE.md # ⭐ Manual de referencia completo (1370 líneas)
SISTEMA DE MACROS (PIEDRA ANGULAR)
Concepto
El sistema de macros permite grabar y reproducir todas las acciones del usuario.
Principio: Grabar teclas raw, no comandos abstractos.
Usuario pulsa: Tab, Tab, Enter, "texto", Escape
Grabamos: [Tab, Tab, Enter, t, e, x, t, o, Escape]
Reproducimos: Inyectamos exactamente esas teclas
Por qué teclas raw (no comandos)
| Enfoque | Pros | Contras |
|---|---|---|
| Teclas raw | Simple, mínima memoria, reproducción exacta | Depende del estado inicial |
| Comandos semánticos | Más robusto | Complejo, más memoria, traducción bidireccional |
Decisión: Teclas raw (como Vim). Razones:
- KISS - menos código = menos bugs
- Vim lo hace así y funciona
- El estado inicial es controlable
Manejo del ratón
Casi todo lo que hace el ratón se puede expresar como teclado:
| Acción ratón | Equivalente teclado |
|---|---|
| Click en botón | Tab hasta focus + Enter |
| Click en fila 5 | Flechas hasta fila 5 |
| Scroll down | PageDown o flechas |
| Drag splitter | Ctrl+flechas |
Estrategia:
- Fase 1: Solo teclado (macros de teclas)
- Fase 2: Mouse → traducir a teclas equivalentes
API Propuesta
pub const MacroRecorder = struct {
events: ArrayList(KeyEvent),
recording: bool,
pub fn start(self: *MacroRecorder) void;
pub fn stop(self: *MacroRecorder) []const KeyEvent;
pub fn record(self: *MacroRecorder, key: KeyEvent) void;
pub fn save(self: *MacroRecorder, path: []const u8) !void;
pub fn load(allocator: Allocator, path: []const u8) !MacroRecorder;
};
pub const MacroPlayer = struct {
pub fn play(
events: []const KeyEvent,
inject_fn: *const fn(KeyEvent) void,
delay_ms: u32,
) void;
};
Casos de Uso
- Testing automatizado: Grabar sesión → convertir en test
- Tutoriales: Macros que se ejecutan paso a paso
- Repetición: Grabar tarea repetitiva, asignar a hotkey
- Debugging: "¿Cómo llegaste a este bug?" → envía el macro
- Demos: Grabar demos que se reproducen en la app
WIDGETS PRIORITARIOS
Basado en análisis de Simifactu (ver docs/research/SIMIFACTU_FYNE_ANALYSIS.md):
| # | Widget | Prioridad | Descripción |
|---|---|---|---|
| 1 | Table | CRÍTICA | Edición in-situ, navegación teclado, dirty tracking |
| 2 | Input | CRÍTICA | Text entry con validación |
| 3 | Select | CRÍTICA | Dropdown selection |
| 4 | Panel | ALTA | Container con título y bordes |
| 5 | Split | ALTA | HSplit/VSplit draggable |
| 6 | Button | ALTA | Con estados disabled, importance |
| 7 | Modal | MEDIA | Diálogos modales |
| 8 | List | MEDIA | Lista seleccionable |
| 9 | Checkbox | MEDIA | Toggle boolean |
| 10 | Label | BAJA | Texto estático |
RENDERING
Software Rasterizer (Command List approach)
pub const DrawCommand = union(enum) {
rect: struct {
x: i32,
y: i32,
w: u32,
h: u32,
color: Color,
},
text: struct {
x: i32,
y: i32,
text: []const u8,
color: Color,
font: *Font,
},
line: struct {
x1: i32,
y1: i32,
x2: i32,
y2: i32,
color: Color,
},
clip: struct {
x: i32,
y: i32,
w: u32,
h: u32,
},
clip_end,
};
Flujo:
Widgets → Commands → Software Rasterizer → Framebuffer → SDL_Texture → Display
Por qué Software Rendering
- Funciona SIEMPRE - No depende de drivers GPU
- SSH compatible - X11 forwarding funciona
- Máxima compatibilidad - Desde HP viejo hasta Lenovo nuevo
- Simple de debugear - Es solo un array de pixels
Fonts
Dos opciones soportadas:
- Bitmap fonts (embebidos) - Siempre funcionan, rápidos
- TTF (stb_truetype) - Más flexible, opcional
PLAN DE DESARROLLO
Fase 0: Setup ✅ COMPLETADA
- Crear estructura de directorios
- build.zig con SDL2
- CLAUDE.md
- Documentación de investigación
Fase 1: Core + Macros ✅ COMPLETADA
- Context con event loop
- Sistema de macros (grabación/reproducción teclas)
- Software rasterizer básico (rects, text, lines)
- SDL2 backend
- Framebuffer RGBA
Fase 2: Widgets Esenciales ✅ COMPLETADA
- Label (static text)
- Button (clickable, importance levels)
- TextInput (editable text, cursor, selection)
- Checkbox (boolean toggle)
- Select (dropdown)
- List (scrollable selection)
- Focus management (FocusManager, FocusRing)
Fase 3: Widgets Avanzados (PENDIENTE)
- Table con edición (CRÍTICO)
- Split panels (HSplit/VSplit draggable)
- Panel (container con título)
- Modal/Popup
Fase 4: Pulido (PENDIENTE)
- Themes hot-reload
- TTF fonts (stb_truetype)
- Documentación completa
- Más examples
REFERENCIAS Y RECURSOS
Librerías estudiadas
| Librería | Lenguaje | LOC | Valor para nosotros |
|---|---|---|---|
| microui | C | 1,100 | Referencia arquitectura mínima |
| DVUI | Zig | 15,000 | Único ejemplo Zig native |
| Dear ImGui | C++ | 60,000 | API design, features |
| Gio | Go | - | Immediate mode moderno |
| Nuklear | C | 30,000 | Vertex buffer approach |
Documentación detallada
docs/research/GIO_UI_ANALYSIS.md- Análisis completo de Giodocs/research/IMMEDIATE_MODE_LIBS.md- Comparativa de libreríasdocs/research/SIMIFACTU_FYNE_ANALYSIS.md- Requisitos de Simifactudocs/ARCHITECTURE.md- Decisiones de arquitectura
Links externos
DECISIONES DE DISEÑO CONSENSUADAS
1. Immediate Mode vs Retained Mode
Decisión: Immediate Mode Razón: Control total, sin threading hell (fyne.Do()), estado explícito
2. Software Rendering vs GPU
Decisión: Software por defecto, GPU opcional futuro Razón: Máxima compatibilidad (SSH, HP viejo, cualquier driver)
3. Sistema de Macros
Decisión: Teclas raw, no comandos abstractos Razón: Simple, como Vim, menos código = menos bugs
4. Backend inicial
Decisión: SDL2 Razón: Cross-platform probado, fácil de usar
5. Fonts
Decisión: Bitmap embebido + TTF opcional Razón: Bitmap siempre funciona, TTF para flexibilidad
6. Enfoque de desarrollo
Decisión: Híbrido (estudiar DVUI/microui, implementar desde cero) Razón: Aprender haciendo, control total, sin dependencias no deseadas
RELACIÓN CON ZCATUI
zcatui (TUI) y zcatgui (GUI) son proyectos hermanos:
| Aspecto | zcatui | zcatgui |
|---|---|---|
| Target | Terminal (ANSI) | Ventana gráfica |
| Rendering | Escape codes | Software rasterizer |
| Paradigma | Immediate mode | Immediate mode |
| Layout | Constraint-based | Constraint-based (reusar) |
| Style | Color/Modifier | Color/Style (reusar) |
| Widgets | 35 widgets | En desarrollo |
Código a reutilizar de zcatui:
- Sistema de Layout (Constraint, Flex)
- Sistema de Style (Color, Style)
- Conceptos de Focus
- Patterns de widgets
EQUIPO
- Usuario (R.Eugenio): Desarrollador principal
- Claude: Asistente de programación (Claude Code / Opus 4.5)
NOTAS ZIG 0.15.2
// Sleep
std.Thread.sleep(ns) // NO std.time.sleep
// ArrayList - CAMBIÓ en 0.15
// VIEJO: std.ArrayList(T).init(allocator)
// NUEVO: std.ArrayListUnmanaged(T) + pasar allocator a cada operación
var list: std.ArrayListUnmanaged(T) = .{};
defer list.deinit(allocator);
try list.append(allocator, item); // allocator en cada append
// HashMap
var map = std.AutoHashMap(K, V).init(allocator);
defer map.deinit();
// Error handling
fn foo() !T { ... }
const result = try foo();
const result = foo() catch |err| { ... };
// File I/O - cambió en 0.15
const file = try std.fs.cwd().createFile(path, .{});
_ = try file.write("data"); // Directo
// stdout - cambió en 0.15
const stdout = std.fs.File.stdout(); // NO std.io.getStdOut()
// O usar std.debug.print() que es más simple
// build.zig.zon - requiere fingerprint
.{
.fingerprint = 0x...,
.name = .proyecto, // enum literal, no string
...
}
HISTORIAL
| Fecha | Versión | Cambios |
|---|---|---|
| 2025-12-09 | v0.1.0 | Proyecto creado, estructura base, documentación |
| 2025-12-09 | v0.2.0 | Widgets Fase 2 completados (Label, Button, TextInput, Checkbox, Select, List, Focus) |
| 2025-12-09 | v0.3.0 | Widgets Fase 3 completados (Table editable, Split panels, Panel container) |
| 2025-12-09 | v0.3.5 | Keyboard integration: InputState ahora trackea teclas, Table responde a flechas/Enter/Escape/Tab/F2 |
| 2025-12-09 | v0.4.0 | Modal widget: diálogos modales (alert, confirm, input), plan extendido documentado |
| 2025-12-09 | v0.5.0 | AutoComplete widget, comparativa DVUI/Gio/zcatui en WIDGET_COMPARISON.md |
| 2025-12-09 | v0.6.0 | FASE 1 Optimización: FrameArena, ObjectPool, dirty rectangles, Benchmark suite |
| 2025-12-09 | v0.7.0 | FASE 2: Progress, Tooltip, Toast, Spinner |
| 2025-12-09 | v0.8.0 | FASE 2: TextArea, Tree, Badge/TagGroup |
| 2025-12-09 | v0.9.0 | FASE 3: Image, ReorderableList, ColorPicker, DatePicker |
| 2025-12-09 | v0.10.0 | FASE 4: NumberEntry, RichText, Breadcrumb |
| 2025-12-09 | v0.11.0 | FASE 5: Canvas, Charts (line/bar/pie), Icon system (60+ icons) |
| 2025-12-09 | v0.12.0 | FASE 6: Clipboard, DragDrop, Shortcuts, FocusGroups |
| 2025-12-09 | v0.13.0 | FASE 7: Animation/Easing, Effects (shadow/gradient/blur), VirtualScroll, AA rendering |
| 2025-12-09 | v0.14.0 | FASE 8: Accessibility system, Testing framework, 274 tests |
| 2025-12-09 | v0.14.1 | FASE 9: Gio parity - 12 widgets + gesture system |
| 2025-12-09 | v0.15.0 | FASE 10: Mobile/Web - WASM, Android, iOS backends |
| 2025-12-09 | v0.15.0 | Documentación: REFERENCE.md completo (1370 líneas) |
| 2025-12-11 | v0.15.1 | FocusSystem rediseñado: registration_group/active_group, focus implícito |
| 2025-12-11 | v0.15.2 | Widgets adaptados a FocusSystem: numberentry, textarea, select, radio, slider, tabs |
| 2025-12-16 | v0.16.0 | TTF rasterization con antialiasing (supersampling 2x) |
| 2025-12-16 | v0.16.1 | Fuente embebida: TtfFont.initEmbedded() |
| 2025-12-16 | v0.16.2 | Fix TTF: DroidSans (187KB) reemplaza AdwaitaSans (variable). Y-flip rasterización. |
| 2025-12-17 | v0.17.0 | ⭐⭐⭐ Integración zcatttf v1.0 - TTF FUNCIONA PERFECTAMENTE |
| 2025-12-17 | v0.18.0 | Paridad Visual DVUI Fase 1: RenderMode dual, esquinas redondeadas, sombras |
| 2025-12-17 | v0.19.0 | Paridad Visual DVUI Fase 2: HoverTransition, Focus Ring AA en 9 widgets |
| 2025-12-17 | v0.20.0 | AdvancedTable: 8 fases completas (~2,700 LOC) - Schema, CRUD, Sorting, Lookup |
| 2025-12-17 | v0.21.0 | AdvancedTable: +990 LOC (multi-select, search, validation) - 🔴 BUG TECLADO |
🔴 BUG PENDIENTE: AdvancedTable Teclado
Estado: NO RESUELTO (2025-12-17) Documentación:
docs/BUG_ADVANCEDTABLE_KEYBOARD_2025-12-17.md
Síntoma
Las flechas ↑↓←→ no mueven la selección en AdvancedTable (zsimifactu WHO panel).
Lo que sabemos
- Click en filas funciona
has_focus=truecuando widget tiene foconavKeyPressed()detecta teclas (probado con debug)- Pero
handleKeyboard()no las procesa
Pista clave
El widget Table original SÍ funciona con teclado. Comparar implementaciones.
Próximo paso
Añadir debug DENTRO de handleKeyboard() (no antes de if (has_focus)).
ESTADO ACTUAL
✅ PROYECTO COMPLETADO - v0.21.0 (con bug pendiente en AdvancedTable)
Para detalles técnicos completos, ver
REFERENCE.md(1370 líneas de documentación)
Widgets (37 total):
Básicos (7): Label, Button, Checkbox, Radio, Slider, TextInput, NumberEntry
Contenedores (6): Panel, Split, Modal, Scroll, Tabs, Menu
Datos (5): List, Table, Tree, ReorderableList, VirtualScroll
Feedback (4): Progress, Tooltip, Toast, Spinner
Input avanzado (5): AutoComplete, Select, TextArea, ColorPicker, DatePicker
Especial (5): Image, Icon, Canvas, Chart, RichText
Navegación (2): Breadcrumb, Focus
Sistema (1): Badge/TagGroup
Backends (5 plataformas):
- SDL2: Desktop (Linux, Windows, macOS)
- WASM: Navegadores web (Canvas 2D)
- Android: ANativeActivity + ANativeWindow
- iOS: UIKit bridge (Objective-C)
Core Systems:
- Context: FrameArena (O(1) reset), dirty rectangles, ID system
- Input: Keyboard, mouse, touch, shortcuts, focus groups, gestures
- Rendering: Software renderer, anti-aliasing, effects (shadow, gradient, blur)
- Animation: Easing functions (20+), AnimationManager, Springs
- Accessibility: Roles, states, announcements, live regions
- Testing: TestRunner, SnapshotTester, Assertions
- Macros: Recording, playback, storage
- Themes: 5 themes (dark, light, high_contrast, nord, dracula)
- Clipboard: SDL2 clipboard integration
- Drag & Drop: Type-filtered drop zones
- Gestures: Tap, double-tap, long-press, swipe, pinch, rotate
Métricas:
- ~35,000 LOC en 81 archivos fuente
- 0 warnings, 0 memory leaks
- WASM: ~18KB compilado
Verificar que funciona:
cd /mnt/cello2/arno/re/recode/zig/zcatgui
# Tests
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig build test
# Desktop
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig build
# WASM (genera web/zcatgui-demo.wasm)
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig build wasm
# Android (requiere NDK)
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig build android
# iOS (requiere macOS + Xcode)
/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig build ios
DOCUMENTACIÓN DISPONIBLE
| Documento | Descripción |
|---|---|
| REFERENCE.md | ⭐ Manual de referencia completo (1370 líneas) |
| docs/DEVELOPMENT_PLAN.md | Plan de desarrollo por fases (10 fases completadas) |
| docs/MOBILE_WEB_BACKENDS.md | Guía de backends WASM/Android/iOS |
| docs/ARCHITECTURE.md | Decisiones de arquitectura |
| docs/research/ | Análisis de librerías de referencia |
SISTEMA DE FOCUS - RESUELTO (2025-12-11)
El sistema de focus fue rediseñado y ahora funciona correctamente.
Documentación completa
/mnt/cello2/arno/re/recode/zig/zcatgui/docs/FOCUS_TRANSITION_2025-12-11.md
Arquitectura final
FocusSystem
|
+---------------+---------------+
| |
FocusGroup 1 FocusGroup 2
(Panel Lista) (Panel Detalle)
| |
Table widget TextInput widgets
| |
- registerFocusable() - registerFocusable()
- hasFocus() -> true/false - hasFocus() -> true/false
Conceptos clave
- registration_group: Grupo donde se registran widgets durante draw
- active_group: Grupo con focus de teclado (solo cambia con F6/clic)
- Focus implícito: Primer widget del grupo activo tiene focus si
focused_index == null
API para widgets
// 1. Generar ID único basado en dirección del state
const widget_id: u64 = @intFromPtr(state);
// 2. Registrar en el grupo de focus activo
ctx.registerFocusable(widget_id);
// 3. Al hacer clic, solicitar focus
if (clicked) {
ctx.requestFocus(widget_id);
}
// 4. Verificar si tiene focus
const has_focus = ctx.hasFocus(widget_id);
state.focused = has_focus;
Widgets integrados con FocusSystem
| Widget | Estado |
|---|---|
| Table | Adaptado - inicializa selected_row/col a 0 |
| TextInput | Correcto |
| NumberEntry | Adaptado |
| TextArea | Adaptado |
| Select | Adaptado |
| Radio | Adaptado |
| Slider | Adaptado |
| Tabs | Adaptado |
Widgets sin FocusSystem (no lo necesitan)
- Modales: Menu, Modal, Tooltip, Toast
- Acción única: Button, Checkbox, Switch
- Solo visualización: Label, Progress, Badge, Icon, Image
PROYECTOS RELACIONADOS
| Proyecto | Ruta | Descripción |
|---|---|---|
| zcatttf | /mnt/cello2/arno/re/recode/zig/zcatttf/ |
⭐ Librería TTF v1.0 - COMPLETA (dependencia de zcatgui) |
| zsimifactu | /mnt/cello2/arno/re/recode/zig/zsimifactu/ |
App de facturación Zig (consumidor principal) |
| zcatui | /mnt/cello2/arno/re/recode/zig/zcatui/ |
TUI library (proyecto hermano) |
| zcatp2p | /mnt/cello2/arno/re/recode/zig/zcatp2p/ |
Librería P2P (v1.0.0 completa) |
| simifactu | /mnt/cello2/arno/re/recode/go/simifactu/ |
App de referencia (Fyne/Go) |
REFERENCIAS EXTERNAS
- microui - Arquitectura mínima
- DVUI - Zig GUI reference
- Gio - Go immediate-mode
- Dear ImGui - C++ reference