zcatgui/REFERENCE.md
reugenio 0625e18e77 docs: Actualizar REFERENCE.md con API TTF completa
- Reemplazar nota de placeholder con documentación real
- Añadir ejemplos de código para cargar y usar TTF
- Documentar FontRef para API unificada bitmap/TTF
- Listar fuentes recomendadas con rutas en Fedora
- Documentar features: AA, cache, alpha blending

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 00:58:29 +01:00

37 KiB

zcatgui Reference Manual

Version: 0.15.0 Language: Zig 0.15.2 Paradigm: Immediate Mode GUI Lines of Code: ~35,000 across 81 source files


Table of Contents

  1. Overview
  2. Installation & Setup
  3. Quick Start
  4. Architecture
  5. Core Modules
  6. Widgets (37 total)
  7. Rendering System
  8. Animation & Effects
  9. Backend System
  10. Macro System
  11. Panel System
  12. Performance Utilities
  13. Theme System
  14. Accessibility
  15. Gesture Recognition
  16. API Reference

Overview

zcatgui is an immediate-mode GUI library for Zig featuring:

  • Software Rendering: Works on any computer without GPU (SSH compatible)
  • Cross-Platform: Linux, Windows, macOS, Web (WASM), Android, iOS
  • Macro System: Record and replay user actions (cornerstone feature)
  • 37 Widgets: From basic labels to complex tables and charts
  • Zero External Dependencies: Only SDL2 for desktop windowing

Design Philosophy

"Maximum compatibility, minimum dependencies, total user control"
  • Immediate mode = explicit state, no callbacks, no threading hell
  • Software rendering first, GPU optional later
  • Macro system integrated from the design phase
  • Works on old laptops, new workstations, and via SSH

Installation & Setup

Requirements

  • Zig 0.15.2
  • SDL2 (for desktop builds only)

Build Commands

# Build library and examples
zig build

# Run tests
zig build test

# Run examples
zig build hello           # Hello world
zig build widgets-demo    # Widget showcase
zig build table-demo      # Table with split panels
zig build macro-demo      # Macro recording demo

# Platform-specific builds
zig build wasm            # Web (WASM) - outputs to web/
zig build android         # Android ARM64
zig build android-x86     # Android x86_64 (emulator)
zig build ios             # iOS ARM64 (device)
zig build ios-sim         # iOS ARM64 (simulator)

Project Integration

Add to your build.zig.zon:

.dependencies = .{
    .zcatgui = .{
        .path = "../path/to/zcatgui",
    },
},

Quick Start

const zcatgui = @import("zcatgui");
const Context = zcatgui.Context;

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    // Initialize context
    var ctx = try Context.init(allocator);
    defer ctx.deinit();

    // Main loop
    while (ctx.running) {
        ctx.beginFrame();

        // Draw a button
        if (zcatgui.button(&ctx, "Click me!")) {
            // Handle click
        }

        // Draw a label
        zcatgui.label(&ctx, "Hello, zcatgui!");

        ctx.endFrame();
    }
}

Architecture

Layer Diagram

┌─────────────────────────────────────────────────────────────┐
│  Layer 4: Widgets (37 widgets)                              │
│  Button, Table, Tree, Chart, Modal, etc.                    │
├─────────────────────────────────────────────────────────────┤
│  Layer 3: Macro System + Panels                             │
│  MacroRecorder, MacroPlayer, AutonomousPanel, Composites    │
├─────────────────────────────────────────────────────────────┤
│  Layer 2: Core UI                                           │
│  Context, Layout, Style, Input, Command, DragDrop, Gesture  │
├─────────────────────────────────────────────────────────────┤
│  Layer 1: Rendering                                         │
│  SoftwareRenderer, Framebuffer, Font, TTF, Animation        │
├─────────────────────────────────────────────────────────────┤
│  Layer 0: Backends                                          │
│  SDL2, WASM, Android, iOS                                   │
└─────────────────────────────────────────────────────────────┘

File Structure

