window: implement initial window data structure
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
parent
266c5ec224
commit
e1c042d5ae
3 changed files with 128 additions and 1 deletions
111
src/Window.zig
Normal file
111
src/Window.zig
Normal file
|
@ -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);
|
||||
}
|
15
src/app.zig
15
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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue