//! Terminal Resize Demo //! //! Demonstrates automatic terminal resize handling. //! Try resizing your terminal window to see the app adapt. //! //! Run with: zig build resize-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; /// State for the demo const State = struct { resize_count: u32 = 0, last_width: u16 = 0, last_height: u16 = 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(); // Enable automatic resize detection term.enableAutoResize(); // Get initial size const initial_size = term.getSize(); var state = State{ .last_width = initial_size.width, .last_height = initial_size.height, }; while (state.running) { // Check if size changed const current_area = term.area(); if (current_area.width != state.last_width or current_area.height != state.last_height) { state.resize_count += 1; state.last_width = current_area.width; state.last_height = current_area.height; } try term.drawWithContext(&state, render); if (try term.pollEvent(100)) |event| { switch (event) { .key => |key| { switch (key.code) { .char => |c| { if (c == 'q') state.running = false; }, .esc => state.running = false, else => {}, } }, else => {}, } } } } fn render(state: *State, area: Rect, buf: *Buffer) void { // Main border const block = Block.init() .title(" Resize Demo ") .setBorders(Borders.all) .borderStyle((Style{}).fg(Color.cyan)); block.render(area, buf); // Content const content_start_y: u16 = 3; const content_x: u16 = 4; // Title _ = buf.setString( content_x, content_start_y, "Resize your terminal to see this demo adapt!", (Style{}).fg(Color.yellow).bold(), ); // Current size var size_buf: [64]u8 = undefined; const size_str = std.fmt.bufPrint(&size_buf, "Current size: {d} x {d}", .{ area.width, area.height, }) catch "?"; _ = buf.setString(content_x, content_start_y + 2, size_str, (Style{}).fg(Color.white)); // Resize count var count_buf: [64]u8 = undefined; const count_str = std.fmt.bufPrint(&count_buf, "Resize events: {d}", .{state.resize_count}) catch "?"; _ = buf.setString(content_x, content_start_y + 3, count_str, (Style{}).fg(Color.white)); // Draw a visual indicator based on size const indicator_y = content_start_y + 6; _ = buf.setString(content_x, indicator_y, "Size indicator:", (Style{}).fg(Color.magenta)); // Draw a bar that scales with width const bar_width = @min(area.width -| 10, 50); var i: u16 = 0; while (i < bar_width) : (i += 1) { const progress = @as(f32, @floatFromInt(i)) / @as(f32, @floatFromInt(bar_width)); const color = if (progress < 0.33) Color.red else if (progress < 0.66) Color.yellow else Color.green; _ = buf.setString(content_x + i, indicator_y + 1, "=", (Style{}).fg(color)); } // Draw a visual box that scales with size if (area.height > 15 and area.width > 30) { const box_y = indicator_y + 4; const box_width = @min(area.width -| 10, 40); const box_height = @min(area.height -| box_y -| 3, 10); // Draw box var y: u16 = 0; while (y < box_height) : (y += 1) { var x: u16 = 0; while (x < box_width) : (x += 1) { const is_border = y == 0 or y == box_height - 1 or x == 0 or x == box_width - 1; const char: []const u8 = if (is_border) "#" else " "; const style = if (is_border) (Style{}).fg(Color.blue) else Style{}; _ = buf.setString(content_x + x, box_y + y, char, style); } } // Label inside box var box_info: [32]u8 = undefined; const box_str = std.fmt.bufPrint(&box_info, "{d}x{d}", .{ box_width, box_height }) catch "?"; const label_x = content_x + (box_width / 2) - @as(u16, @intCast(box_str.len / 2)); _ = buf.setString(label_x, box_y + box_height / 2, box_str, (Style{}).fg(Color.cyan)); } // Footer _ = buf.setString( 2, area.height -| 1, "Press q to quit | Resize terminal to test", (Style{}).fg(Color.rgb(100, 100, 100)), ); }