zcatgui/
├── src/
│   ├── zcatgui.zig              # Main entry point, re-exports
│   ├── core/                    # Core modules
│   │   ├── context.zig          # UI context, frame management
│   │   ├── layout.zig           # Rect, Constraint, Layout
│   │   ├── style.zig            # Color, Theme, ThemeManager
│   │   ├── input.zig            # Key, Mouse, InputState
│   │   ├── command.zig          # DrawCommand list
│   │   ├── clipboard.zig        # Clipboard operations
│   │   ├── dragdrop.zig         # Drag and drop system
│   │   ├── shortcuts.zig        # Keyboard shortcuts
│   │   ├── focus_group.zig      # Focus navigation
│   │   ├── accessibility.zig    # A11y roles and states
│   │   └── gesture.zig          # Touch gesture recognition
│   ├── widgets/                 # 37 widgets
│   │   └── widgets.zig          # Re-exports all widgets
│   ├── render/                  # Rendering
│   │   ├── framebuffer.zig      # Pixel buffer
│   │   ├── software.zig         # Software rasterizer
│   │   ├── font.zig             # Bitmap fonts
│   │   ├── ttf.zig              # TrueType fonts
│   │   ├── animation.zig        # Easing, Animation, Spring
│   │   ├── effects.zig          # Shadow, Gradient, Blur
│   │   └── antialiasing.zig     # AA drawing functions
│   ├── backend/                 # Platform backends
│   │   ├── backend.zig          # Abstract interface
│   │   ├── sdl2.zig             # SDL2 (desktop)
│   │   ├── wasm.zig             # WebAssembly
│   │   ├── android.zig          # Android NDK
│   │   └── ios.zig              # iOS UIKit
│   ├── macro/                   # Macro system
│   │   └── macro.zig            # Recorder, Player, Storage
│   ├── panels/                  # Panel architecture
│   │   ├── panels.zig           # Re-exports
│   │   ├── panel.zig            # AutonomousPanel
│   │   ├── composite.zig        # Composite patterns
│   │   └── data_manager.zig     # Observer pattern
│   └── utils/                   # Utilities
│       ├── utils.zig            # Re-exports
│       ├── arena.zig            # FrameArena, ScopedArena
│       ├── pool.zig             # ObjectPool, CommandPool
│       ├── benchmark.zig        # Timer, Benchmark
│       └── testing.zig          # TestRunner, Assertions
├── examples/                    # Example applications
├── web/                         # WASM build output
├── ios/                         # iOS bridge files
└── docs/                        # Documentation

Core Modules

Context (src/core/context.zig)

The UI context manages frame lifecycle, command queue, and dirty regions.

const Context = zcatgui.Context;

// Create context
var ctx = try Context.init(allocator);
defer ctx.deinit();

// Frame lifecycle
ctx.beginFrame();
// ... draw widgets ...
ctx.endFrame();

// Access components
ctx.layout        // LayoutState
ctx.input         // InputState
ctx.commands      // Command list
ctx.frame_arena   // Per-frame allocator

// Dirty rectangle tracking
ctx.invalidateRect(rect);
ctx.needsRedraw();
ctx.getDirtyRects();

Key Types:

  • Context - Main UI context
  • FrameStats - Performance statistics

Layout (src/core/layout.zig)

Rectangle and constraint-based layout system.

const Layout = zcatgui.Layout;
const Rect = zcatgui.Rect;
const Constraint = zcatgui.Constraint;

// Create rectangles
const rect = Rect.init(x, y, width, height);

// Rectangle operations
rect.contains(point_x, point_y)
rect.intersection(other_rect)
rect.union_rect(other_rect)
rect.isEmpty()
rect.left(), rect.right(), rect.top(), rect.bottom()
rect.center()
rect.inset(amount)
rect.expand(amount)

// Constraints
const constraint = Constraint{
    .min_width = 100,
    .max_width = 500,
    .min_height = 50,
    .max_height = 200,
};

Style (src/core/style.zig)

Colors and theming system.

const Style = zcatgui.Style;
const Color = zcatgui.Color;
const Theme = zcatgui.Theme;

// Color creation
const red = Color.rgb(255, 0, 0);
const semi_transparent = Color.rgba(255, 0, 0, 128);

// Predefined colors
Color.white, Color.black, Color.red, Color.green, Color.blue
Color.primary, Color.secondary, Color.success, Color.warning, Color.danger

// Color operations
color.toABGR()           // For framebuffer
color.blend(background)   // Alpha blending
color.withAlpha(128)     // New alpha value

// Theme system
const theme = zcatgui.currentTheme();
theme.colors.primary
theme.colors.background
theme.colors.text

Built-in Themes: dark, light, high_contrast, nord, dracula


Input (src/core/input.zig)

Keyboard and mouse input handling.

const Input = zcatgui.Input;
const InputState = Input.InputState;

// In your frame loop
const input = &ctx.input;

// Keyboard
input.keyPressed(.enter)     // Just pressed this frame
input.keyReleased(.escape)   // Just released
input.keyDown(.left_shift)   // Currently held
input.getChar()              // Text input character

// Mouse
input.mousePressed(.left)
input.mouseReleased(.right)
input.mouseDown(.middle)
const pos = input.mousePos(); // {x, y}
input.mouseDelta()           // Movement since last frame
input.scrollDelta()          // Scroll wheel

