diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..e7525b2 --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,1370 @@ +# 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](#overview) +2. [Installation & Setup](#installation--setup) +3. [Quick Start](#quick-start) +4. [Architecture](#architecture) +5. [Core Modules](#core-modules) +6. [Widgets (37 total)](#widgets) +7. [Rendering System](#rendering-system) +8. [Animation & Effects](#animation--effects) +9. [Backend System](#backend-system) +10. [Macro System](#macro-system) +11. [Panel System](#panel-system) +12. [Performance Utilities](#performance-utilities) +13. [Theme System](#theme-system) +14. [Accessibility](#accessibility) +15. [Gesture Recognition](#gesture-recognition) +16. [API Reference](#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 + +```bash +# 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`: +```zig +.dependencies = .{ + .zcatgui = .{ + .path = "../path/to/zcatgui", + }, +}, +``` + +--- + +## Quick Start + +```zig +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. + +```zig +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. + +```zig +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. + +```zig +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. + +```zig +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. + +```zig +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 + +```zig +// 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 + +```zig +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 + +```zig +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 + +```zig +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 + +```zig +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. + +```zig +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. + +```zig +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 + +**Bitmap Fonts** (`src/render/font.zig`): +```zig +const Font = zcatgui.render.Font; + +// Built-in 8x8 font +const font = zcatgui.render.default_font; + +font.charWidth() // 8 +font.charHeight() // 8 +font.textWidth("Hello") // 40 + +font.drawChar(fb, x, y, 'A', color, clip); +font.drawText(fb, x, y, "Hello", color, clip); +``` + +**TrueType Fonts** (`src/render/ttf.zig`): +```zig +const TtfFont = zcatgui.render.TtfFont; + +var ttf = try TtfFont.loadFromFile(allocator, "font.ttf"); +defer ttf.deinit(); + +const metrics = ttf.getMetrics(); +ttf.renderGlyph(codepoint, size); +``` + +--- + +## Animation & Effects + +### Animation (`src/render/animation.zig`) + +**Easing Functions:** +```zig +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:** +```zig +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:** +```zig +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:** +```zig +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:** +```zig +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:** +```zig +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:** +```zig +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`) + +```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`) + +```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:** +```zig +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). + +```zig +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 +// 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`): +```javascript +// 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. + +```zig +// 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:** +```zig +// 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`) + +```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 + +```zig +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 + +```zig +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 +,,, +... +``` + +--- + +## 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. + +```zig +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`) + +```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. + +```zig +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. + +```zig +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. + +```zig +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. + +```zig +const CommandPool = zcatgui.CommandPool; + +var pool = CommandPool.init(allocator); +defer pool.deinit(); + +const cmd = pool.acquire(); +pool.releaseAll(); +``` + +### Benchmark (`src/utils/benchmark.zig`) + +```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 + +```zig +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 + +```zig +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 + +```zig +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`) + +```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 + +```zig +const A11yState = zcatgui.A11yState; + +const state = A11yState{ + .disabled = false, + .focused = true, + .selected = false, + .checked = true, + .expanded = false, +}; +``` + +### Info + +```zig +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 + +```zig +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`) + +```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`) + +```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 + +--- + +## Related Projects + +- **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*