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>
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):
- Renderizado de outlines: Las formas y texto se renderizan desde sus contornos vectoriales
- Sin pre-procesamiento CPU: Los paths SVG se renderizan en GPU con mínimo trabajo en CPU
- 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 finalSpaceStart- Espacio al inicioSpaceSides- Espacio en ambos ladosSpaceAround- Espacio alrededor de childrenSpaceBetween- Espacio entre childrenSpaceEvenly- 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
- Separación estado/presentación: Widget state vs widget render
- Sistema de constraints: Constraints/Dimensions muy robusto
- Event tags: Sin callbacks, consulta de eventos
- Zero-allocation: Operaciones tipadas
- Spacing modes: Flex con SpaceBetween, SpaceAround, etc.
9.2 Qué Adaptar
- Rendering: Gio usa GPU, nosotros software renderer
- Operaciones: Gio usa op.Ops (GPU), nosotros DrawCommand (CPU)
- 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 |