// Modifiers
input.keyDown(.left_ctrl) or input.keyDown(.right_ctrl)
input.keyDown(.left_shift) or input.keyDown(.right_shift)
input.keyDown(.left_alt) or input.keyDown(.right_alt)

Key Enum: 130+ keys including .a-.z, .F1-.F12, .space, .enter, .tab, .escape, arrow keys, numpad, etc.


Command (src/core/command.zig)

Draw command system for batched rendering.

const Command = zcatgui.Command;

// Command types
Command.rect(x, y, w, h, color)           // Filled rectangle
Command.rectOutline(x, y, w, h, color, thickness)
Command.text(x, y, text, color, font)     // Text rendering
Command.line(x1, y1, x2, y2, color)       // Line
Command.clip(x, y, w, h)                  // Push clip region
Command.clipEnd()                         // Pop clip region
Command.nop                               // No operation

Widgets

Basic Widgets

Widget File Description
Label widgets/label.zig Static text display
Button widgets/button.zig Clickable button with importance levels
TextInput widgets/text_input.zig Single-line text entry
TextArea widgets/textarea.zig Multi-line text editor
Checkbox widgets/checkbox.zig Boolean toggle
Radio widgets/radio.zig Radio button groups
Switch widgets/switch.zig Toggle switch (iOS style)

Selection Widgets

Widget File Description
Select widgets/select.zig Dropdown selection
List widgets/list.zig Scrollable list
AutoComplete widgets/autocomplete.zig ComboBox with filtering
Menu widgets/menu.zig Dropdown/context menus
Tabs widgets/tabs.zig Tab container

Data Widgets

Widget File Description
Table widgets/table.zig Editable data table with sorting
Tree widgets/tree.zig Hierarchical tree view
VirtualScroll widgets/virtual_scroll.zig Virtualized list for large data

Input Widgets

Widget File Description
Slider widgets/slider.zig Range selection
NumberEntry widgets/numberentry.zig Numeric input with validation
ColorPicker widgets/colorpicker.zig Color selection
DatePicker widgets/datepicker.zig Date selection calendar

Feedback Widgets

Widget File Description
Progress widgets/progress.zig Bar, circle, and spinner
Tooltip widgets/tooltip.zig Hover tooltips
Toast widgets/toast.zig Non-blocking notifications
Badge widgets/badge.zig Status labels and tags
Loader widgets/loader.zig Loading indicators

Layout Widgets

Widget File Description
Split widgets/split.zig HSplit/VSplit draggable panels
Panel widgets/panel.zig Container with title bar
Modal widgets/modal.zig Dialog windows
ScrollArea widgets/scroll.zig Scrollable content region
Surface widgets/surface.zig Elevated container (material)
Grid widgets/grid.zig Grid layout container
Resize widgets/resize.zig Resizable container
Divider widgets/divider.zig Visual separator

Navigation Widgets

Widget File Description
AppBar widgets/appbar.zig Top app bar
NavDrawer widgets/navdrawer.zig Side navigation
Sheet widgets/sheet.zig Bottom/side sheets
Breadcrumb widgets/breadcrumb.zig Navigation breadcrumbs
Discloser widgets/discloser.zig Expand/collapse sections

Visual Widgets

Widget File Description
Icon widgets/icon.zig Icon display
IconButton widgets/iconbutton.zig Icon-only button
Image widgets/image.zig Image display with caching
RichText widgets/richtext.zig Styled text spans
Canvas widgets/canvas.zig Custom drawing area
Chart widgets/chart.zig Line, bar, pie charts

Interactive Widgets

Widget File Description
Reorderable widgets/reorderable.zig Drag-to-reorder list
Selectable widgets/selectable.zig Selection container

Widget Usage Examples

Button

// Simple button
if (zcatgui.button(&ctx, "Click me")) {
    // Handle click
}

// Button with importance
if (zcatgui.buttonPrimary(&ctx, "Submit")) { ... }
if (zcatgui.buttonDanger(&ctx, "Delete")) { ... }

// Full configuration
const result = zcatgui.widgets.button.buttonEx(&ctx, "Save", .{
    .importance = .primary,
    .disabled = false,
    .width = 120,
}, .{});

TextInput

var text_state = zcatgui.TextInputState{};
var buffer: [256]u8 = undefined;

const result = zcatgui.textInput(&ctx, &text_state, &buffer);
if (result.changed) {
    // Text was modified
}
if (result.submitted) {
    // Enter was pressed
}

Table

const columns = [_]zcatgui.widgets.Column{
    .{ .name = "Name", .width = 150 },
    .{ .name = "Age", .width = 80, .column_type = .number },
    .{ .name = "Email", .width = 200 },
};

var table_state = zcatgui.widgets.TableState{};

const result = zcatgui.widgets.table.table(
    &ctx,
    &table_state,
    &columns,
    data,
    row_count,
);

