Commit graph

27 commits

Author SHA1 Message Date
dacc3eb57d perf: Smart Cursor - widgets request cursor blink explicitly
Implements "Active Request" pattern for cursor animation:
- Add requested_cursor_blink flag to Context (reset each frame)
- Add requestCursorBlink() function for widgets to call
- needsCursorAnimation() now returns false if no widget requested it
- TextInput calls requestCursorBlink() when focused and editable
- CellEditor calls requestCursorBlink() when editing

This eliminates unnecessary redraws when no cursor is visible
(e.g., in Config tab with tables but no active text input).

Also raised CURSOR_BLINK_PERIOD_MS from 300ms to 600ms (GTK/Linux standard).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 11:59:24 +01:00
f366a30b66 perf: Reduce cursor blink rate from 300ms to 600ms
GTK/Linux standard rate. Reduces unnecessary redraws by ~50%.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 01:07:49 +01:00
4cdc8c44e2 feat(panel): derived_bg en PanelFrameResult
Añade derived_bg al resultado de drawPanelFrame para que los paneles
puedan usar el color exacto del fondo para las tablas (mimetismo visual).

Las tablas deben usar frame_result.derived_bg como row_normal para
integrarse visualmente con el panel.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 13:07:56 +01:00
f17104c08b feat(bevel): API configurable de biseles 3D
Nueva API BevelStyle para control fino de efectos 3D:
- effect: raised (elevado) o sunken (hundido)
- inset: 0 (exterior) o 1 (interior)
- light_top, light_left: intensidad de luz por borde
- dark_bottom, dark_right: intensidad de sombra por borde
- use_hsl: HSL (true) o RGB (false)

Presets incluidos:
- BevelStyle.raised_inset (default, botones)
- BevelStyle.sunken_inset (botones presionados)
- BevelStyle.raised_outer (estilo Windows 95)
- BevelStyle.sunken_outer (estilo Windows 95)

API:
- ctx.drawBevel(x, y, w, h, color, style) - nueva función principal
- ctx.drawBeveledRect() - wrapper compatibilidad (usa raised_inset)
- ctx.drawBeveledRectPressed() - wrapper compatibilidad (usa sunken_inset)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 22:00:16 +01:00
f4b1b75914 perf(telemetry): Añadir métrica executed_cmds
- FrameStats: nuevo campo executed_cmds para comandos realmente ejecutados
- SoftwareRenderer: contador que se incrementa en execute()
- Métodos resetExecutedCount() y getExecutedCount()
- CLAUDE.md: sección OPTIMIZACIONES DE RENDIMIENTO documentada

Permite comparar Total (generados) vs Exec (ejecutados) para
diagnosticar efectividad del dirty regions filtering.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 11:54:56 +01:00
4ce39c4fc8 perf: @setRuntimeSafety(false) + burst detection infrastructure
- fillRect: disable runtime safety for hot path (bounds pre-validated)
- drawGlyphBitmap: disable runtime safety for hot path
- Context: add burst detection (isSelectionBurstActive, markNavigationEvent)
- PanelFrameConfig: add burst_sensitive field
- PanelFrameResult: new struct for frame drawing results

Note: burst_sensitive mechanism available but not actively used
(causes visual flickering when suppressing panel content)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:27:10 +01:00
84bf37cd89 feat(context): Ghost Drawing - suppress_commands flag
Nuevo flag para "Dibujo Fantasma":
- suppress_commands: bool en Context
- pushCommand() y pushOverlayCommand() retornan si está activo
- Permite procesar input (draw) sin generar comandos (ahorra CPU)

Solución de Gemini para immediate-mode + dirty panels

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 11:32:42 +01:00
105ff0063d feat(context): Sistema de registro de paneles dirty
Añade el sistema de dirty panels para optimización de rendering:
- panel_areas: HashMap para registrar rectángulos de paneles
- dirty_panels: HashMap con flags de invalidación por panel
- registerPanelArea(id, rect): Registrar panel con nombre
- invalidatePanel(id): Marcar panel como dirty
- isPanelDirty(id): Consultar si necesita redraw
- markAllPanelsDirty(): Para resize/tab change
- getDirtyPanelRects(): Obtener rects dirty para renderer
- clearDirtyPanels(): Limpiar flags (automático en endFrame)

