# Plan de Paridad con Gio UI > **Objetivo**: Implementar todas las features y widgets de Gio que faltan en zcatgui > **Fecha**: 2025-12-09 > **Estado actual**: ✅ COMPLETADO - 47 widgets, 338+ tests --- ## RESUMEN EJECUTIVO ### Lo que YA tenemos (35 widgets): ``` Label, Button, Checkbox, RadioButton, TextInput, TextArea, NumberEntry, Slider, AutoComplete, Select, List, Tree, Table, Chart (Line/Bar/Pie), Sparkline, Panel, HSplit, VSplit, Tabs, ScrollArea, Modal, Progress, Tooltip, Toast, Badge, Menu, ContextMenu, Image, Icon, ColorPicker, DatePicker, RichText, Breadcrumb, Canvas, Reorderable, VirtualScroll ``` ### Lo que FALTA para paridad con Gio: #### Widgets Nuevos (14): 1. Switch (toggle switch) 2. IconButton 3. Loader (spinner animado diferente) 4. AppBar 5. NavDrawer 6. ModalNavDrawer 7. Sheet (side panel) 8. ModalSheet 9. Grid (layout grid) 10. Divider 11. Surface (elevated container) 12. Resize (drag handle) 13. Discloser (expandable) 14. Selectable (texto seleccionable) #### Features de Sistema (6): 1. Sistema de Animación con timing 2. Gestos avanzados (multi-click, fling/momentum, swipe) 3. Sistema de Layout mejorado (Flex, Stack, Direction) 4. Texto seleccionable/copiable 5. Drag & Drop mejorado con MIME types 6. Sombras y elevación --- ## PLAN POR FASES ### FASE 1: Widgets Básicos Faltantes **Widgets**: Switch, IconButton, Divider, Loader **Estimación**: ~400 LOC | Widget | Descripción | Dependencias | |--------|-------------|--------------| | Switch | Toggle on/off con animación | Ninguna | | IconButton | Botón circular con icono | icon.zig | | Divider | Línea horizontal/vertical | Ninguna | | Loader | Spinner animado avanzado | progress.zig base | ### FASE 2: Layout y Contenedores **Widgets**: Surface, Grid, Resize **Features**: Sistema de sombras, elevación **Estimación**: ~600 LOC | Widget | Descripción | Dependencias | |--------|-------------|--------------| | Surface | Contenedor con sombra/elevación | effects.zig | | Grid | Layout grid con scroll | scroll.zig | | Resize | Handle de redimensionado | dragdrop.zig | ### FASE 3: Navegación **Widgets**: AppBar, NavDrawer, ModalNavDrawer, Sheet, ModalSheet **Estimación**: ~800 LOC | Widget | Descripción | Dependencias | |--------|-------------|--------------| | AppBar | Barra superior/inferior | button.zig, icon.zig | | NavDrawer | Panel lateral de navegación | panel.zig | | ModalNavDrawer | NavDrawer modal con scrim | modal.zig, NavDrawer | | Sheet | Panel lateral deslizante | panel.zig | | ModalSheet | Sheet modal | modal.zig, Sheet | ### FASE 4: Interacción Avanzada **Widgets**: Discloser, Selectable **Features**: Texto seleccionable, gestos **Estimación**: ~500 LOC | Widget | Descripción | Dependencias | |--------|-------------|--------------| | Discloser | Contenido expandible con flecha | tree.zig pattern | | Selectable | Texto con selección y copia | clipboard.zig | ### FASE 5: Sistema de Animación **Features**: Framework de animación, transiciones, easing **Estimación**: ~400 LOC | Feature | Descripción | |---------|-------------| | AnimationController | Control de animaciones con timing | | Transitions | Fade, slide, scale transitions | | Spring animations | Animaciones con física de resorte | ### FASE 6: Gestos Avanzados **Features**: Multi-click, fling, swipe, long-press **Estimación**: ~300 LOC | Feature | Descripción | |---------|-------------| | GestureRecognizer | Reconocedor de gestos | | FlingDetector | Momentum scroll | | MultiClickDetector | Doble/triple click | | LongPressDetector | Pulsación larga | --- ## DETALLE DE IMPLEMENTACIÓN ### FASE 1: Widgets Básicos Faltantes #### 1.1 Switch (`src/widgets/switch.zig`) ```zig pub const SwitchState = struct { is_on: bool = false, animation_progress: f32 = 0, // 0=off, 1=on }; pub const SwitchConfig = struct { label: ?[]const u8 = null, disabled: bool = false, // Tamaños track_width: u16 = 44, track_height: u16 = 24, thumb_size: u16 = 20, }; pub fn switch_(ctx: *Context, state: *SwitchState, config: SwitchConfig) SwitchResult ``` #### 1.2 IconButton (`src/widgets/iconbutton.zig`) ```zig pub const IconButtonConfig = struct { icon: icon.IconType, size: enum { small, medium, large } = .medium, tooltip: ?[]const u8 = null, disabled: bool = false, // Circular por defecto style: enum { filled, outlined, ghost } = .ghost, }; pub fn iconButton(ctx: *Context, config: IconButtonConfig) IconButtonResult ``` #### 1.3 Divider (`src/widgets/divider.zig`) ```zig pub const DividerConfig = struct { orientation: enum { horizontal, vertical } = .horizontal, thickness: u16 = 1, margin: u16 = 8, label: ?[]const u8 = null, // Para dividers con texto }; pub fn divider(ctx: *Context, rect: Rect, config: DividerConfig) void ``` #### 1.4 Loader (`src/widgets/loader.zig`) ```zig // Extiende progress.zig con más estilos de spinner pub const LoaderStyle = enum { circular, // Spinner circular (default) dots, // Puntos animados bars, // Barras verticales pulse, // Círculo pulsante bounce, // Puntos rebotando }; pub const LoaderConfig = struct { style: LoaderStyle = .circular, size: enum { small, medium, large } = .medium, label: ?[]const u8 = null, }; ``` ### FASE 2: Layout y Contenedores #### 2.1 Surface (`src/widgets/surface.zig`) ```zig pub const Elevation = enum(u8) { none = 0, low = 1, // 2px shadow medium = 2, // 4px shadow high = 3, // 8px shadow highest = 4, // 16px shadow }; pub const SurfaceConfig = struct { elevation: Elevation = .low, corner_radius: u16 = 8, background: ?Color = null, border: ?struct { color: Color, width: u16 } = null, }; pub fn surface(ctx: *Context, rect: Rect, config: SurfaceConfig) Rect // Retorna rect interior para contenido ``` #### 2.2 Grid (`src/widgets/grid.zig`) ```zig pub const GridConfig = struct { columns: u16 = 3, row_height: ?u16 = null, // null = auto gap: u16 = 8, padding: u16 = 8, }; pub const GridState = struct { scroll_offset: i32 = 0, selected_cell: ?struct { row: usize, col: usize } = null, }; pub fn grid(ctx: *Context, rect: Rect, state: *GridState, config: GridConfig, items: []const GridItem) GridResult ``` #### 2.3 Resize (`src/widgets/resize.zig`) ```zig pub const ResizeConfig = struct { direction: enum { horizontal, vertical, both } = .horizontal, min_size: u16 = 50, max_size: ?u16 = null, handle_size: u16 = 8, }; pub const ResizeState = struct { size: u16, dragging: bool = false, }; pub fn resize(ctx: *Context, state: *ResizeState, config: ResizeConfig) ResizeResult ``` ### FASE 3: Navegación #### 3.1 AppBar (`src/widgets/appbar.zig`) ```zig pub const AppBarConfig = struct { title: []const u8, position: enum { top, bottom } = .top, height: u16 = 56, // Acciones leading_icon: ?icon.IconType = null, // e.g., menu, back actions: []const AppBarAction = &.{}, // Estilo elevation: Elevation = .low, }; pub const AppBarAction = struct { icon: icon.IconType, tooltip: ?[]const u8 = null, id: u32, }; pub fn appBar(ctx: *Context, config: AppBarConfig) AppBarResult ``` #### 3.2 NavDrawer (`src/widgets/navdrawer.zig`) ```zig pub const NavDrawerConfig = struct { width: u16 = 280, items: []const NavItem, header: ?NavDrawerHeader = null, }; pub const NavItem = struct { icon: ?icon.IconType = null, label: []const u8, id: u32, badge: ?[]const u8 = null, children: []const NavItem = &.{}, // Sub-items }; pub const NavDrawerState = struct { selected_id: ?u32 = null, expanded_ids: [16]u32 = undefined, expanded_count: usize = 0, }; pub fn navDrawer(ctx: *Context, rect: Rect, state: *NavDrawerState, config: NavDrawerConfig) NavDrawerResult ``` #### 3.3 ModalNavDrawer (`src/widgets/navdrawer.zig`) ```zig pub const ModalNavDrawerState = struct { is_open: bool = false, animation_progress: f32 = 0, nav_state: NavDrawerState = .{}, }; pub fn modalNavDrawer(ctx: *Context, state: *ModalNavDrawerState, config: NavDrawerConfig) ModalNavDrawerResult ``` #### 3.4 Sheet (`src/widgets/sheet.zig`) ```zig pub const SheetConfig = struct { side: enum { left, right, bottom } = .right, width: u16 = 320, // Para left/right height: u16 = 400, // Para bottom }; pub const SheetState = struct { is_open: bool = false, animation_progress: f32 = 0, }; pub fn sheet(ctx: *Context, state: *SheetState, config: SheetConfig) SheetResult pub fn modalSheet(ctx: *Context, state: *SheetState, config: SheetConfig) ModalSheetResult ``` ### FASE 4: Interacción Avanzada #### 4.1 Discloser (`src/widgets/discloser.zig`) ```zig pub const DiscloserConfig = struct { label: []const u8, icon: enum { arrow, plus_minus, chevron } = .arrow, initially_expanded: bool = false, }; pub const DiscloserState = struct { is_expanded: bool = false, animation_progress: f32 = 0, }; pub fn discloser(ctx: *Context, state: *DiscloserState, config: DiscloserConfig) DiscloserResult // DiscloserResult.content_rect = área para contenido expandido ``` #### 4.2 Selectable (`src/widgets/selectable.zig`) ```zig pub const SelectableConfig = struct { text: []const u8, allow_copy: bool = true, // Estilo de selección selection_color: ?Color = null, }; pub const SelectableState = struct { selection_start: ?usize = null, selection_end: ?usize = null, is_selecting: bool = false, }; pub fn selectable(ctx: *Context, rect: Rect, state: *SelectableState, config: SelectableConfig) SelectableResult ``` ### FASE 5: Sistema de Animación #### 5.1 AnimationController (`src/core/animation_controller.zig`) ```zig pub const AnimationController = struct { const MAX_ANIMATIONS = 64; animations: [MAX_ANIMATIONS]ManagedAnimation, count: usize = 0, pub fn create(self: *AnimationController, target: *f32, to: f32, duration_ms: u32, easing: Easing) AnimationId pub fn cancel(self: *AnimationController, id: AnimationId) void pub fn update(self: *AnimationController, delta_ms: u32) void pub fn isRunning(self: AnimationController, id: AnimationId) bool }; pub const ManagedAnimation = struct { id: AnimationId, target: *f32, from: f32, to: f32, duration_ms: u32, elapsed_ms: u32 = 0, easing: Easing, on_complete: ?*const fn() void = null, }; pub const Easing = enum { linear, ease_in, ease_out, ease_in_out, ease_in_quad, ease_out_quad, ease_in_out_quad, ease_in_cubic, ease_out_cubic, ease_in_out_cubic, ease_in_elastic, ease_out_elastic, ease_in_bounce, ease_out_bounce, spring, }; ``` ### FASE 6: Gestos Avanzados #### 6.1 GestureRecognizer (`src/core/gestures.zig`) ```zig pub const GestureRecognizer = struct { // Estado click_count: u8 = 0, last_click_time: i64 = 0, last_click_pos: struct { x: i32, y: i32 } = .{ .x = 0, .y = 0 }, // Fling velocity_x: f32 = 0, velocity_y: f32 = 0, is_flinging: bool = false, // Long press press_start_time: i64 = 0, long_press_triggered: bool = false, pub fn update(self: *GestureRecognizer, input: *InputState, delta_ms: u32) GestureEvents }; pub const GestureEvents = struct { single_click: bool = false, double_click: bool = false, triple_click: bool = false, long_press: bool = false, fling: ?struct { vx: f32, vy: f32 } = null, swipe: ?enum { left, right, up, down } = null, }; ``` --- ## CHECKLIST DE IMPLEMENTACIÓN ### Fase 1: Widgets Básicos ✅ COMPLETADO - [x] Switch (`src/widgets/switch.zig`) - [x] IconButton (`src/widgets/iconbutton.zig`) - [x] Divider (`src/widgets/divider.zig`) - [x] Loader (`src/widgets/loader.zig`) ### Fase 2: Layout y Contenedores ✅ COMPLETADO - [x] Surface (`src/widgets/surface.zig`) - [x] Grid (`src/widgets/grid.zig`) - [x] Resize (`src/widgets/resize.zig`) ### Fase 3: Navegación ✅ COMPLETADO - [x] AppBar (`src/widgets/appbar.zig`) - [x] NavDrawer (`src/widgets/navdrawer.zig`) - [x] ModalNavDrawer (incluido en navdrawer.zig) - [x] Sheet (`src/widgets/sheet.zig`) - [x] ModalSheet (incluido en sheet.zig como modal: true) ### Fase 4: Interacción Avanzada ✅ COMPLETADO - [x] Discloser (`src/widgets/discloser.zig`) - [x] Selectable (`src/widgets/selectable.zig`) ### Fase 5: Sistema de Animación ✅ COMPLETADO - [x] Spring physics (`src/render/animation.zig`) - [x] AnimationController ya existente, mejorado ### Fase 6: Gestos Avanzados ✅ COMPLETADO - [x] GestureRecognizer (`src/core/gesture.zig`) - [x] Tap, double-tap, long-press, drag, swipe detection - [x] Velocity tracking y fling detection --- ## ESTIMACIÓN TOTAL | Fase | LOC | Widgets/Features | |------|-----|------------------| | 1 | ~400 | 4 widgets | | 2 | ~600 | 3 widgets + sombras | | 3 | ~800 | 5 widgets | | 4 | ~500 | 2 widgets | | 5 | ~400 | 1 sistema | | 6 | ~300 | 1 sistema | | **Total** | **~3,000** | **14 widgets + 2 sistemas** | --- ## POST-PARIDAD ✅ ALCANZADO zcatgui ahora tiene: - **47 archivos de widgets** - **338+ tests pasando** - **Paridad 100%** con Gio en widgets - **Ventajas únicas sobre Gio**: - Sistema de Macros para grabación/reproducción - Charts completos (Line, Bar, Pie) - Table con edición in-situ - ColorPicker y DatePicker - VirtualScroll para listas grandes - Breadcrumb navigation ### Widgets añadidos en esta sesión: 1. Switch (toggle animado) 2. IconButton (circular con estilos) 3. Divider (horizontal/vertical/con label) 4. Loader (7 estilos de spinner) 5. Surface (contenedor con elevación) 6. Grid (layout con scroll) 7. Resize (handle de redimensionado) 8. AppBar (barra superior/inferior) 9. NavDrawer (panel de navegación) 10. Sheet (panel lateral deslizante) 11. Discloser (contenido expandible) 12. Selectable (región clicable/seleccionable) ### Sistemas añadidos: - Spring physics para animaciones fluidas - GestureRecognizer completo (tap, double-tap, long-press, drag, swipe)