if (result.cell_edited) {
    // Handle cell edit
}
if (result.row_added) {
    // Add new row
}

Slider

var slider_state = zcatgui.widgets.SliderState{};
slider_state.setValue(50, 0, 100); // Initial value

const result = zcatgui.widgets.slider.slider(&ctx, &slider_state);
if (result.changed) {
    const value = slider_state.getValueInt(0, 100);
}

Modal

var show_modal = false;

if (zcatgui.button(&ctx, "Open Modal")) {
    show_modal = true;
}

if (show_modal) {
    const result = zcatgui.widgets.modal.alert(
        &ctx,
        "Confirmation",
        "Are you sure?",
    );
    if (result.confirmed or result.cancelled) {
        show_modal = false;
    }
}

Rendering System

Framebuffer (src/render/framebuffer.zig)

Software pixel buffer.

const Framebuffer = zcatgui.render.Framebuffer;

var fb = try Framebuffer.init(allocator, 800, 600);
defer fb.deinit();

// Operations
fb.clear(Color.black);
fb.setPixel(x, y, color);
fb.getPixel(x, y);
fb.fillRect(x, y, w, h, color);
fb.drawRect(x, y, w, h, color);  // Outline
fb.drawLine(x1, y1, x2, y2, color);
fb.drawHLine(x, y, w, color);
fb.drawVLine(x, y, h, color);

// For blitting to backend
fb.getData()   // []const u32
fb.getPitch()  // Bytes per row

SoftwareRenderer (src/render/software.zig)

Executes draw commands on framebuffer.

const SoftwareRenderer = zcatgui.render.SoftwareRenderer;

var renderer = SoftwareRenderer.init(&framebuffer);
renderer.setDefaultFont(&font);

// Execute commands
renderer.execute(command);
renderer.executeAll(command_slice);

// Clipping
renderer.getClip();  // Current clip rect

Font System

zcatgui provides multiple bitmap fonts for different use cases:

Font Size Characters Use Case
default_font 8x8 ASCII Compact displays, terminals
default_font_latin1 8x8 Latin-1 Compact + Spanish/European
font_8x16 8x16 ASCII Standard UI, good readability
font_8x16_latin1 8x16 Latin-1 Standard UI + Spanish/European

Latin-1 Character Support: ñ, Ñ, á, é, í, ó, ú, ü, ¿, ¡, ç, ß, and all Western European accented characters.

Bitmap Fonts (src/render/font.zig):

const render = zcatgui.render;

// Direct font access
const font = render.default_font_latin1;  // 8x8 with Spanish support
const font_tall = render.font_8x16_latin1;  // 8x16 taller, more readable

// Font by size category (recommended)
const small_font = render.getFontForSize(.small);   // 8x8 Latin-1
const medium_font = render.getFontForSize(.medium); // 8x16 Latin-1

// ASCII-only variants (smaller memory)
const ascii_font = render.getFontForSizeAscii(.medium);

// Font operations
font.charWidth()           // 8
font.charHeight()          // 8 or 16
font.textWidth("Hello")    // width in pixels

font.drawChar(fb, x, y, 'A', color, clip);
font.drawText(fb, x, y, "¿Hola, España!", color, clip);

Setting Default Font in Renderer:

var renderer = SoftwareRenderer.init(&framebuffer);

// Use 8x16 Latin-1 for better readability and Spanish support
renderer.setDefaultFont(@constCast(&render.font_8x16_latin1));

TrueType Fonts (src/render/ttf.zig):

TTF fonts are fully supported with real glyph rasterization and antialiasing.

const TtfFont = zcatgui.render.TtfFont;
const FontRef = zcatgui.render.FontRef;

// Load TTF from file
var ttf = try TtfFont.loadFromFile(allocator, "/usr/share/fonts/adwaita-sans-fonts/AdwaitaSans-Regular.ttf");
defer ttf.deinit();

// Set render size (glyphs cached per size)
ttf.setSize(14);  // 14pt

// Get metrics
const metrics = ttf.getGlyphMetrics('A');
const width = ttf.textWidth("Hello");
const height = ttf.lineHeight();
const asc = ttf.ascent();   // Baseline to top
const desc = ttf.descent(); // Baseline to bottom

// Draw text directly
ttf.drawText(&framebuffer, x, y, "¡Hola, España!", color, clip);

// Or use FontRef for unified bitmap/TTF API
const font_ref = FontRef{ .ttf = &ttf };
font_ref.drawText(&framebuffer, x, y, "Hello", color, clip);

Features:

  • Real bezier curve rasterization (quadratic beziers)
  • Antialiasing via 2x supersampling
  • Glyph caching (by codepoint + size)
  • Alpha blending for smooth edges
  • Full Unicode support (BMP via cmap format 4, full via format 12)