Diseño:
- La aplicación registra paneles al inicio
- La aplicación notifica cambios via invalidatePanel()
- El renderer usa getDirtyPanelRects() para limpieza selectiva
- Los flags se limpian automáticamente en endFrame()

Parte de la implementación de Dirty Panels Fase 1.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 18:46:31 +01:00
092671adda chore: Eliminar debug print en drawPanelFrame
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 20:51:16 +01:00
89c7508426 fix(bevel): Bisel inset +1px para no solapar borde exterior
- drawBeveledRect: bordes ahora en x+1,y+1 (interior del rect)
- drawBeveledRectPressed: mismo fix para estado presionado
- inner_w/inner_h calculados como w-2/h-2 para correcta insetación
- Fix identificado en verificación MASTER_RESCATE punto C

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 13:48:54 +01:00
0f16a77ae4 fix(panels): Semáforo reubicado - texto + cuadrado a la derecha
- Título: x+28 para dejar espacio al semáforo (antes x+10)
- Semáforo: "Viendo ■" alineado a la derecha (antes ■ izquierda, texto derecha)
- Botones: visual_adjust +2px para compensar baseline TTF
- contrastTextColor como fallback para títulos sin base_color

Layout final: "[N] Título                    Estado ■"

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 13:17:37 +01:00
d657a25ba7 fix(visual): Títulos legibles + botones centrados
Fix legibilidad títulos:
- title_color: 85% soft_white + 15% tinte del base_color
- Antes: base.lightenHsl(90) → azul claro sobre azul oscuro (ilegible)
- Ahora: blanco con tinte sutil → máximo contraste + identidad visual

Fix centrado vertical botones:
- Añadido char_height al Context (default 14px para TTF)
- button.zig: usa char_height en vez de char_width
- Offset visual -1px para compensar efecto 3D del bisel

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 12:15:13 +01:00
f7e1e346be feat(context): Títulos integrados con color adaptativo
Z-Design V5 - Títulos Adaptativos:
- derivePanelFrameColors: title_color según luminosidad del fondo
  - Fondo oscuro (L < 0.5) → base.lightenHsl(90) (blanco teñido)
  - Fondo claro → base.darkenHsl(90) (negro teñido)
- drawPanelFrame: siempre usa title_color (no border_unfocus)
- Márgenes título mejorados: x+10, y+5

Resultado: máximo contraste y legibilidad en todos los paneles.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 01:54:58 +01:00
797cca736c feat(context): Smart Panel V2 - base_color derivación genérica + título
- PanelFrameConfig: añadir base_color, title, title_color
- drawPanelFrame: modo híbrido (explícito vs Z-Design)
- derivePanelFrameColors: fórmula genérica luminosidad (L inversamente proporcional)
- Documentar decisión de omitir clipping (performance + control)

Consensuado: Claude + Gemini + R.Eugenio (2025-12-31)
2025-12-31 00:19:18 +01:00
f71c9e6186 feat(context): Add drawPanelFrame helper for DRY panel rendering
- Add PanelFrameConfig struct with has_focus, focus_bg, unfocus_bg, border_color options
- Add drawPanelFrame() method that encapsulates common panel rendering pattern:
  1. Update ColorTransition and request animation frame if needed
  2. Draw shadow when focused
  3. Draw beveled background
  4. Draw border outline
- Export ColorTransition from context module
- Reduces ~15 lines of repeated code per panel to single function call

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 20:33:28 +01:00
ed2701fbd8 feat(animation): Liquid UI V2 - Mayor fluidez y contraste
- ColorTransition: 200ms → 500ms (transiciones más perceptibles)
- deriveDarkPalette: 4%/20% base color (mayor contraste focus/unfocus)
- deriveLightPalette: 1%/6% base color (proporcional)
- Context: añadir requestAnimationFrame/needsAnimationFrame
- Tests actualizados para nuevos umbrales

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 19:24:36 +01:00
6154cb1080 feat(context): Añadir drawBeveledRect/drawBeveledRectPressed
Helpers para dibujar rectángulos con efecto 3D:
- drawBeveledRect: luz desde arriba-izquierda (normal)
- drawBeveledRectPressed: bisel invertido (presionado)

Usa lightenHsl(10) y darkenHsl(15) para bordes.

