zcatui/examples/spinner_demo.zig
reugenio 7abc87a4f5 feat: zcatui v2.2 - Complete feature set with 13 new modules
New modules (13):
- src/resize.zig: SIGWINCH terminal resize detection
- src/drag.zig: Mouse drag state and Splitter panels
- src/diagnostic.zig: Elm-style error messages with code snippets
- src/debug.zig: Debug overlay (FPS, timing, widget count)
- src/profile.zig: Performance profiling with scoped timers
- src/sixel.zig: Sixel graphics encoding for terminal images
- src/async_loop.zig: epoll-based async event loop with timers
- src/compose.zig: Widget composition utilities
- src/shortcuts.zig: Keyboard shortcut registry
- src/widgets/logo.zig: ASCII art logo widget

Enhanced modules:
- src/layout.zig: Added Constraint.ratio(num, denom)
- src/terminal.zig: Integrated resize handling
- src/root.zig: Re-exports all new modules

New examples (9):
- resize_demo, splitter_demo, dirtree_demo
- help_demo, markdown_demo, progress_demo
- spinner_demo, syntax_demo, viewport_demo

Package manager:
- build.zig.zon: Zig package manager support

Stats: 60+ source files, 186+ tests, 20 executables

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 22:46:06 +01:00

151 lines
3.8 KiB
Zig

//! Spinner Demo - Shows all spinner styles
//!
//! Run with: zig build spinner-demo
const std = @import("std");
const zcatui = @import("zcatui");
const Terminal = zcatui.Terminal;
const Rect = zcatui.Rect;
const Buffer = zcatui.Buffer;
const Style = zcatui.Style;
const Color = zcatui.Color;
const Block = zcatui.widgets.Block;
const Borders = zcatui.widgets.Borders;
const Spinner = zcatui.widgets.Spinner;
const SpinnerStyle = zcatui.widgets.SpinnerStyle;
const styles = [_]SpinnerStyle{
.dots,
.dots_braille,
.line,
.arrows,
.box_corners,
.circle,
.blocks,
};
const style_names = [_][]const u8{
"Dots",
"Braille",
"Line",
"Arrows",
"Box",
"Circle",
"Blocks",
};
const messages = [_][]const u8{
"Loading...",
"Processing...",
"Compiling...",
"Connecting...",
"Syncing...",
"Waiting...",
"Downloading...",
};
/// State for the demo
const State = struct {
frame: u64 = 0,
selected_style: usize = 0,
running: bool = true,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var term = try Terminal.init(allocator);
defer term.deinit();
var state = State{};
// Main loop
while (state.running) {
try term.drawWithContext(&state, render);
// Poll events (non-blocking)
if (try term.pollEvent(50)) |event| {
switch (event) {
.key => |key| {
switch (key.code) {
.char => |c| {
if (c == 'q') state.running = false;
// Number keys 1-7 to select style
if (c >= '1' and c <= '7') {
state.selected_style = c - '1';
}
},
.up => {
if (state.selected_style > 0) state.selected_style -= 1;
},
.down => {
if (state.selected_style < styles.len - 1) state.selected_style += 1;
},
.esc => state.running = false,
else => {},
}
},
else => {},
}
}
state.frame +%= 1;
}
}
fn render(state: *State, area: Rect, buf: *Buffer) void {
// Draw border
const block = Block.init()
.title(" Spinner Styles ")
.setBorders(Borders.all)
.borderStyle((Style{}).fg(Color.cyan));
block.render(area, buf);
const inner = Rect.init(2, 2, area.width -| 4, area.height -| 4);
// Draw all spinners
var y: u16 = 0;
for (styles, 0..) |style, i| {
if (y >= inner.height -| 2) break;
const is_selected = i == state.selected_style;
const row_style = if (is_selected)
(Style{}).fg(Color.yellow).bold()
else
Style{};
// Style name
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "{s:<10}", .{style_names[i]}) catch "???";
_ = buf.setString(inner.x, inner.y + y, name, row_style);
// Spinner
var spinner = Spinner.init(style)
.setLabel(messages[i]);
// Tick based on frame
var tick_count: u64 = 0;
while (tick_count < state.frame) : (tick_count += 1) {
spinner.tick();
}
spinner.render(
Rect.init(inner.x + 12, inner.y + y, inner.width -| 12, 1),
buf,
);
y += 2;
}
// Instructions at bottom
const help_y = area.height -| 2;
_ = buf.setString(
2,
help_y,
"Press 1-7 to select style, up/down to navigate, q to quit",
(Style{}).fg(Color.rgb(100, 100, 100)),
);
}