Recommended fonts (free, good Latin-1 support):

Font Location (Fedora) Notes
AdwaitaSans /usr/share/fonts/adwaita-sans-fonts/ GNOME default, modern
DejaVu Sans /usr/share/fonts/dejavu-sans-fonts/ Very complete
Droid Sans /usr/share/fonts/google-droid-sans-fonts/ Android default

Switching between Bitmap and TTF:

// Use FontRef to switch fonts without changing widget code
var current_font: FontRef = .{ .bitmap = &render.font_8x16_latin1 };

// Later, switch to TTF
current_font = .{ .ttf = &ttf_font };

// Widget code stays the same
current_font.drawText(fb, x, y, text, color, clip);

UTF-8 Text Rendering

The software renderer automatically decodes UTF-8 text and maps codepoints to the font's character set.

How it works:

  1. Text strings (from SQLite, files, user input) are typically UTF-8 encoded
  2. The renderer decodes UTF-8 sequences (1-4 bytes per character)
  3. Codepoints are mapped to Latin-1 (0x00-0xFF) for bitmap font rendering
  4. Characters outside Latin-1 are displayed as '?' (placeholder)

Supported characters with Latin-1 fonts:

  • ASCII (0x00-0x7F): A-Z, a-z, 0-9, punctuation
  • Latin-1 Supplement (0x80-0xFF): ñ, Ñ, á, é, í, ó, ú, ü, ¿, ¡, ç, ß, €, £, ¥, etc.

Example - Spanish text:

// UTF-8 string from database or source code
const text = "¿Cómo está? Número: 100€";

// Renderer automatically handles UTF-8 decoding
ctx.pushCommand(Command.text(x, y, text, color));
// Displays correctly: ¿Cómo está? Número: 100€

Why UTF-8 in databases/files?

  • SQLite uses UTF-8 natively
  • Universal standard (Linux, Web, JSON, APIs)
  • ASCII-compatible (English text = same size)
  • Overhead minimal: "Razón Social" = 2 extra bytes vs pure ASCII

Animation & Effects

Animation (src/render/animation.zig)

Easing Functions:

const Easing = zcatgui.Easing;

Easing.linear(t)
Easing.easeInQuad(t), Easing.easeOutQuad(t), Easing.easeInOutQuad(t)
Easing.easeInCubic(t), Easing.easeOutCubic(t), Easing.easeInOutCubic(t)
Easing.easeInSine(t), Easing.easeOutSine(t), Easing.easeInOutSine(t)
Easing.easeInExpo(t), Easing.easeOutExpo(t), Easing.easeInOutExpo(t)
Easing.easeInElastic(t), Easing.easeOutElastic(t)
Easing.easeInBounce(t), Easing.easeOutBounce(t), Easing.easeInOutBounce(t)
Easing.easeInBack(t), Easing.easeOutBack(t), Easing.easeInOutBack(t)

Animation:

const Animation = zcatgui.Animation;

var anim = Animation.create(0, 100, 1000, Easing.easeOutCubic);
anim.start(current_time_ms);

// In frame loop
const value = anim.getValue(current_time_ms);
if (anim.isComplete(current_time_ms)) {
    // Animation done
}

Spring Physics:

const Spring = zcatgui.Spring;
const SpringConfig = zcatgui.SpringConfig;

var spring = Spring.create(0, 100, .{
    .stiffness = 100,
    .damping = 10,
    .mass = 1,
});

// Each frame
spring.update(dt_seconds);
const value = spring.getValue();
if (spring.isSettled()) { ... }

AnimationManager:

const AnimationManager = zcatgui.AnimationManager;

var manager = AnimationManager.init();
manager.startAnimation(id, animation, time);
manager.getValue(id, time);
manager.stopAnimation(id);
manager.update(time);

Effects (src/render/effects.zig)

Shadows:

const Shadow = zcatgui.Shadow;

const shadow = Shadow{
    .offset_x = 4,
    .offset_y = 4,
    .blur_radius = 8,
    .color = Color.rgba(0, 0, 0, 128),
};

// Presets
Shadow.soft()   // Subtle shadow
Shadow.hard()   // No blur
Shadow.drop(offset, blur)

zcatgui.applyShadow(framebuffer, rect, shadow);

Gradients:

const Gradient = zcatgui.Gradient;

// Types
Gradient.horizontal(start_color, end_color)
Gradient.vertical(start_color, end_color)
Gradient.diagonal(start_color, end_color)

const gradient = Gradient{
    .start_color = Color.rgb(255, 0, 0),
    .end_color = Color.rgb(0, 0, 255),
    .direction = .radial,
};

