zcatgui/docs/research/GIO_UI_ANALYSIS.md
reugenio 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

12 KiB

Análisis Técnico: Gio UI (Go)

Investigación realizada: 2025-12-09 Propósito: Entender arquitectura de Gio como referencia para zCatGui


Resumen Ejecutivo

Gio UI (gioui.org) es una librería de GUI immediate mode para Go que permite crear interfaces gráficas cross-platform nativas. Es comparable a Flutter en diseño pero implementado completamente en Go, sin dependencias externas más allá de las librerías de sistema para ventanas y GPU.

Campo Valor
Repositorio https://git.sr.ht/~eliasnaur/gio
Versión v0.9.0 (pre-1.0, API inestable)
Licencia MIT / Unlicense
Plataformas Android, iOS, macOS, Linux, Windows, FreeBSD, OpenBSD, WebAssembly

1. Arquitectura General

1.1 Estructura de Capas

┌─────────────────────────────────────────┐
│   Material Design (widget/material)     │  <- Widgets estilizados
├─────────────────────────────────────────┤
│   Widget State (widget)                 │  <- Estado de controles
├─────────────────────────────────────────┤
│   Layout System (layout)                │  <- Sistema de layouts
├─────────────────────────────────────────┤
│   Operations (op, op/clip, op/paint)    │  <- Comandos de dibujo
├─────────────────────────────────────────┤
│   Window Management (app)               │  <- Manejo de ventanas
├─────────────────────────────────────────┤
│   GPU Rendering (gpu)                   │  <- Backends gráficos
├─────────────────────────────────────────┤
│   Platform Backend                      │  <- Win/macOS/Linux/etc.
└─────────────────────────────────────────┘

1.2 Módulos Principales

Paquete Propósito
gioui.org/app Window management, eventos del OS
gioui.org/op Sistema de operaciones (comandos de dibujo)
gioui.org/layout Layouts (Flex, Stack, List, Inset)
gioui.org/widget Widgets con estado (Clickable, Editor, List, etc.)
gioui.org/widget/material Material Design theme
gioui.org/gpu Rendering GPU (OpenGL, Direct3D, Vulkan)
gioui.org/io Input/output (pointer, keyboard, clipboard)
gioui.org/text Text shaping, layout, glyphs
gioui.org/font Font handling, OpenType
gioui.org/gesture Gestures de alto nivel (Click, Drag, Scroll, Hover)
gioui.org/x/component Componentes extendidos Material

2. Sistema de Rendering

2.1 GPU Backends

Gio soporta múltiples backends GPU según la plataforma:

  • OpenGL ES - Multiplataforma (Linux, Android, iOS, WebAssembly)
  • Direct3D 11 - Windows
  • Vulkan - Linux, Android (opcional)

2.2 Vector Rendering Pipeline

Gio usa un vector renderer basado en Pathfinder (proyecto de Mozilla):

  1. Renderizado de outlines: Las formas y texto se renderizan desde sus contornos vectoriales
  2. Sin pre-procesamiento CPU: Los paths SVG se renderizan en GPU con mínimo trabajo en CPU
  3. Migración a piet-gpu: Renderer basado en compute shaders para mayor eficiencia

2.3 CPU Fallback

Importante para zCatGui: Gio incluye un fallback CPU (gioui.org/cpu) con binarios pre-compilados de piet-gpu para arm, arm64, amd64, permitiendo renderizado software cuando no hay GPU disponible.


3. Sistema de Layout

3.1 Conceptos Fundamentales

// Constraints = lo que el padre dice al hijo (límites de tamaño)
type Constraints struct {
    Min, Max image.Point
}

// Dimensions = lo que el hijo devuelve al padre (tamaño usado)
type Dimensions struct {
    Size     image.Point
    Baseline int
}

// Context = bundle de estado pasado a todos los widgets
type Context struct {
    Constraints Constraints
    Metric      unit.Metric
    Now         time.Time
    // ...
}

