zcatgui/examples/hello.zig
reugenio 59c597fc18 feat: zCatGui v0.1.0 - Initial project setup
Immediate Mode GUI library for Zig with software rendering.

Core features:
- SDL2 backend for cross-platform window/events
- Software rasterizer (works everywhere, including SSH)
- Macro recording system (cornerstone feature, like Vim)
- Command-list rendering (DrawRect, DrawText, etc.)
- Layout system with constraints
- Color/Style system with themes

Project structure:
- src/core/: context, command, input, layout, style
- src/macro/: MacroRecorder, MacroPlayer, MacroStorage
- src/render/: Framebuffer, SoftwareRenderer, Font
- src/backend/: Backend interface, SDL2 implementation
- examples/: hello.zig, macro_demo.zig
- docs/: Architecture, research (Gio, immediate-mode libs, Simifactu)

Build: zig build (requires SDL2-devel)
Tests: 16 tests passing

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 01:30:05 +01:00

81 lines
2.3 KiB
Zig

//! Hello World - Basic zCatGui example
//!
//! Demonstrates:
//! - Initializing the backend
//! - Creating a framebuffer
//! - Basic rendering
//! - Event loop
const std = @import("std");
const zcatgui = @import("zcatgui");
const Framebuffer = zcatgui.render.Framebuffer;
const SoftwareRenderer = zcatgui.render.SoftwareRenderer;
const Sdl2Backend = zcatgui.backend.Sdl2Backend;
const Color = zcatgui.Color;
const Command = zcatgui.Command;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Initialize backend
var backend = try Sdl2Backend.init("zCatGui - Hello World", 800, 600);
defer backend.deinit();
// Create framebuffer
var fb = try Framebuffer.init(allocator, 800, 600);
defer fb.deinit();
// Create renderer
var renderer = SoftwareRenderer.init(&fb);
var running = true;
var frame: u32 = 0;
while (running) {
// Poll events
while (backend.pollEvent()) |event| {
switch (event) {
.quit => running = false,
.key => |key| {
if (key.key == .escape and key.pressed) {
running = false;
}
},
.resize => |size| {
try fb.resize(size.width, size.height);
},
else => {},
}
}
// Clear
renderer.clear(Color.background);
// Draw some rectangles
renderer.execute(Command.rect(50, 50, 200, 100, Color.primary));
renderer.execute(Command.rect(300, 50, 200, 100, Color.success));
renderer.execute(Command.rect(550, 50, 200, 100, Color.danger));
// Draw rectangle outline
renderer.execute(Command.rectOutline(50, 200, 700, 100, Color.border));
// Animate a rectangle
const x = @as(i32, @intCast(50 + (frame % 600)));
renderer.execute(Command.rect(x, 350, 100, 100, Color.warning));
// Draw some lines
renderer.execute(Command.line(50, 500, 750, 500, Color.foreground));
renderer.execute(Command.line(400, 450, 400, 550, Color.foreground));
// Present
backend.present(&fb);
frame += 1;
// Cap at ~60 FPS
std.Thread.sleep(16 * std.time.ns_per_ms);
}
}