zcatgui.applyGradient(framebuffer, rect, gradient);

Color Operations:

zcatgui.interpolateColor(color_a, color_b, t)  // Blend
zcatgui.applyOpacity(color, 0.5)               // Reduce alpha
zcatgui.highlight(color, 50)                   // Lighter
zcatgui.lowlight(color, 50)                    // Darker
zcatgui.applyBlur(framebuffer, rect, radius)   // Box blur

Anti-aliasing (src/render/antialiasing.zig)

const AA = zcatgui.render.antialiasing;

// Quality levels
AAQuality.none, AAQuality.low, AAQuality.medium, AAQuality.high

// AA drawing functions
zcatgui.drawLineAA(fb, x1, y1, x2, y2, color, quality)
zcatgui.drawCircleAA(fb, cx, cy, radius, color, quality)
zcatgui.drawRoundedRectAA(fb, rect, corner_radius, color, quality)
zcatgui.drawEllipseAA(fb, rect, color, quality)
zcatgui.drawPolygonAA(fb, points, color, quality)

Backend System

Abstract Interface (src/backend/backend.zig)

const Backend = zcatgui.backend.Backend;

// VTable interface
backend.pollEvent()       // ?Event
backend.present(fb)       // Display framebuffer
backend.getSize()         // {width, height}
backend.deinit()          // Cleanup

Event Types:

const Event = zcatgui.backend.Event;

event.key        // KeyEvent
event.mouse      // MouseEvent
event.resize     // {width, height}
event.quit       // Window close
event.text_input // Unicode text

SDL2 Backend (src/backend/sdl2.zig)

Desktop platform (Linux, Windows, macOS).

const Sdl2Backend = zcatgui.backend.Sdl2Backend;

var backend = try Sdl2Backend.init(allocator, "My App", 800, 600);
defer backend.deinit();

while (backend.pollEvent()) |event| {
    // Handle events
}

backend.present(&framebuffer);

WASM Backend (src/backend/wasm.zig)

Browser via WebAssembly.

// Zig side - exports these functions
export fn wasm_main() void { ... }
export fn wasm_frame(time: f64) void { ... }
export fn wasm_resize(w: u32, h: u32) void { ... }
export fn wasm_mouse_move(x: i32, y: i32) void { ... }
export fn wasm_mouse_button(btn: u8, down: bool) void { ... }
export fn wasm_key_event(code: u16, down: bool) void { ... }

JavaScript integration (web/zcatgui.js):

// Load and initialize
const app = await ZcatguiApp.create('canvas-id', 'zcatgui-demo.wasm');
app.start();

Build: zig build wasm outputs to web/zcatgui-demo.wasm (18KB)

Android Backend (src/backend/android.zig)

Native Android via NDK.

// Exports for JNI
export fn ANativeActivity_onCreate(...) void { ... }

// Logging
zcatgui.backend.android.log("Message: {}", .{value});

Build: zig build android (ARM64), zig build android-x86 (emulator)

iOS Backend (src/backend/ios.zig)

iOS via UIKit bridge.

Zig side:

// Extern C functions called from Objective-C
extern fn ios_view_init(w: u32, h: u32) void;
extern fn ios_view_present(pixels: [*]const u32, w: u32, h: u32) void;
extern fn ios_poll_event(buffer: [*]u8) u32;

Objective-C bridge (ios/ZcatguiBridge.m):

  • ZcatguiView: UIView subclass for framebuffer display
  • ZcatguiViewController: View controller with CADisplayLink render loop
  • Touch event handling with queue

Build: zig build ios (device), zig build ios-sim (simulator)


Macro System

The macro system is a cornerstone feature of zcatgui, enabling recording and playback of user actions.

Design Philosophy

Raw keys, not semantic commands:

  • Simpler (less code = less bugs)
  • Like Vim (proven to work)
  • Minimal memory usage

MacroRecorder (src/macro/macro.zig)

const MacroRecorder = zcatgui.MacroRecorder;

var recorder = MacroRecorder.init(allocator);
defer recorder.deinit();

// Record
recorder.start();
recorder.record(key_event);  // Call for each key event
const events = recorder.stop();

// Save/Load
try recorder.save("macro.zcm");
try recorder.load("macro.zcm");

// Convert to named macro
const macro = try recorder.toMacro("my_macro");

MacroPlayer

const MacroPlayer = zcatgui.MacroPlayer;

// Injection function
fn injectKey(event: KeyEvent) void {
    // Add to input queue
}

// Playback
MacroPlayer.play(events, injectKey);
MacroPlayer.playWithDelay(events, injectKey, 50); // 50ms between keys

MacroStorage

const MacroStorage = zcatgui.macro.MacroStorage;

var storage = MacroStorage.init(allocator);
defer storage.deinit();

