Widgets implemented (13 total): - Label: Static text with alignment - Button: With importance levels (primary/normal/danger) - TextInput: Single-line text entry with cursor - Checkbox: Boolean toggle - Select: Dropdown selection - List: Scrollable selectable list - Focus: Focus manager with tab navigation - Table: Editable table with dirty tracking, keyboard nav - Split: HSplit/VSplit draggable panels - Panel: Container with title bar, collapsible - Modal: Dialogs (alert, confirm, inputDialog) - AutoComplete: ComboBox with prefix/contains/fuzzy matching Core improvements: - InputState now tracks keyboard state (keys_down, key_events) - Full keyboard navigation for Table widget Research documentation: - WIDGET_COMPARISON.md: zcatgui vs DVUI vs Gio vs zcatui - SIMIFACTU_ADVANCEDTABLE.md: Analysis of 10K LOC table component - LEGO_PANELS_SYSTEM.md: Modular panel composition architecture Examples: - widgets_demo.zig: All basic widgets showcase - table_demo.zig: Table, Split, Panel demonstration All tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
177 lines
5.1 KiB
Zig
177 lines
5.1 KiB
Zig
//! Widget Demo - Showcase all zcatgui widgets
|
|
//!
|
|
//! This example demonstrates all available widgets:
|
|
//! - Label (static text)
|
|
//! - Button (clickable)
|
|
//! - TextInput (editable text)
|
|
//! - Checkbox (boolean toggle)
|
|
//! - Select (dropdown)
|
|
//! - List (scrollable selection)
|
|
//!
|
|
//! Run with: zig build widgets-demo
|
|
|
|
const std = @import("std");
|
|
const zcatgui = @import("zcatgui");
|
|
|
|
const Context = zcatgui.Context;
|
|
const Color = zcatgui.Color;
|
|
const Layout = zcatgui.Layout;
|
|
const Command = zcatgui.Command;
|
|
|
|
const print = std.debug.print;
|
|
|
|
pub fn main() !void {
|
|
print("=== zcatgui Widget Demo ===\n\n", .{});
|
|
print("This demo shows all available widgets.\n", .{});
|
|
print("In a real application, this would open a window.\n\n", .{});
|
|
|
|
// Create context
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
var ctx = Context.init(allocator, 800, 600);
|
|
defer ctx.deinit();
|
|
|
|
// Widget state
|
|
var name_buf: [64]u8 = undefined;
|
|
var name_input = zcatgui.TextInputState.init(&name_buf);
|
|
name_input.setText("Hello World");
|
|
|
|
var email_buf: [128]u8 = undefined;
|
|
var email_input = zcatgui.TextInputState.init(&email_buf);
|
|
|
|
var remember_me = true;
|
|
var newsletter = false;
|
|
|
|
var country_select = zcatgui.SelectState{};
|
|
const countries = [_][]const u8{ "Spain", "France", "Germany", "Italy", "Portugal" };
|
|
|
|
var file_list = zcatgui.ListState{};
|
|
const files = [_][]const u8{
|
|
"document.pdf",
|
|
"image.png",
|
|
"video.mp4",
|
|
"music.mp3",
|
|
"archive.zip",
|
|
"notes.txt",
|
|
"config.json",
|
|
"data.csv",
|
|
};
|
|
|
|
var click_count: u32 = 0;
|
|
|
|
// Simulate a few frames
|
|
print("Simulating 3 frames of UI rendering...\n\n", .{});
|
|
|
|
for (0..3) |frame| {
|
|
ctx.beginFrame();
|
|
|
|
// Set up layout
|
|
ctx.layout.row_height = 24;
|
|
|
|
print("--- Frame {} ---\n", .{frame + 1});
|
|
|
|
// Title
|
|
zcatgui.labelEx(&ctx, "Widget Demo", .{
|
|
.color = Color.primary,
|
|
.alignment = .center,
|
|
});
|
|
|
|
// Spacing
|
|
ctx.layout.row_height = 8;
|
|
_ = ctx.layout.nextRect(); // Empty row for spacing
|
|
|
|
ctx.layout.row_height = 24;
|
|
|
|
// Name input
|
|
zcatgui.label(&ctx, "Name:");
|
|
_ = zcatgui.textInput(&ctx, &name_input);
|
|
|
|
// Email input
|
|
zcatgui.label(&ctx, "Email:");
|
|
_ = zcatgui.textInputEx(&ctx, &email_input, .{
|
|
.placeholder = "user@example.com",
|
|
});
|
|
|
|
// Checkboxes
|
|
ctx.layout.row_height = 20;
|
|
_ = zcatgui.checkbox(&ctx, &remember_me, "Remember me");
|
|
_ = zcatgui.checkbox(&ctx, &newsletter, "Subscribe to newsletter");
|
|
|
|
// Country select
|
|
ctx.layout.row_height = 30;
|
|
zcatgui.label(&ctx, "Country:");
|
|
_ = zcatgui.select(&ctx, &country_select, &countries);
|
|
|
|
// Buttons
|
|
ctx.layout.row_height = 32;
|
|
|
|
// Simulate click on frame 2
|
|
if (frame == 1) {
|
|
ctx.input.setMousePos(100, 250);
|
|
ctx.input.setMouseButton(.left, true);
|
|
} else if (frame == 2) {
|
|
ctx.input.setMouseButton(.left, false);
|
|
}
|
|
|
|
if (zcatgui.buttonPrimary(&ctx, "Submit")) {
|
|
click_count += 1;
|
|
print(" -> Button clicked! Count: {}\n", .{click_count});
|
|
}
|
|
|
|
if (zcatgui.buttonDanger(&ctx, "Cancel")) {
|
|
print(" -> Cancel clicked!\n", .{});
|
|
}
|
|
|
|
// File list
|
|
ctx.layout.row_height = 150;
|
|
zcatgui.label(&ctx, "Files:");
|
|
_ = zcatgui.list(&ctx, &file_list, &files);
|
|
|
|
// Status
|
|
ctx.layout.row_height = 20;
|
|
var status_buf: [128]u8 = undefined;
|
|
const status = std.fmt.bufPrint(&status_buf, "Commands: {} | Clicks: {}", .{
|
|
ctx.commands.items.len,
|
|
click_count,
|
|
}) catch "Error";
|
|
zcatgui.labelColored(&ctx, status, Color.secondary);
|
|
|
|
ctx.endFrame();
|
|
|
|
print(" Generated {} draw commands\n", .{ctx.commands.items.len});
|
|
|
|
// Print some command details
|
|
var rect_count: usize = 0;
|
|
var text_count: usize = 0;
|
|
var line_count: usize = 0;
|
|
|
|
for (ctx.commands.items) |cmd| {
|
|
switch (cmd) {
|
|
.rect => rect_count += 1,
|
|
.text => text_count += 1,
|
|
.line => line_count += 1,
|
|
else => {},
|
|
}
|
|
}
|
|
|
|
print(" Rects: {}, Text: {}, Lines: {}\n", .{ rect_count, text_count, line_count });
|
|
}
|
|
|
|
print("\n", .{});
|
|
print("Widget state after 3 frames:\n", .{});
|
|
print(" Name: \"{s}\"\n", .{name_input.text()});
|
|
print(" Email: \"{s}\"\n", .{email_input.text()});
|
|
print(" Remember me: {}\n", .{remember_me});
|
|
print(" Newsletter: {}\n", .{newsletter});
|
|
print(" Country: {s}\n", .{
|
|
if (zcatgui.widgets.select.getSelectedText(country_select, &countries)) |c| c else "(none)",
|
|
});
|
|
print(" Selected file: {s}\n", .{
|
|
if (zcatgui.widgets.list.getSelectedText(file_list, &files)) |f| f else "(none)",
|
|
});
|
|
print(" Click count: {}\n", .{click_count});
|
|
|
|
print("\n=== Demo Complete ===\n", .{});
|
|
}
|