Parte del plan 'Acabado Espectacular'.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 15:23:22 +01:00
702c33c13a feat(virtual_table): Tab navigation + cursor fixes + cell editing
- Tab/Shift+Tab with wrap navigation in editing mode
- tab_out/tab_shift result fields for application handling
- Cursor position, blinking, background color fixes
- markRowSaved() to clear dirty state after save
- last_edited_row only set when actual changes made
2025-12-27 01:18:54 +01:00
3f442bf8b9 feat(autocomplete): Sistema overlay para dropdowns + mejoras UX
OVERLAY SYSTEM:
- Context: nuevo campo overlay_commands para capa superior
- Context: nueva función pushOverlayCommand()
- mainloop: renderiza overlay_commands DESPUÉS de commands
- autocomplete: dropdown usa overlay (se dibuja encima de otros widgets)

MEJORAS AUTOCOMPLETE:
- Dropdown se abre inmediatamente al escribir (sin delay de 1 frame)
- Dropdown se abre al borrar con backspace/delete
- Click en flecha del dropdown hace toggle abrir/cerrar
- Área clicable de flecha: 20px

ESTADO: En progreso - funcionalidad básica operativa, pendiente:
- Keyboard handlers completos
- Más testing de casos edge

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 19:07:44 +01:00
f077c87dfc feat(v0.22.2): AutoComplete focus + Text Metrics + cursor 300ms
AutoComplete:
- Integración sistema focus (registerFocusable, requestFocus, hasFocus)
- Fix input: event.char → ctx.input.getTextInput()
- Fix dropdown al iniciar: is_first_frame guard

Text Metrics:
- Nuevo ctx.measureText() y ctx.measureTextToCursor()
- text_measure_fn callback para fuentes TTF
- char_width fallback para bitmap (8px)

Cursor:
- text_input.zig y autocomplete.zig usan métricas reales
- Blink rate: 500ms → 300ms (más responsive)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 20:08:11 +01:00
f3cdb213cf fix: Add table clipping + cursor animation API
Table clipping:
- Add clip region around table content area
- Prevents cell text from drawing outside table bounds
- Header and scrollbar render outside clip region

Cursor animation API:
- Add CURSOR_IDLE_TIMEOUT_MS (5s) and CURSOR_BLINK_PERIOD_MS (500ms) constants
- Add needsCursorAnimation() to check if cursor should blink
- Add getAnimationTimeout() for dynamic event loop timeout
- Update TextInput to use constants from Context

The application can now query ctx.getAnimationTimeout() to determine
if a short timeout is needed for cursor animation, or if it can wait
indefinitely for events.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 23:41:56 +01:00
e98646b442 feat: Hybrid cursor blink - blinks while active, solid when idle
Implement user-friendly cursor behavior:
- Cursor blinks (500ms on/off) while there's user activity
- After 5 seconds of inactivity, cursor becomes solid (always visible)
- Any input (keyboard, mouse move, click, scroll) resets the timer

Changes:
- context.zig: Add last_input_time_ms tracking
- input.zig: Add hasActivity() and hasActivityWithMouse() methods
- input.zig: Track mouse_x_prev/mouse_y_prev for movement detection
- text_input.zig: Implement hybrid blink logic

This saves battery on laptops while maintaining natural cursor feedback.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 23:32:35 +01:00
05e4f2c926 feat: Implement keyboard system improvements (4 phases)
Phase 1: Frame timing in Context
- Added current_time_ms and frame_delta_ms to Context
- Added setFrameTime() method for applications to provide timing

Phase 2: Centralized shortcuts system
- Added StandardShortcut enum with common shortcuts (copy, paste, etc.)
- Added isStandardActive() function for checking shortcuts
- Updated TextInput to use centralized shortcuts

Phase 3: Incremental search in table
- Added search_buffer, search_len, search_last_time to TableState
- Added addSearchChar(), getSearchTerm(), clearSearch() methods
- Typing in focused table searches first column (case-insensitive)
- 1 second timeout resets search buffer

Phase 4: Blinking cursor in TextInput
- Cursor blinks every 500ms when field is focused
- Uses current_time_ms from Context for timing

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 22:58:22 +01:00
7cde6370d8 fix: Sistema de focus rediseñado y funcionando
Cambios principales:
- Nuevo FocusSystem unificado en core/focus.zig
- Separación registration_group / active_group para multi-panel
- Focus implícito para primer widget del grupo activo
- Table inicializa selected_row/col a 0 cuando tiene datos
- Corregido test navKeyPressed (usaba setKeyState en vez de handleKeyEvent)