try storage.store(macro);
const m = storage.get("macro_name");
storage.remove("macro_name");
const names = storage.list();

File Format

ZCATGUI_MACRO_V1
<key_code>,<modifiers>,<char>,<pressed>
...

Panel System

Lego-style composable panels based on Simifactu architecture.

AutonomousPanel (src/panels/panel.zig)

Self-contained UI component with own state, UI, and logic.

const AutonomousPanel = zcatgui.panels.AutonomousPanel;

const panel = AutonomousPanel{
    .id = "my_panel",
    .panel_type = .content,
    .state = .active,
    .build_fn = myBuildFn,
    .refresh_fn = myRefreshFn,
    .data_change_fn = myDataChangeFn,
};

Composite Patterns (src/panels/composite.zig)

const composite = zcatgui.panels.composite;

// Vertical stack
var vstack = composite.VerticalComposite.init();
vstack.add(panel1);
vstack.add(panel2);

// Horizontal stack
var hstack = composite.HorizontalComposite.init();

// Split with draggable divider
var split = composite.SplitComposite.init(.horizontal, 0.5);

// Tabs
var tabs = composite.TabComposite.init();
tabs.addTab("Tab 1", panel1);
tabs.addTab("Tab 2", panel2);

// Grid layout
var grid = composite.GridComposite.init(3, 2); // 3 columns, 2 rows

DataManager (src/panels/data_manager.zig)

Observer pattern for panel communication.

const DataManager = zcatgui.panels.DataManager;

var manager = DataManager.init(allocator);
defer manager.deinit();

// Subscribe to changes
manager.subscribe("data_key", myCallback);

// Notify changes
manager.notify(.{
    .key = "data_key",
    .change_type = .modified,
    .data = payload,
});

// Global access
zcatgui.panels.setDataManager(&manager);
const dm = zcatgui.panels.getDataManager();

Performance Utilities

FrameArena (src/utils/arena.zig)

Per-frame allocator with O(1) reset.

const FrameArena = zcatgui.FrameArena;

var arena = try FrameArena.init(allocator, 1024 * 1024);
defer arena.deinit();

// Each frame
arena.reset();
const temp = arena.alloc(u8, 100);
// No need to free - reset clears everything

ObjectPool (src/utils/pool.zig)

Generic object pool for frequently reused objects.

const ObjectPool = zcatgui.ObjectPool;

var pool = ObjectPool(MyType).init(allocator, 100);
defer pool.deinit();

const obj = pool.acquire();
// Use obj...
pool.release(obj);

CommandPool

Specialized pool for draw commands.

const CommandPool = zcatgui.CommandPool;

var pool = CommandPool.init(allocator);
defer pool.deinit();

const cmd = pool.acquire();
pool.releaseAll();

Benchmark (src/utils/benchmark.zig)

const Timer = zcatgui.Timer;
const Benchmark = zcatgui.Benchmark;
const FrameTimer = zcatgui.FrameTimer;

// Simple timing
var timer = Timer.start();
// ... work ...
const elapsed_ns = timer.elapsed();

// Statistics
var bench = Benchmark.init();
for (iterations) |_| {
    timer = Timer.start();
    // ... work ...
    bench.addSample(timer.elapsed());
}
bench.average();
bench.min();
bench.max();
bench.stddev();
bench.median();

// Frame timing
var frame_timer = FrameTimer.init();
// Each frame
frame_timer.tick();
frame_timer.fps();
frame_timer.frameTimeMs();

AllocationTracker

const AllocationTracker = zcatgui.AllocationTracker;

var tracker = AllocationTracker.init();
tracker.trackAlloc(size);
tracker.trackFree(size);
tracker.currentBytes();
tracker.peakBytes();
tracker.totalAllocations();

Theme System

Built-in Themes

const ThemeManager = zcatgui.ThemeManager;

// Get global manager
var manager = zcatgui.getThemeManager();

// Switch themes
manager.setTheme(.dark);
manager.setTheme(.light);
manager.setTheme(.high_contrast);
manager.setTheme(.nord);
manager.setTheme(.dracula);

// Get current theme
const theme = zcatgui.currentTheme();
theme.colors.primary
theme.colors.secondary
theme.colors.background
theme.colors.surface
theme.colors.text
theme.colors.text_secondary
theme.colors.border
theme.colors.success
theme.colors.warning
theme.colors.danger

Custom Themes

const custom_theme = Theme{
    .name = "custom",
    .colors = .{
        .primary = Color.rgb(100, 150, 200),
        .background = Color.rgb(30, 30, 30),
        // ... etc
    },
};

manager.registerTheme("custom", custom_theme);

Accessibility

Roles (src/core/accessibility.zig)

