Apply TEAM_STANDARDS Norma #25: project names use lowercase everywhere - repo, directory, module, documentation, imports. No CamelCase in project names. Consistency = less cognitive friction. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
535 lines
16 KiB
Markdown
535 lines
16 KiB
Markdown
# 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/TEAM_STANDARDS/LAST_UPDATE.md
|
|
```
|
|
|
|
### Paso 2: Leer normas completas si es necesario
|
|
```
|
|
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/NORMAS_TRABAJO_CONSENSUADAS.md
|
|
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/QUICK_REFERENCE.md
|
|
```
|
|
|
|
### Paso 3: Leer documentación de investigación
|
|
```
|
|
docs/research/GIO_UI_ANALYSIS.md # Análisis de Gio UI (Go)
|
|
docs/research/IMMEDIATE_MODE_LIBS.md # Comparativa librerías immediate-mode
|
|
docs/research/SIMIFACTU_FYNE_ANALYSIS.md # Requisitos extraídos de Simifactu
|
|
docs/ARCHITECTURE.md # Arquitectura y decisiones de diseño
|
|
```
|
|
|
|
### Paso 4: Verificar estado del proyecto
|
|
```bash
|
|
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ó.
|
|
|
|
---
|
|
|
|
## INFORMACIÓN DEL PROYECTO
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **Nombre** | zcatgui |
|
|
| **Versión** | v0.1.0 - EN DESARROLLO |
|
|
| **Fecha inicio** | 2025-12-09 |
|
|
| **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:
|
|
|
|
1. **Software Rendering por defecto** - Funciona en cualquier ordenador sin GPU
|
|
2. **Cross-platform** - Linux, Windows, macOS
|
|
3. **SSH compatible** - Funciona via X11 forwarding
|
|
4. **Sistema de Macros** - Grabación/reproducción de acciones (piedra angular)
|
|
5. **Sin dependencias pesadas** - Solo SDL2 para ventanas
|
|
|
|
### 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
|
|
|
|
```bash
|
|
# 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/TEAM_STANDARDS/
|
|
|
|
# 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
|
|
|
|
```bash
|
|
# Compilar
|
|
zig build
|
|
|
|
# Tests
|
|
zig build test
|
|
|
|
# Ejemplos (cuando estén implementados)
|
|
zig build hello
|
|
zig build button-demo
|
|
zig build macro-demo
|
|
|
|
# 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
|
|
|
|
```
|
|
zcatgui/
|
|
├── src/
|
|
│ ├── zcatgui.zig # Entry point, re-exports
|
|
│ │
|
|
│ ├── core/
|
|
│ │ ├── context.zig # Context, ID system, state pool
|
|
│ │ ├── layout.zig # Constraints, Flex (de zcatui)
|
|
│ │ ├── style.zig # Color, Style (de zcatui)
|
|
│ │ ├── input.zig # InputState, KeyEvent, MouseEvent
|
|
│ │ └── command.zig # DrawCommand list
|
|
│ │
|
|
│ ├── widgets/
|
|
│ │ ├── button.zig
|
|
│ │ ├── label.zig
|
|
│ │ ├── input.zig # Text entry
|
|
│ │ ├── select.zig # Dropdown
|
|
│ │ ├── checkbox.zig
|
|
│ │ ├── slider.zig
|
|
│ │ ├── table.zig # Editable table (CRÍTICO)
|
|
│ │ ├── list.zig
|
|
│ │ ├── panel.zig # Window-like container
|
|
│ │ ├── split.zig # HSplit/VSplit
|
|
│ │ ├── popup.zig
|
|
│ │ └── modal.zig
|
|
│ │
|
|
│ ├── render/
|
|
│ │ ├── software.zig # Software rasterizer
|
|
│ │ ├── framebuffer.zig # Pixel buffer RGBA
|
|
│ │ └── font.zig # Bitmap + TTF fonts
|
|
│ │
|
|
│ ├── backend/
|
|
│ │ ├── backend.zig # Backend interface
|
|
│ │ └── sdl2.zig # SDL2 implementation
|
|
│ │
|
|
│ └── macro/
|
|
│ ├── event.zig # MacroEvent (teclas raw)
|
|
│ ├── recorder.zig # Grabador
|
|
│ ├── player.zig # Reproductor
|
|
│ └── storage.zig # Guardar/cargar macros
|
|
│
|
|
├── examples/
|
|
│ ├── hello.zig
|
|
│ ├── button_demo.zig
|
|
│ └── macro_demo.zig
|
|
│
|
|
├── docs/
|
|
│ ├── ARCHITECTURE.md # Arquitectura detallada
|
|
│ └── research/
|
|
│ ├── GIO_UI_ANALYSIS.md
|
|
│ ├── IMMEDIATE_MODE_LIBS.md
|
|
│ └── SIMIFACTU_FYNE_ANALYSIS.md
|
|
│
|
|
├── build.zig
|
|
├── build.zig.zon
|
|
├── README.md
|
|
└── CLAUDE.md # Este archivo
|
|
```
|
|
|
|
---
|
|
|
|
## 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:
|
|
1. KISS - menos código = menos bugs
|
|
2. Vim lo hace así y funciona
|
|
3. 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**:
|
|
1. Fase 1: Solo teclado (macros de teclas)
|
|
2. Fase 2: Mouse → traducir a teclas equivalentes
|
|
|
|
### API Propuesta
|
|
|
|
```zig
|
|
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
|
|
|
|
1. **Testing automatizado**: Grabar sesión → convertir en test
|
|
2. **Tutoriales**: Macros que se ejecutan paso a paso
|
|
3. **Repetición**: Grabar tarea repetitiva, asignar a hotkey
|
|
4. **Debugging**: "¿Cómo llegaste a este bug?" → envía el macro
|
|
5. **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)
|
|
|
|
```zig
|
|
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
|
|
|
|
1. **Funciona SIEMPRE** - No depende de drivers GPU
|
|
2. **SSH compatible** - X11 forwarding funciona
|
|
3. **Máxima compatibilidad** - Desde HP viejo hasta Lenovo nuevo
|
|
4. **Simple de debugear** - Es solo un array de pixels
|
|
|
|
### Fonts
|
|
|
|
**Dos opciones soportadas**:
|
|
1. **Bitmap fonts** (embebidos) - Siempre funcionan, rápidos
|
|
2. **TTF** (stb_truetype) - Más flexible, opcional
|
|
|
|
---
|
|
|
|
## PLAN DE DESARROLLO
|
|
|
|
### Fase 0: Setup ✅ COMPLETADA
|
|
- [x] Crear estructura de directorios
|
|
- [x] build.zig con SDL2
|
|
- [x] CLAUDE.md
|
|
- [x] Documentación de investigación
|
|
|
|
### Fase 1: Core + Macros (1 semana)
|
|
- [ ] Context con event loop
|
|
- [ ] Sistema de macros (grabación/reproducción teclas)
|
|
- [ ] Software rasterizer básico (rects, text)
|
|
- [ ] SDL2 backend
|
|
- [ ] Button, Label (para probar)
|
|
|
|
### Fase 2: Widgets Esenciales (2 semanas)
|
|
- [ ] Input (text entry)
|
|
- [ ] Select (dropdown)
|
|
- [ ] Checkbox
|
|
- [ ] List
|
|
- [ ] Layout system
|
|
- [ ] Focus management
|
|
|
|
### Fase 3: Widgets Avanzados (2 semanas)
|
|
- [ ] Table con edición
|
|
- [ ] Split panels
|
|
- [ ] Modal/Popup
|
|
- [ ] Panel con título
|
|
|
|
### Fase 4: Pulido (1 semana)
|
|
- [ ] Themes
|
|
- [ ] Font handling robusto
|
|
- [ ] Documentación
|
|
- [ ] Examples completos
|
|
|
|
---
|
|
|
|
## 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 Gio
|
|
- `docs/research/IMMEDIATE_MODE_LIBS.md` - Comparativa de librerías
|
|
- `docs/research/SIMIFACTU_FYNE_ANALYSIS.md` - Requisitos de Simifactu
|
|
- `docs/ARCHITECTURE.md` - Decisiones de arquitectura
|
|
|
|
### Links externos
|
|
|
|
- [microui GitHub](https://github.com/rxi/microui)
|
|
- [DVUI GitHub](https://github.com/david-vanderson/dvui)
|
|
- [Gio UI](https://gioui.org/)
|
|
- [Dear ImGui](https://github.com/ocornut/imgui)
|
|
|
|
---
|
|
|
|
## 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 (Arno)**: Desarrollador principal
|
|
- **Claude**: Asistente de programación (Claude Code / Opus 4.5)
|
|
|
|
---
|
|
|
|
## NOTAS ZIG 0.15.2
|
|
|
|
```zig
|
|
// Sleep
|
|
std.Thread.sleep(ns) // NO std.time.sleep
|
|
|
|
// ArrayList
|
|
var list = std.ArrayList(T).init(allocator);
|
|
defer list.deinit();
|
|
|
|
// 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| { ... };
|
|
```
|
|
|
|
---
|
|
|
|
## HISTORIAL
|
|
|
|
| Fecha | Versión | Cambios |
|
|
|-------|---------|---------|
|
|
| 2025-12-09 | v0.1.0 | Proyecto creado, estructura base, documentación |
|
|
|
|
---
|
|
|
|
## ESTADO ACTUAL
|
|
|
|
**El proyecto está EN FASE INICIAL**
|
|
|
|
- ✅ Estructura de directorios creada
|
|
- ✅ build.zig configurado con SDL2
|
|
- ✅ Documentación de investigación completa
|
|
- ✅ CLAUDE.md con toda la información
|
|
- ⏳ Código fuente pendiente de implementar
|
|
|
|
**Próximo paso**: Implementar Fase 1 (Core + Macros)
|