diff --git a/src/container.zig b/src/container.zig index 05abd46..1b19eba 100644 --- a/src/container.zig +++ b/src/container.zig @@ -566,6 +566,7 @@ pub fn Container(comptime Event: type) type { size: Point, properties: Properties, element: Element, + // TODO this should be renamed to `children` elements: std.ArrayList(@This()), /// Properties for each `Container` to configure their layout, @@ -593,7 +594,7 @@ pub fn Container(comptime Event: type) type { }; } - pub fn deinit(this: *@This()) void { + pub fn deinit(this: *const @This()) void { for (this.elements.items) |*element| { element.deinit(); } @@ -855,7 +856,7 @@ pub fn Container(comptime Event: type) type { this.grow_resize(this.size); } - pub fn handle(this: *@This(), event: Event) !void { + pub fn handle(this: *const @This(), event: Event) !void { switch (event) { .mouse => |mouse| if (mouse.in(this.origin, this.size)) { // the element receives the mouse event with relative position @@ -873,11 +874,12 @@ pub fn Container(comptime Event: type) type { } } - pub fn content(this: *const @This()) ![]const Cell { + pub fn content(this: *const @This()) ![]Cell { if (this.size.x == 0 or this.size.y == 0) return Error.TooSmall; + const cells = try this.allocator.alloc(Cell, @as(usize, this.size.x) * @as(usize, this.size.y)); - @memset(cells, .{}); errdefer this.allocator.free(cells); + @memset(cells, .{}); this.properties.layout.content(@This(), cells, this.origin, this.size, this.elements.items); this.properties.border.content(cells, this.size); diff --git a/src/element.zig b/src/element.zig index 3d2a801..b575d97 100644 --- a/src/element.zig +++ b/src/element.zig @@ -182,6 +182,7 @@ pub fn Scrollable(Event: type) type { configuration: Configuration, pub const Configuration = packed struct { + // TODO the scrollbar bool and the color should be in their own struct using `enabled` and `color` inside of the struct to be more consistent with other `Configuration` structs scrollbar: bool, color: Color = .default, x_axis: bool = false, @@ -281,7 +282,6 @@ pub fn Scrollable(Event: type) type { const size = container.size; const origin = container.origin; const contents = try container.content(); - defer container.allocator.free(contents); const anchor = (@as(usize, origin.y) * @as(usize, container_size.x)) + @as(usize, origin.x); @@ -294,6 +294,8 @@ pub fn Scrollable(Event: type) type { if (contents.len == idx) break :blk; } } + // free immediately + container.allocator.free(contents); for (container.elements.items) |child| try render_container(child, cells, size); } @@ -306,13 +308,7 @@ pub fn Scrollable(Event: type) type { const offset_y: usize = if (this.configuration.y_axis) 1 else 0; const container_size = this.container.size; - const container_cells = try this.container.allocator.alloc(Cell, @as(usize, container_size.x) * @as(usize, container_size.y)); - { - const container_cells_const = try this.container.content(); - defer this.container.allocator.free(container_cells_const); - assert(container_cells_const.len == @as(usize, container_size.x) * @as(usize, container_size.y)); - @memcpy(container_cells, container_cells_const); - } + const container_cells = try this.container.content(); for (this.container.elements.items) |child| try render_container(child, container_cells, container_size); @@ -705,7 +701,7 @@ pub fn Progress(Event: type, Queue: type) fn (meta.FieldEnum(Event)) type { } fn handle(ctx: *anyopaque, event: Event) !void { - var this: *@This() = @ptrCast(@alignCast(ctx)); + const this: *@This() = @ptrCast(@alignCast(ctx)); // TODO should this `Element` trigger a completion event? (I don't think that this is useful?) switch (event) { progress_event => |value| {