const A11yRole = zcatgui.A11yRole;

A11yRole.button
A11yRole.checkbox
A11yRole.radio
A11yRole.textbox
A11yRole.slider
A11yRole.progressbar
A11yRole.listbox
A11yRole.tree
A11yRole.table
A11yRole.dialog
// ... and more

States

const A11yState = zcatgui.A11yState;

const state = A11yState{
    .disabled = false,
    .focused = true,
    .selected = false,
    .checked = true,
    .expanded = false,
};

Info

const A11yInfo = zcatgui.A11yInfo;

// Create info for widgets
A11yInfo.button("Submit")
A11yInfo.checkbox("Accept terms", is_checked)
A11yInfo.slider("Volume", 0, 100, current_value)
A11yInfo.progressBar("Loading", progress)
A11yInfo.listItem("Item 1", position, total)

// Announce for screen readers
var buf: [256]u8 = undefined;
const announcement = info.announce(&buf);

Manager

const A11yManager = zcatgui.A11yManager;

var manager = A11yManager.init(allocator);
defer manager.deinit();

manager.register(widget_id, a11y_info);
manager.setFocus(widget_id);
manager.queueAnnouncement("File saved", .polite);

Gesture Recognition

GestureRecognizer (src/core/gesture.zig)

const GestureRecognizer = zcatgui.GestureRecognizer;
const GestureType = zcatgui.GestureType;

var recognizer = GestureRecognizer.init(.{
    .double_tap_time_ms = 300,
    .long_press_time_ms = 500,
    .swipe_min_distance = 50,
    .swipe_min_velocity = 200,
});

// Each frame
const result = recognizer.update(&input_state, current_time_ms);

// Check gestures
if (recognizer.detected(.tap)) { ... }
if (recognizer.detected(.double_tap)) { ... }
if (recognizer.detected(.long_press)) { ... }
if (recognizer.detected(.swipe_left)) { ... }
if (recognizer.isDragging()) {
    const delta = recognizer.dragDelta();
}

Gesture Types:

  • .tap - Single tap
  • .double_tap - Double tap
  • .long_press - Press and hold
  • .drag - Press and move
  • .swipe_left, .swipe_right, .swipe_up, .swipe_down
  • .pinch, .rotate (future touch support)

API Reference

Main Module Exports (src/zcatgui.zig)

// Core
pub const Context
pub const Layout
pub const Style
pub const Input
pub const Command
pub const clipboard
pub const dragdrop
pub const shortcuts
pub const focus_group
pub const accessibility
pub const gesture

// Rendering
pub const render.Framebuffer
pub const render.SoftwareRenderer
pub const render.Font
pub const render.TtfFont
pub const render.animation
pub const render.effects
pub const render.antialiasing

// Animation (re-exports)
pub const Animation
pub const AnimationManager
pub const Easing
pub const Spring
pub const SpringConfig
pub const lerp
pub const lerpInt

// Effects (re-exports)
pub const Shadow
pub const Gradient
pub const applyShadow
pub const applyGradient
pub const applyBlur
pub const interpolateColor
pub const highlight
pub const lowlight

// Backend
pub const backend.Backend
pub const backend.Sdl2Backend  // Desktop only
pub const backend.wasm         // WASM only
pub const backend.android      // Android only
pub const backend.ios          // iOS only

// Macro
pub const macro
pub const MacroRecorder
pub const MacroPlayer
pub const KeyEvent

// Widgets (37 total)
pub const widgets

// Widget shortcuts
pub const label, labelEx, labelColored, labelCentered
pub const button, buttonEx, buttonPrimary, buttonDanger
pub const textInput, textInputEx, TextInputState
pub const checkbox, checkboxEx
pub const select, selectEx, SelectState
pub const list, listEx, ListState
pub const FocusManager, FocusRing

// Panels
pub const panels

// Utils
pub const utils
pub const FrameArena
pub const ScopedArena
pub const ObjectPool
pub const CommandPool
pub const RingBuffer
pub const Benchmark
pub const Timer
pub const FrameTimer
pub const AllocationTracker

// Types
pub const Color
pub const Rect
pub const Constraint
pub const Theme
pub const ThemeManager

Version History

Version Date Changes
0.15.0 2025-12-09 Mobile/Web backends (WASM, Android, iOS)
0.14.1 2025-12-09 Gio parity phase - 12 widgets + gesture system
0.1.0 2025-12-09 Initial release - core + macros + basic widgets

License

MIT License


  • zcatui: TUI library for terminal interfaces (sibling project)
  • microui: Inspiration for minimal architecture
  • DVUI: Reference Zig immediate-mode implementation
  • Gio: Go immediate-mode GUI (feature parity target)

Generated: 2025-12-09