// Widget = función que calcula dimensions desde constraints
type Widget func(gtx layout.Context) layout.Dimensions

3.2 Layouts Principales

Flex - Distribución lineal con pesos

layout.Flex{Axis: layout.Vertical}.Layout(gtx,
    layout.Rigid(func(gtx C) D { return header.Layout(gtx) }),
    layout.Flexed(1, func(gtx C) D { return content.Layout(gtx) }),
    layout.Rigid(func(gtx C) D { return footer.Layout(gtx) }),
)

Spacing modes:

  • SpaceEnd - Espacio al final
  • SpaceStart - Espacio al inicio
  • SpaceSides - Espacio en ambos lados
  • SpaceAround - Espacio alrededor de children
  • SpaceBetween - Espacio entre children
  • SpaceEvenly - Distribución uniforme

Stack - Elementos apilados

layout.Stack{}.Layout(gtx,
    layout.Expanded(func(gtx C) D { return image.Layout(gtx) }),
    layout.Stacked(func(gtx C) D { return button.Layout(gtx) }),
)

List - Lista scrollable virtualizada

// Solo renderiza los elementos visibles
list.Layout(gtx, 1_000_000, func(gtx C, i int) D {
    return material.Label(theme, unit.Sp(16), fmt.Sprintf("Item %d", i)).Layout(gtx)
})

Inset - Padding

layout.UniformInset(10).Layout(gtx, func(gtx C) D {
    return widget.Layout(gtx)
})

3.3 Sistema de Unidades

type Px    // Physical pixels (dependiente de dispositivo)
type Dp    // Device-independent pixels (escala por densidad)
type Sp    // Scaled points (incluye scaling de fuente del sistema)

4. Sistema de Eventos

4.1 Tipos de Eventos

type pointer.Event    // Mouse/touch (Press, Release, Move, Drag, Scroll)
type key.Event        // Keyboard
type key.EditEvent    // Edición de texto
type key.FocusEvent   // Cambio de foco

4.2 Distribución de Eventos (Tag-based)

Gio usa un sistema sin callbacks basado en tags:

// Declarar área clickable
pointer.InputOp{
    Tag:   &button,  // Tag único
    Types: pointer.Press | pointer.Release,
}.Add(ops)

// Consultar eventos
for {
    ev, ok := gtx.Event(pointer.Filter{Target: &button, ...})
    if !ok { break }
    // Procesar evento
}

Ventaja: Elimina el overhead de callbacks y simplifica el manejo de estado.

4.3 Gestures de Alto Nivel

type Click     // Detecta clicks
type Drag      // Detecta drags
type Hover     // Detecta hover
type Scroll    // Detecta scroll

5. Widgets Incluidos

5.1 Widget Pattern (Separación de Concerns)

Gio separa estado (stateful) y presentación (stateless):

widget.Clickable  (state)  →  material.Button      (presentation)
widget.Editor     (state)  →  material.Editor      (presentation)
widget.Bool       (state)  →  material.CheckBox    (presentation)

5.2 Widget State (gioui.org/widget)

Widget Propósito
Clickable Área clickable (botones, cards, etc.)
Editor Editor de texto de una línea
Selectable Texto seleccionable (no editable)
Float Valor float para sliders
Bool Valor booleano (checkboxes, switches)
Enum Valor enum (radio buttons)
List Estado de lista scrollable
Scrollbar Estado de scrollbar
Draggable Soporte drag & drop
Decorations Decoraciones de ventana
Icon Ícono vectorial

5.3 Material Widgets (gioui.org/widget/material)

Texto: Label, H1-H6, Body1, Body2, Caption, Subtitle1, Subtitle2, Overline Botones: Button, IconButton, ButtonLayout Input: Editor, CheckBox, RadioButton, Switch, Slider Contenedores: List, Scrollbar Indicadores: ProgressBar, ProgressCircle, Loader (spinner) Ventanas: Decorations

