From e1c042d5ae3894ddc56e6203adc0737ec52633a1 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Fri, 19 Jan 2024 06:45:44 -0600 Subject: [PATCH] window: implement initial window data structure Signed-off-by: Tim Culverhouse --- src/Window.zig | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ src/app.zig | 15 ++++++- src/main.zig | 3 ++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/Window.zig diff --git a/src/Window.zig b/src/Window.zig new file mode 100644 index 0000000..224693e --- /dev/null +++ b/src/Window.zig @@ -0,0 +1,111 @@ +const std = @import("std"); + +const Screen = @import("Screen.zig"); +const Cell = @import("cell.zig").Cell; + +const Window = @This(); + +pub const Size = union(enum) { + expand, + limit: usize, +}; + +x_off: usize, +y_off: usize, +width: usize, +height: usize, + +parent: ?*Window, +screen: *Screen, + +/// Creates a new window with offset relative to parent and size clamped to the +/// parents' size +pub fn initChild( + self: *Window, + x_off: usize, + y_off: usize, + width: Size, + height: Size, +) Window { + const resolved_width = switch (width) { + .expand => self.width - x_off, + .limit => |w| blk: { + if (w + x_off > self.width) { + break :blk self.width - x_off; + } + break :blk w; + }, + }; + const resolved_height = switch (height) { + .expand => self.height - y_off, + .limit => |h| blk: { + if (h + y_off > self.height) { + break :blk self.height - y_off; + } + break :blk h; + }, + }; + return Window{ + .x_off = x_off, + .y_off = y_off, + .width = resolved_width, + .height = resolved_height, + .parent = self, + .screen = self.screen, + }; +} + +/// writes a cell to the location in the window +pub fn writeCell(self: Window, cell: Cell, row: usize, col: usize) void { + if (self.h < row or self.w < col) return; + if (self.parent) |p| { + p.writeCell(cell, row + self.y_off, col + self.x_off); + } else { + self.screen.writeCell(cell, row + self.y_off, col + self.x_off); + } +} + +test "Window size set" { + var parent = Window{ + .x_off = 0, + .y_off = 0, + .width = 20, + .height = 20, + .parent = null, + .screen = undefined, + }; + + const child = parent.initChild(1, 1, .expand, .expand); + try std.testing.expectEqual(19, child.width); + try std.testing.expectEqual(19, child.height); +} + +test "Window size set too big" { + var parent = Window{ + .x_off = 0, + .y_off = 0, + .width = 20, + .height = 20, + .parent = null, + .screen = undefined, + }; + + const child = parent.initChild(0, 0, .{ .limit = 21 }, .{ .limit = 21 }); + try std.testing.expectEqual(20, child.width); + try std.testing.expectEqual(20, child.height); +} + +test "Window size set too big with offset" { + var parent = Window{ + .x_off = 0, + .y_off = 0, + .width = 20, + .height = 20, + .parent = null, + .screen = undefined, + }; + + const child = parent.initChild(10, 10, .{ .limit = 21 }, .{ .limit = 21 }); + try std.testing.expectEqual(10, child.width); + try std.testing.expectEqual(10, child.height); +} diff --git a/src/app.zig b/src/app.zig index 43c2c68..b1dc72d 100644 --- a/src/app.zig +++ b/src/app.zig @@ -4,6 +4,7 @@ const queue = @import("queue.zig"); const Tty = @import("Tty.zig"); const Key = @import("Key.zig"); const Screen = @import("Screen.zig"); +const Window = @import("Window.zig"); /// App is the entrypoint for an odditui application. The provided type T should /// be a tagged union which contains all of the events the application will @@ -83,6 +84,17 @@ pub fn App(comptime T: type) type { pub fn resize(self: *Self, alloc: std.mem.Allocator, w: usize, h: usize) !void { try self.screen.resize(alloc, w, h); } + + pub fn window(self: *Self) Window { + return Window{ + .x_off = 0, + .y_off = 0, + .w = .{.expand}, + .h = .{.expand}, + .parent = null, + .screen = &self.screen, + }; + } }; } @@ -90,8 +102,9 @@ test "App: event queueing" { const Event = union(enum) { key, }; + const alloc = std.testing.allocator; var app: App(Event) = try App(Event).init(.{}); - defer app.deinit(); + defer app.deinit(alloc); app.postEvent(.key); const event = app.nextEvent(); try std.testing.expect(event == .key); diff --git a/src/main.zig b/src/main.zig index 15eae6b..2464fdc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,7 +4,10 @@ pub const Winsize = @import("Tty.zig").Winsize; test { _ = @import("Key.zig"); + _ = @import("Screen.zig"); _ = @import("Tty.zig"); + _ = @import("Window.zig"); _ = @import("app.zig"); + _ = @import("cell.zig"); _ = @import("queue.zig"); }