# zcatgui Reference Manual **Version**: 0.16.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 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`): ```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**: ```zig 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. ```zig 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:** ```zig // 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:** ```zig // 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:** ```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*