5.4 Extended Components (gioui.org/x/component)

  • AppBar, NavDrawer, Menu, MenuItem, ContextArea
  • Grid, Table, Sheet, Surface
  • TextField (con label animada), Tooltip
  • Discloser (expandible), Divider
  • ModalLayer, Scrim

6. Theming y Styling

6.1 Sistema de Theme

type Theme struct {
    Shaper   *text.Shaper
    Palette  Palette
    TextSize unit.Sp
    Face     text.Face
    FingerSize unit.Dp  // Tamaño mínimo área touch (48dp)
}

type Palette struct {
    Bg          color.NRGBA
    Fg          color.NRGBA
    ContrastBg  color.NRGBA
    ContrastFg  color.NRGBA
}

6.2 Niveles de Customización

Global (Theme-wide):

theme := material.NewTheme()
theme.Palette.Fg = color.NRGBA{R: 255, G: 255, B: 255, A: 255}

Widget-local:

btn := material.Button(theme, button, "Click me!")
btn.Background = color.NRGBA{R: 0, G: 150, B: 0, A: 255}

7. Window Management

7.1 Creación de Ventana

func main() {
    go func() {
        window := new(app.Window)
        window.Option(app.Title("My App"))
        window.Option(app.Size(unit.Dp(800), unit.Dp(600)))
        if err := run(window); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }()
    app.Main()  // BLOQUEANTE en algunas plataformas
}

7.2 Event Loop

func run(window *app.Window) error {
    var ops op.Ops
    for {
        switch e := window.Event().(type) {
        case app.DestroyEvent:
            return e.Err
        case app.FrameEvent:
            ops.Reset()
            gtx := app.NewContext(&ops, e)
            drawUI(gtx)
            e.Frame(gtx.Ops)
        }
    }
}

8. Paradigma Immediate Mode

8.1 Filosofía

while running:
    eventos ← poll_events()
    actualizar_estado(eventos)

    ops.Reset()
    dibujar_ui_completa(ops, estado)  ← UI es función pura del estado
    enviar_a_gpu(ops)

8.2 Ventajas Específicas de Gio

Sin callbacks:

// NO HAY ESTO:
button.onClick(func() { ... })

// EN SU LUGAR:
for button.Clicked(gtx) {
    count++
}

Estado mínimo:

// El estado es tuyo, no del framework
type State struct {
    count int
    name  string
}

// Widgets solo contienen estado UI mínimo
var button widget.Clickable

UI como función pura:

func drawUI(gtx layout.Context, state *State) {
    label := material.H1(theme, fmt.Sprintf("Count: %d", state.count))
    label.Layout(gtx)
}

8.3 Zero-Allocation Design

// Método tipado, sin interfaz → sin allocación
operation.Add(ops)

9. Lecciones para zCatGui

9.1 Qué Adoptar

  1. Separación estado/presentación: Widget state vs widget render
  2. Sistema de constraints: Constraints/Dimensions muy robusto
  3. Event tags: Sin callbacks, consulta de eventos
  4. Zero-allocation: Operaciones tipadas
  5. Spacing modes: Flex con SpaceBetween, SpaceAround, etc.

9.2 Qué Adaptar

  1. Rendering: Gio usa GPU, nosotros software renderer
  2. Operaciones: Gio usa op.Ops (GPU), nosotros DrawCommand (CPU)
  3. Complejidad: Gio es ~40K LOC, nosotros apuntamos a ~5-10K

9.3 Diferencias Clave

Aspecto Gio zCatGui
Lenguaje Go Zig
Rendering GPU (Pathfinder) Software (framebuffer)
Complejidad Alta (~40K LOC) Baja (target ~5K)
Macros No tiene Piedra angular
Fonts HarfBuzz Bitmap + stb_truetype

10. Referencias