Bug resuelto: tabla no respondía a teclado sin clic previo
Causa: selected_col quedaba en -1, selectedCell() retornaba null

Documentación: docs/FOCUS_TRANSITION_2025-12-11.md

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 17:55:08 +01:00
9b6210c76e refactor: Unificar sistema de focus - trabajo en progreso
PROBLEMA DETECTADO:
- Existían dos sistemas de focus paralelos que no se comunicaban
- FocusManager (widgets/focus.zig) usaba IDs u32
- FocusGroupManager (core/focus_group.zig) usaba IDs u64
- Esto causaba que Tab no funcionara y clics no cambiaran focus

SOLUCIÓN CONSENSUADA:
- Usar SOLO FocusGroupManager como fuente de verdad
- Integrar en Context con métodos públicos
- Widgets se auto-registran en el grupo activo al dibujarse
- Tab navega DENTRO del grupo activo
- F6 (u otro) cambia entre grupos/paneles

CAMBIOS:
- context.zig: Añadidos createFocusGroup(), setActiveFocusGroup(),
  hasFocus(), requestFocus(), registerFocusable(), handleTabKey()
- text_input.zig: Usa @intFromPtr para ID único, se auto-registra
- table.zig: Ahora se registra como widget focusable
- widgets.zig/zcatgui.zig: Eliminadas referencias antiguas a FocusManager
- CLAUDE.md: Documentado el trabajo en progreso

ESTADO: EN PROGRESO - Compila pero requiere más testing

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 00:26:22 +01:00
8adc93a345 feat: zcatgui v0.6.0 - Phase 1 Optimization Complete
Performance Infrastructure:
- FrameArena: O(1) per-frame allocator with automatic reset
- ObjectPool: Generic object pool for frequently allocated types
- CommandPool: Specialized pool for draw commands
- RingBuffer: Circular buffer for streaming data
- ScopedArena: RAII pattern for temporary allocations

Dirty Rectangle System:
- Context now tracks dirty regions for partial redraws
- Automatic rect merging to reduce overdraw
- invalidateRect(), needsRedraw(), getDirtyRects() API
- Falls back to full redraw when > 32 dirty rects

Benchmark Suite:
- Timer: High-resolution timing
- Benchmark: Stats collection (avg, min, max, stddev, median)
- FrameTimer: FPS and frame time tracking
- AllocationTracker: Memory usage monitoring
- Pre-built benchmarks for arena, pool, and commands

Context Improvements:
- Integrated FrameArena for zero-allocation hot paths
- frameAllocator() for per-frame widget allocations
- FrameStats for performance monitoring
- Context.init() now returns error union (breaking change)

New Widgets (from previous session):
- Slider: Horizontal/vertical with customization
- ScrollArea: Scrollable content region
- Tabs: Tab container with keyboard navigation
- RadioButton: Radio button groups
- Menu: Dropdown menus (foundation)

Theme System Expansion:
- 5 built-in themes: dark, light, high_contrast, nord, dracula
- ThemeManager with runtime switching
- TTF font support via stb_truetype

Documentation:
- DEVELOPMENT_PLAN.md: 9-phase roadmap to DVUI/Gio parity
- Updated WIDGET_COMPARISON.md with detailed analysis
- Lego Panels architecture documented

Stats: 17 widgets, 123 tests, 5 themes

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 12:45:00 +01:00
59c597fc18 feat: zCatGui v0.1.0 - Initial project setup
Immediate Mode GUI library for Zig with software rendering.

Core features:
- SDL2 backend for cross-platform window/events
- Software rasterizer (works everywhere, including SSH)
- Macro recording system (cornerstone feature, like Vim)
- Command-list rendering (DrawRect, DrawText, etc.)
- Layout system with constraints
- Color/Style system with themes

Project structure:
- src/core/: context, command, input, layout, style
- src/macro/: MacroRecorder, MacroPlayer, MacroStorage
- src/render/: Framebuffer, SoftwareRenderer, Font
- src/backend/: Backend interface, SDL2 implementation
- examples/: hello.zig, macro_demo.zig
- docs/: Architecture, research (Gio, immediate-mode libs, Simifactu)

Build: zig build (requires SDL2-devel)
Tests: 16 tests passing

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 01:30:05 +01:00