ref(event): remove .resize and replace with recursize method calls
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 40s

This also means that currently the dynamic resizing through the app's
detached thread is not working, as it cannot send size updates. The
examples have been overhauled to still implement intermediate mode
applications accordingly.
This commit is contained in:
2025-03-04 14:52:19 +01:00
parent 43cdc46853
commit ec22e68e8c
17 changed files with 334 additions and 224 deletions

View File

@@ -108,10 +108,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| { .key => |key| {
if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(); if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit();
@@ -140,6 +138,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -118,10 +118,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.click => |button| { .click => |button| {
log.info("Clicked with mouse using Button: {s}", .{button}); log.info("Clicked with mouse using Button: {s}", .{button});
@@ -137,6 +135,15 @@ pub fn main() !void {
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -131,10 +131,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.accept => |input| { .accept => |input| {
defer allocator.free(input); defer allocator.free(input);
@@ -151,6 +149,15 @@ pub fn main() !void {
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -157,10 +157,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
else => {}, else => {},
@@ -172,6 +170,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -70,7 +70,6 @@ const ErrorNotification = struct {
const this: *@This() = @ptrCast(@alignCast(ctx)); const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) { switch (event) {
.key => |key| if (!key.isAscii()) return error.UnsupportedKey, .key => |key| if (!key.isAscii()) return error.UnsupportedKey,
.size => |_| {},
.err => |err| this.msg = err.msg, .err => |err| this.msg = err.msg,
else => {}, else => {},
} }
@@ -134,10 +133,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
else => {}, else => {},
@@ -149,6 +146,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -85,10 +85,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
// NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
@@ -102,6 +100,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -77,10 +77,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
// NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
@@ -94,6 +92,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -89,10 +89,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
// NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
@@ -106,6 +104,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -76,10 +76,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
// NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
@@ -93,6 +91,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -74,10 +74,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
else => {}, else => {},
@@ -89,6 +87,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -127,10 +127,8 @@ pub fn main() !void {
const event = app.nextEvent(); const event = app.nextEvent();
log.debug("received event: {s}", .{@tagName(event)}); log.debug("received event: {s}", .{@tagName(event)});
// pre event handling
switch (event) { switch (event) {
.init => continue,
.quit => break,
.size => |size| try renderer.resize(size),
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(), .key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
else => {}, else => {},
@@ -142,6 +140,16 @@ pub fn main() !void {
.msg = "Container Event handling failed", .msg = "Container Event handling failed",
}, },
}); });
// post event handling
switch (event) {
.quit => break,
else => {},
}
try renderer.resize();
container.reposition(.{});
container.resize(renderer.size);
try renderer.render(@TypeOf(container), &container); try renderer.render(@TypeOf(container), &container);
try renderer.flush(); try renderer.flush();
} }

View File

@@ -97,9 +97,6 @@ pub fn App(comptime E: type) type {
try terminal.enterAltScreen(); try terminal.enterAltScreen();
try terminal.hideCursor(); try terminal.hideCursor();
try terminal.enableMouseSupport(); try terminal.enableMouseSupport();
// send initial size afterwards
this.postEvent(.{ .size = terminal.getTerminalSize() });
} }
pub fn interrupt(this: *@This()) !void { pub fn interrupt(this: *@This()) !void {
@@ -144,7 +141,8 @@ pub fn App(comptime E: type) type {
fn winsizeCallback(ptr: *anyopaque) void { fn winsizeCallback(ptr: *anyopaque) void {
const this: *@This() = @ptrCast(@alignCast(ptr)); const this: *@This() = @ptrCast(@alignCast(ptr));
this.postEvent(.{ .size = terminal.getTerminalSize() }); _ = this;
// this.postEvent(.{ .size = terminal.getTerminalSize() });
} }
var winch_handler: ?SignalHandler = null; var winch_handler: ?SignalHandler = null;
@@ -329,10 +327,12 @@ pub fn App(comptime E: type) type {
const width_char = iter.next() orelse break; const width_char = iter.next() orelse break;
const height_char = iter.next() orelse break; const height_char = iter.next() orelse break;
this.postEvent(.{ .size = .{ _ = width_char;
.x = std.fmt.parseUnsigned(u16, width_char, 10) catch break, _ = height_char;
.y = std.fmt.parseUnsigned(u16, height_char, 10) catch break, // this.postEvent(.{ .size = .{
} }); // .x = std.fmt.parseUnsigned(u16, width_char, 10) catch break,
// .y = std.fmt.parseUnsigned(u16, height_char, 10) catch break,
// } });
} }
}, },
'u' => { 'u' => {

View File

@@ -601,22 +601,21 @@ pub fn Container(comptime Event: type) type {
try this.elements.append(element); try this.elements.append(element);
} }
pub fn position(this: *@This(), pos: Point) !void { pub fn reposition(this: *@This(), origin: Point) void {
log.debug("pos: .{{ .x = {d}, .y = {d} }}", .{ pos.x, pos.y }); log.debug("origin: .{{ .x = {d}, .y = {d} }}", .{ origin.x, origin.y });
this.origin = pos; this.origin = origin;
this.element.reposition(origin);
} }
pub fn handle(this: *@This(), event: Event) !void { pub fn resize(this: *@This(), size: Point) void {
switch (event) {
.size => |size| resize: {
log.debug("Event .size: {{ .x = {d}, .y = {d} }}", .{ size.x, size.y }); log.debug("Event .size: {{ .x = {d}, .y = {d} }}", .{ size.x, size.y });
this.size = size; this.size = size;
if (this.properties.fixed_size.x > 0 and size.x < this.properties.fixed_size.x) return Error.TooSmall; if (this.properties.fixed_size.x > 0 and size.x < this.properties.fixed_size.x) return;
if (this.properties.fixed_size.y > 0 and size.y < this.properties.fixed_size.y) return Error.TooSmall; if (this.properties.fixed_size.y > 0 and size.y < this.properties.fixed_size.y) return;
try this.element.handle(event); this.element.resize(size);
if (this.elements.items.len == 0) break :resize; if (this.elements.items.len == 0) return;
const layout = this.properties.layout; const layout = this.properties.layout;
var fixed_size_elements: u16 = 0; var fixed_size_elements: u16 = 0;
@@ -634,8 +633,8 @@ pub fn Container(comptime Event: type) type {
} }
// check if the available screen is large enough // check if the available screen is large enough
switch (layout.direction) { switch (layout.direction) {
.horizontal => if (fixed_size.x > size.x) return Error.TooSmall, .horizontal => if (fixed_size.x > size.x) return,
.vertical => if (fixed_size.y > size.y) return Error.TooSmall, .vertical => if (fixed_size.y > size.y) return,
} }
const sides = this.properties.border.sides; const sides = this.properties.border.sides;
const padding = layout.padding; const padding = layout.padding;
@@ -763,11 +762,13 @@ pub fn Container(comptime Event: type) type {
if (sides.top) element_origin.y += 1; if (sides.top) element_origin.y += 1;
if (sides.left) element_origin.x += 1; if (sides.left) element_origin.x += 1;
// TODO tell the element its origin element.reposition(element_origin);
try element.position(element_origin); element.resize(element_size);
try element.handle(.{ .size = element_size });
} }
}, }
pub fn handle(this: *@This(), event: Event) !void {
switch (event) {
.mouse => |mouse| if (mouse.in(this.origin, this.size)) { .mouse => |mouse| if (mouse.in(this.origin, this.size)) {
try this.element.handle(event); try this.element.handle(event);
for (this.elements.items) |*element| try element.handle(event); for (this.elements.items) |*element| try element.handle(event);

View File

@@ -13,10 +13,24 @@ pub fn Element(Event: type) type {
vtable: *const VTable = &.{}, vtable: *const VTable = &.{},
pub const VTable = struct { pub const VTable = struct {
resize: ?*const fn (ctx: *anyopaque, size: Point) void = null,
reposition: ?*const fn (ctx: *anyopaque, origin: Point) void = null,
handle: ?*const fn (ctx: *anyopaque, event: Event) anyerror!void = null, handle: ?*const fn (ctx: *anyopaque, event: Event) anyerror!void = null,
content: ?*const fn (ctx: *anyopaque, cells: []Cell, origin: Point, size: Point) anyerror!void = null, content: ?*const fn (ctx: *anyopaque, cells: []Cell, origin: Point, size: Point) anyerror!void = null,
}; };
/// Resize the corresponding `Element` with the given *size*.
pub fn resize(this: @This(), size: Point) void {
if (this.vtable.resize) |resize_fn|
resize_fn(this.ptr, size);
}
/// Reposition the corresponding `Element` with the given *origin*.
pub fn reposition(this: @This(), origin: Point) void {
if (this.vtable.reposition) |reposition_fn|
reposition_fn(this.ptr, origin);
}
/// Handle the received event. The event is one of the user provided /// Handle the received event. The event is one of the user provided
/// events or a system event, with the exception of the `.size` /// events or a system event, with the exception of the `.size`
/// `Event` as every `Container` already handles that event. /// `Event` as every `Container` already handles that event.
@@ -73,6 +87,8 @@ pub fn Scrollable(Event: type) type {
return .{ return .{
.ptr = this, .ptr = this,
.vtable = &.{ .vtable = &.{
.resize = resize,
.reposition = reposition,
.handle = handle, .handle = handle,
.content = content, .content = content,
}, },
@@ -86,16 +102,23 @@ pub fn Scrollable(Event: type) type {
}; };
} }
fn resize(ctx: *anyopaque, size: Point) void {
const this: *@This() = @ptrCast(@alignCast(ctx));
this.size = size;
// TODO scrollbar space - depending on configuration and only if necessary?
this.container_size = Point.max(size, this.min_size);
this.container_origin = size; // TODO the size should be a provided origin
this.container.resize(this.container_size);
}
fn reposition(ctx: *anyopaque, origin: Point) void {
const this: *@This() = @ptrCast(@alignCast(ctx));
this.container_origin = origin; // TODO the size should be a provided origin
}
fn handle(ctx: *anyopaque, event: Event) !void { fn handle(ctx: *anyopaque, event: Event) !void {
const this: *@This() = @ptrCast(@alignCast(ctx)); const this: *@This() = @ptrCast(@alignCast(ctx));
switch (event) { switch (event) {
.size => |size| {
this.size = size;
// TODO scrollbar space - depending on configuration and only if necessary?
this.container_size = size.max(this.min_size);
this.container_origin = size; // TODO the size should be a provided origin
try this.container.handle(.{ .size = this.container_size });
},
// TODO other means to scroll except with the mouse? (i.e. Ctrl-u/d, k/j, etc.?) // TODO other means to scroll except with the mouse? (i.e. Ctrl-u/d, k/j, etc.?)
.mouse => |mouse| switch (mouse.button) { .mouse => |mouse| switch (mouse.button) {
Mouse.Button.wheel_up => if (this.container_size.y > this.size.y) { Mouse.Button.wheel_up => if (this.container_size.y > this.size.y) {
@@ -224,7 +247,7 @@ test "scrollable vertical" {
var renderer: testing.Renderer = .init(allocator, size); var renderer: testing.Renderer = .init(allocator, size);
defer renderer.deinit(); defer renderer.deinit();
try container.handle(.{ .size = size }); container.resize(size);
try renderer.render(Container(event.SystemEvent), &container); try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.top.zon"), renderer.screen); try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.vertical.top.zon"), renderer.screen);
@@ -298,7 +321,7 @@ test "scrollable horizontal" {
var renderer: testing.Renderer = .init(allocator, size); var renderer: testing.Renderer = .init(allocator, size);
defer renderer.deinit(); defer renderer.deinit();
try container.handle(.{ .size = size }); container.resize(size);
try renderer.render(Container(event.SystemEvent), &container); try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.left.zon"), renderer.screen); try testing.expectEqualCells(.{}, renderer.size, @import("test/element/scrollable.horizontal.left.zon"), renderer.screen);

View File

@@ -21,8 +21,6 @@ pub const SystemEvent = union(enum) {
/// associated error message /// associated error message
msg: []const u8, msg: []const u8,
}, },
/// Size event emitted by the terminal to derive the `Size` of the current terminal the application is rendered in
size: Point,
/// Input key event received from the user /// Input key event received from the user
key: Key, key: Key,
/// Mouse input event /// Mouse input event

View File

@@ -2,17 +2,17 @@ pub const Point = packed struct {
x: u16 = 0, x: u16 = 0,
y: u16 = 0, y: u16 = 0,
pub fn add(this: @This(), other: @This()) @This() { pub fn add(a: @This(), b: @This()) @This() {
return .{ return .{
.x = this.x + other.x, .x = a.x + b.x,
.y = this.y + other.y, .y = a.y + b.y,
}; };
} }
pub fn max(this: @This(), other: @This()) @This() { pub fn max(a: @This(), b: @This()) @This() {
return .{ return .{
.x = @max(this.x, other.x), .x = @max(a.x, b.x),
.y = @max(this.y, other.y), .y = @max(a.y, b.y),
}; };
} }

View File

@@ -29,9 +29,12 @@ pub const Buffered = struct {
} }
} }
pub fn resize(this: *@This(), size: Point) !void { pub fn resize(this: *@This()) !void {
const size = terminal.getTerminalSize();
if (std.meta.eql(this.size, size)) return;
this.size = size; this.size = size;
const n = @as(usize, size.x) * @as(usize, size.y); const n = @as(usize, this.size.x) * @as(usize, this.size.y);
if (!this.created) { if (!this.created) {
this.screen = this.allocator.alloc(Cell, n) catch @panic("render.zig: Out of memory."); this.screen = this.allocator.alloc(Cell, n) catch @panic("render.zig: Out of memory.");