From c2c3f41ff3cd4facd9f2b3c9de43e3c393300ff6 Mon Sep 17 00:00:00 2001 From: Yves Biener Date: Mon, 6 Jan 2025 21:56:04 +0100 Subject: [PATCH] mod(memory): do not create items on the stack instead using the provided allocator --- examples/container.zig | 81 +++++++++------------- examples/exec.zig | 55 ++++++--------- examples/padding.zig | 74 +++++++++----------- examples/stack.zig | 140 ++++++++++++++++---------------------- examples/tabs.zig | 92 +++++++++++-------------- examples/tui.zig | 110 ++++++++++++------------------ src/layout.zig | 1 - src/layout/Framing.zig | 26 ++++--- src/layout/HContainer.zig | 19 +++--- src/layout/HStack.zig | 19 +++--- src/layout/Margin.zig | 26 ++++--- src/layout/Padding.zig | 26 ++++--- src/layout/Tab.zig | 29 ++++---- src/layout/VContainer.zig | 19 +++--- src/layout/VStack.zig | 19 +++--- src/widget.zig | 1 - src/widget/Input.zig | 42 +++++++----- src/widget/List.zig | 26 ++++--- src/widget/RawText.zig | 26 ++++--- src/widget/Spacer.zig | 14 ++-- src/widget/Text.zig | 23 ++++--- 21 files changed, 404 insertions(+), 464 deletions(-) diff --git a/examples/container.zig b/examples/container.zig index 2e5a47c..30c0a34 100644 --- a/examples/container.zig +++ b/examples/container.zig @@ -30,56 +30,37 @@ pub fn main() !void { // TODO: when not running fullscreen, the application needs to screen down accordingly to display the contents // -> size hint how much should it use? - var layout = Layout.createFrom(layout: { - var stack = Layout.HContainer.init(allocator, .{ - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 15, - }, - .{ - Layout.createFrom(container: { - var container = Layout.VContainer.init(allocator, .{ - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 25, - }, - .{ - Widget.createFrom(blk: { - const file = try std.fs.cwd().openFile("./src/app.zig", .{}); - defer file.close(); - var widget = Widget.RawText.init(allocator, file); - break :blk &widget; - }), - 50, - }, - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 25, - }, - }); - break :container &container; - }), - 70, - }, - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 15, - }, - }); - break :layout &stack; - }); + var layout = Layout.createFrom(Layout.HContainer.init(allocator, .{ + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 15, + }, + .{ + Layout.createFrom(Layout.VContainer.init(allocator, .{ + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 25, + }, + .{ + Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./src/app.zig", .{}); + defer file.close(); + break :blk Widget.RawText.init(allocator, file); + }), + 50, + }, + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 25, + }, + })), + 70, + }, + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 15, + }, + })); defer layout.deinit(); try app.start(null); diff --git a/examples/exec.zig b/examples/exec.zig index 3fb1c2c..16996f2 100644 --- a/examples/exec.zig +++ b/examples/exec.zig @@ -31,41 +31,26 @@ pub fn main() !void { // TODO: when not running fullscreen, the application needs to screen down accordingly to display the contents // -> size hint how much should it use? - var layout = Layout.createFrom(layout: { - var container = Layout.VContainer.init(allocator, .{ - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 45, - }, - .{ - Layout.createFrom(framing: { - var framing = Layout.Framing.init(allocator, .{}, .{ - .widget = Widget.createFrom(blk: { - var widget = Widget.Text.init(.center, &[_]Cell{ - .{ .content = "Press " }, - .{ .content = "Ctrl+n", .style = .{ .fg = .{ .index = 6 } } }, - .{ .content = " to launch $EDITOR" }, - }); - break :blk &widget; - }), - }); - break :framing &framing; - }), - 10, - }, - .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - 45, - }, - }); - break :layout &container; - }); + var layout = Layout.createFrom(Layout.VContainer.init(allocator, .{ + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 45, + }, + .{ + Layout.createFrom(Layout.Framing.init(allocator, .{}, .{ + .widget = Widget.createFrom(Widget.Text.init(allocator, .center, &[_]Cell{ + .{ .content = "Press " }, + .{ .content = "Ctrl+n", .style = .{ .fg = .{ .index = 6 } } }, + .{ .content = " to launch $EDITOR" }, + })), + })), + 10, + }, + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 45, + }, + })); defer layout.deinit(); const min_size: zterm.Size = .{ diff --git a/examples/padding.zig b/examples/padding.zig index 859ce15..f992870 100644 --- a/examples/padding.zig +++ b/examples/padding.zig @@ -30,54 +30,44 @@ pub fn main() !void { // TODO: when not running fullscreen, the application needs to screen down accordingly to display the contents // -> size hint how much should it use? - var layout = Layout.createFrom(layout: { - var padding = Layout.Padding.init(allocator, .{ - .padding = 15, - }, .{ - .layout = Layout.createFrom(framing: { - var framing = Layout.Framing.init( + var layout = Layout.createFrom(Layout.Padding.init(allocator, .{ + .padding = 15, + }, .{ + .layout = Layout.createFrom(Layout.Framing.init( + allocator, + .{ + .style = .{ + .fg = .{ + .index = 6, + }, + }, + .frame = .round, + .title = .{ + .str = "Content in Margin", + .style = .{ + .ul_style = .single, + .ul = .{ .index = 6 }, + .bold = true, + }, + }, + }, + .{ + .layout = Layout.createFrom(Layout.Margin.init( allocator, .{ - .style = .{ - .fg = .{ - .index = 6, - }, - }, - .frame = .round, - .title = .{ - .str = "Content in Margin", - .style = .{ - .ul_style = .single, - .ul = .{ .index = 6 }, - .bold = true, - }, - }, + .margin = 10, }, .{ - .layout = Layout.createFrom(margin: { - var margin = Layout.Margin.init( - allocator, - .{ - .margin = 10, - }, - .{ - .widget = Widget.createFrom(blk: { - const file = try std.fs.cwd().openFile("./examples/padding.zig", .{}); - defer file.close(); - var widget = Widget.RawText.init(allocator, file); - break :blk &widget; - }), - }, - ); - break :margin &margin; + .widget = Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/padding.zig", .{}); + defer file.close(); + break :blk Widget.RawText.init(allocator, file); }), }, - ); - break :framing &framing; - }), - }); - break :layout &padding; - }); + )), + }, + )), + })); defer layout.deinit(); try app.start(null); diff --git a/examples/stack.zig b/examples/stack.zig index 9e0d395..62077b9 100644 --- a/examples/stack.zig +++ b/examples/stack.zig @@ -30,97 +30,71 @@ pub fn main() !void { // TODO: when not running fullscreen, the application needs to screen down accordingly to display the contents // -> size hint how much should it use? - var layout = Layout.createFrom(layout: { - var framing = Layout.Framing.init(allocator, .{ + var layout = Layout.createFrom(Layout.Framing.init(allocator, .{ + .style = .{ + .fg = .{ + .index = 6, + }, + }, + .frame = .round, + .title = .{ + .str = "HStack", .style = .{ - .fg = .{ - .index = 6, - }, + .ul_style = .single, + .ul = .{ .index = 6 }, + .bold = true, }, - .frame = .round, - .title = .{ - .str = "HStack", - .style = .{ - .ul_style = .single, - .ul = .{ .index = 6 }, - .bold = true, + }, + }, .{ + .layout = Layout.createFrom(Layout.HStack.init(allocator, .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + Layout.createFrom(Layout.Framing.init( + allocator, + .{ + .style = .{ + .fg = .{ + .index = 6, + }, + }, + .frame = .round, + .title = .{ + .str = "VStack", + .style = .{ + .ul_style = .single, + .ul = .{ .index = 6 }, + .bold = true, + }, + }, }, - }, - }, .{ - .layout = Layout.createFrom(hstack: { - var hstack = Layout.HStack.init(allocator, .{ - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - Layout.createFrom(framing: { - var framing = Layout.Framing.init( + .{ + .layout = Layout.createFrom( + Layout.Margin.init( allocator, .{ - .style = .{ - .fg = .{ - .index = 6, - }, - }, - .frame = .round, - .title = .{ - .str = "VStack", - .style = .{ - .ul_style = .single, - .ul = .{ .index = 6 }, - .bold = true, - }, - }, + .margin = 10, }, .{ - .layout = Layout.createFrom( - padding: { - var padding = Layout.Margin.init( - allocator, - .{ - .margin = 10, - }, - .{ - .layout = Layout.createFrom(vstack: { - var vstack = Layout.VStack.init(allocator, .{ - Widget.createFrom(blk: { - const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); - defer file.close(); - var widget = Widget.RawText.init(allocator, file); - break :blk &widget; - }), - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - Widget.createFrom(blk: { - const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); - defer file.close(); - var widget = Widget.RawText.init(allocator, file); - break :blk &widget; - }), - }); - break :vstack &vstack; - }), - }, - ); - break :padding &padding; - }, - ), + .layout = Layout.createFrom(Layout.VStack.init(allocator, .{ + Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); + defer file.close(); + break :blk Widget.RawText.init(allocator, file); + }), + Widget.createFrom(Widget.Spacer.init(allocator)), + Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); + defer file.close(); + break :blk Widget.RawText.init(allocator, file); + }), + })), }, - ); - break :framing &framing; - }), - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - }); - break :hstack &hstack; - }), - }); - break :layout &framing; - }); + ), + ), + }, + )), + Widget.createFrom(Widget.Spacer.init(allocator)), + })), + })); defer layout.deinit(); try app.start(null); diff --git a/examples/tabs.zig b/examples/tabs.zig index 173bfb0..fe0624b 100644 --- a/examples/tabs.zig +++ b/examples/tabs.zig @@ -31,62 +31,46 @@ pub fn main() !void { // TODO: when not running fullscreen, the application needs to screen down accordingly to display the contents // -> size hint how much should it use? - var layout = Layout.createFrom(layout: { - var tabs = Layout.Tab.init(allocator, .{}, .{ - .{ - Layout.createFrom(margin: { - var margin = Layout.Margin.init(allocator, .{ .margin = 10 }, .{ - .widget = Widget.createFrom(blk: { - const file = try std.fs.cwd().openFile("./examples/tabs.zig", .{}); - defer file.close(); - var widget = Widget.RawText.init(allocator, file); - break :blk &widget; - }), - }); - break :margin &margin; + var layout = Layout.createFrom(Layout.Tab.init(allocator, .{}, .{ + .{ + Layout.createFrom(Layout.Margin.init(allocator, .{ .margin = 10 }, .{ + .widget = Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/tabs.zig", .{}); + defer file.close(); + break :blk Widget.RawText.init(allocator, file); }), - "Tab 2", - Cell.Style.Color{ .index = 6 }, - }, - .{ - Layout.createFrom(framing: { - var framing = Layout.Framing.init( - allocator, - .{ - .frame = .round, - .title = .{ - .str = "Content in Margin", - .style = .{ - .ul_style = .single, - .ul = .{ .index = 4 }, - .bold = true, - }, - }, + })), + "Tab 2", + Cell.Style.Color{ .index = 6 }, + }, + .{ + Layout.createFrom(Layout.Framing.init( + allocator, + .{ + .frame = .round, + .title = .{ + .str = "Content in Margin", + .style = .{ + .ul_style = .single, + .ul = .{ .index = 4 }, + .bold = true, }, - .{ - .layout = Layout.createFrom(margin: { - var margin = Layout.Margin.init(allocator, .{ .margin = 10 }, .{ - .widget = Widget.createFrom(blk: { - var widget = Widget.List.init(allocator, .ordered, .{ - &[_]Cell{.{ .content = "First entry" }}, - &[_]Cell{.{ .content = "Second entry" }}, - &[_]Cell{.{ .content = "Third entry" }}, - }); - break :blk &widget; - }), - }); - break :margin &margin; - }), - }, - ); - break :framing &framing; - }), - "Tab 1", - Cell.Style.Color{ .index = 4 }, - }, - }); - break :layout &tabs; - }); + }, + }, + .{ + .layout = Layout.createFrom(Layout.Margin.init(allocator, .{ .margin = 10 }, .{ + .widget = Widget.createFrom(Widget.List.init(allocator, .ordered, .{ + &[_]Cell{.{ .content = "First entry" }}, + &[_]Cell{.{ .content = "Second entry" }}, + &[_]Cell{.{ .content = "Third entry" }}, + })), + })), + }, + )), + "Tab 1", + Cell.Style.Color{ .index = 4 }, + }, + })); defer layout.deinit(); try app.start(null); diff --git a/examples/tui.zig b/examples/tui.zig index c1c38bd..7948873 100644 --- a/examples/tui.zig +++ b/examples/tui.zig @@ -25,73 +25,49 @@ pub fn main() !void { var renderer: App.Renderer = .{}; // FIXME: the layout creates an 'incorrect alignment'? - var layout = Layout.createFrom(layout: { - var layout = Layout.VContainer.init(allocator, .{ - .{ - Layout.createFrom(framing: { - var framing = Layout.Framing.init(allocator, .{ - .title = .{ - .str = "Welcome to my terminal website", - .style = .{ - .ul = .{ .index = 6 }, - .ul_style = .single, - }, - }, - }, .{ - .layout = Layout.createFrom(hcontainer: { - var hcontainer = Layout.HContainer.init(allocator, .{ - .{ - Widget.createFrom(text: { - var text = Widget.Text.init(.left, &[1]Cell{ - .{ .content = "Yves Biener", .style = .{ .bold = true } }, - }); - break :text &text; - }), - 25, - }, - .{ - Widget.createFrom(text: { - var text = Widget.Text.init(.left, &[1]Cell{ - .{ .content = "File name", .style = .{ .bold = true } }, - }); - break :text &text; - }), - 50, - }, - .{ - Widget.createFrom(text: { - var text = Widget.Text.init(.left, &[1]Cell{ - .{ .content = "Contacts", .style = .{ .bold = true } }, - }); - break :text &text; - }), - 25, - }, - }); - break :hcontainer &hcontainer; - }), - }); - break :framing &framing; - }), - 10, - }, - .{ - Layout.createFrom(margin: { - var margin = Layout.Margin.init(allocator, .{ .left = 15, .right = 15 }, .{ - .widget = Widget.createFrom(text: { - var text = Widget.Text.init(.default, &[1]Cell{ - .{ .content = "Does this change anything", .style = .{ .ul = .default, .ul_style = .single } }, - }); - break :text &text; - }), - }); - break :margin &margin; - }), - 90, - }, - }); - break :layout &layout; - }); + var layout = Layout.createFrom(Layout.VContainer.init(allocator, .{ + .{ + Layout.createFrom(Layout.Framing.init(allocator, .{ + .title = .{ + .str = "Welcome to my terminal website", + .style = .{ + .ul = .{ .index = 6 }, + .ul_style = .single, + }, + }, + }, .{ + .layout = Layout.createFrom(Layout.HContainer.init(allocator, .{ + .{ + Widget.createFrom(Widget.Text.init(allocator, .left, &[1]Cell{ + .{ .content = "Yves Biener", .style = .{ .bold = true } }, + })), + 25, + }, + .{ + Widget.createFrom(Widget.Text.init(allocator, .left, &[1]Cell{ + .{ .content = "File name", .style = .{ .bold = true } }, + })), + 50, + }, + .{ + Widget.createFrom(Widget.Text.init(allocator, .left, &[1]Cell{ + .{ .content = "Contacts", .style = .{ .bold = true } }, + })), + 25, + }, + })), + })), + 10, + }, + .{ + Layout.createFrom(Layout.Margin.init(allocator, .{ .left = 15, .right = 15 }, .{ + .widget = Widget.createFrom(Widget.Text.init(allocator, .default, &[1]Cell{ + .{ .content = "Does this change anything", .style = .{ .ul = .default, .ul_style = .single } }, + })), + })), + 90, + }, + })); defer layout.deinit(); try app.start(null); diff --git a/src/layout.zig b/src/layout.zig index a0f6543..cc69d8e 100644 --- a/src/layout.zig +++ b/src/layout.zig @@ -52,7 +52,6 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type { pub fn deinit(this: *LayoutType) void { this.vtable.deinit(this); - this.* = undefined; } pub fn createFrom(object: anytype) LayoutType { diff --git a/src/layout/Framing.zig b/src/layout/Framing.zig index f467f30..cad9bf1 100644 --- a/src/layout/Framing.zig +++ b/src/layout/Framing.zig @@ -27,11 +27,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { - size: terminal.Size = undefined, - require_render: bool = true, - element: Element = undefined, - events: Events = undefined, - config: Config = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + require_render: bool, + element: Element, + events: Events, + config: Config, const Config = struct { style: Style = .{ .fg = .default }, @@ -49,12 +50,14 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t }; }; - pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) @This() { - return .{ - .config = config, - .element = element, - .events = Events.init(allocator), - }; + pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) *@This() { + var this = allocator.create(@This()) catch @panic("Framing.zig: Failed to create."); + this.allocator = allocator; + this.require_render = true; + this.config = config; + this.element = element; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -67,6 +70,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/HContainer.zig b/src/layout/HContainer.zig index e275dad..b28e179 100644 --- a/src/layout/HContainer.zig +++ b/src/layout/HContainer.zig @@ -36,11 +36,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t const Events = std.ArrayList(Event); return struct { // TODO: current focused `Element`? - size: terminal.Size = undefined, - containers: Containers = undefined, - events: Events = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + containers: Containers, + events: Events, - pub fn init(allocator: std.mem.Allocator, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -87,10 +88,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } @compileError("nested child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType)); } - return .{ - .containers = containers, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("HContainer.zig: Failed to create."); + this.allocator = allocator; + this.containers = containers; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -106,6 +108,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.containers.deinit(); + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/HStack.zig b/src/layout/HStack.zig index a0d8642..8c01af3 100644 --- a/src/layout/HStack.zig +++ b/src/layout/HStack.zig @@ -30,11 +30,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t const Events = std.ArrayList(Event); return struct { // TODO: current focused `Element`? - size: terminal.Size = undefined, - elements: Elements = undefined, - events: Events = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + elements: Elements, + events: Events, - pub fn init(allocator: std.mem.Allocator, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -55,10 +56,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } @compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType)); } - return .{ - .elements = elements, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("HStack.zig: Failed to create."); + this.allocator = allocator; + this.elements = elements; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -74,6 +76,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.elements.deinit(); + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/Margin.zig b/src/layout/Margin.zig index 5009038..b6177c5 100644 --- a/src/layout/Margin.zig +++ b/src/layout/Margin.zig @@ -26,11 +26,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { - size: terminal.Size = undefined, - require_render: bool = false, - element: Element = undefined, - events: Events = undefined, - config: Config = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + require_render: bool, + element: Element, + events: Events, + config: Config, const Config = struct { margin: ?u8 = null, @@ -40,18 +41,20 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t bottom: u8 = 0, }; - pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) @This() { + pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) *@This() { if (config.margin) |margin| { std.debug.assert(margin <= 50); } else { std.debug.assert(config.left + config.right < 100); std.debug.assert(config.top + config.bottom < 100); } - return .{ - .config = config, - .element = element, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("Margin.zig: Failed to create."); + this.allocator = allocator; + this.require_render = true; + this.config = config; + this.element = element; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -64,6 +67,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/Padding.zig b/src/layout/Padding.zig index bf9570d..649cdc6 100644 --- a/src/layout/Padding.zig +++ b/src/layout/Padding.zig @@ -26,11 +26,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { - size: terminal.Size = undefined, - require_render: bool = false, - element: Element = undefined, - events: Events = undefined, - config: Config = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + require_render: bool, + element: Element, + events: Events, + config: Config, const Config = struct { padding: ?u16 = null, @@ -40,12 +41,14 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t bottom: u16 = 0, }; - pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) @This() { - return .{ - .config = config, - .element = element, - .events = Events.init(allocator), - }; + pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) *@This() { + var this = allocator.create(@This()) catch @panic("Padding.zig: Failed to create."); + this.allocator = allocator; + this.require_render = true; + this.config = config; + this.element = element; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -58,6 +61,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/Tab.zig b/src/layout/Tab.zig index 75cb7d9..b5cea83 100644 --- a/src/layout/Tab.zig +++ b/src/layout/Tab.zig @@ -37,12 +37,13 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t }; const Tabs = std.ArrayList(Tab); return struct { - size: terminal.Size = undefined, - require_render: bool = true, - tabs: Tabs = undefined, - active_tab: usize = 0, - events: Events = undefined, - config: Config = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + require_render: bool, + tabs: Tabs, + active_tab: usize, + events: Events, + config: Config, const Config = struct { frame: Frame = .round, @@ -53,7 +54,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t }; }; - pub fn init(allocator: std.mem.Allocator, config: Config, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, config: Config, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -104,11 +105,14 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } @compileError("nested child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType)); } - return .{ - .config = config, - .tabs = tabs, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("Tab.zig: Failed to create."); + this.allocator = allocator; + this.active_tab = 0; + this.require_render = true; + this.config = config; + this.tabs = tabs; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -124,6 +128,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.tabs.deinit(); + this.allocator.destroy(this); } fn resize_active_tab(this: *@This()) !void { diff --git a/src/layout/VContainer.zig b/src/layout/VContainer.zig index e151b21..9e7428c 100644 --- a/src/layout/VContainer.zig +++ b/src/layout/VContainer.zig @@ -36,11 +36,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t const Events = std.ArrayList(Event); return struct { // TODO: current focused `Element`? - size: terminal.Size = undefined, - containers: Containers = undefined, - events: Events = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + containers: Containers, + events: Events, - pub fn init(allocator: std.mem.Allocator, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -87,10 +88,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } @compileError("nested child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType)); } - return .{ - .containers = containers, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("VContainer.zig: Failed to create."); + this.allocator = allocator; + this.containers = containers; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -106,6 +108,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.containers.deinit(); + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/VStack.zig b/src/layout/VStack.zig index 9213f5a..f7bdd82 100644 --- a/src/layout/VStack.zig +++ b/src/layout/VStack.zig @@ -30,11 +30,12 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t const Events = std.ArrayList(Event); return struct { // TODO: current focused `Element`? - size: terminal.Size = undefined, - elements: Elements = undefined, - events: Events = undefined, + allocator: std.mem.Allocator, + size: terminal.Size, + elements: Elements, + events: Events, - pub fn init(allocator: std.mem.Allocator, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -55,10 +56,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } @compileError("child: " ++ field.name ++ " is not of type " ++ @typeName(WidgetType) ++ " or " ++ @typeName(LayoutType) ++ " but " ++ @typeName(ChildType)); } - return .{ - .elements = elements, - .events = Events.init(allocator), - }; + var this = allocator.create(@This()) catch @panic("VStack.zig: Failed to create."); + this.allocator = allocator; + this.elements = elements; + this.events = Events.init(allocator); + return this; } pub fn deinit(this: *@This()) void { @@ -74,6 +76,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.elements.deinit(); + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/widget.zig b/src/widget.zig index 8a95cd7..6bdc8bd 100644 --- a/src/widget.zig +++ b/src/widget.zig @@ -58,7 +58,6 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { pub fn deinit(this: *WidgetType) void { this.vtable.deinit(this); - this.* = undefined; } pub fn createFrom(object: anytype) WidgetType { diff --git a/src/widget/Input.zig b/src/widget/Input.zig index 82be21d..d82230e 100644 --- a/src/widget/Input.zig +++ b/src/widget/Input.zig @@ -13,30 +13,38 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { @compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`."); } return struct { - active: bool = false, - allocator: std.mem.Allocator = undefined, - label: ?[]const u8 = null, - placeholder: ?[]const u8 = null, - size: Size = undefined, - require_render: bool = false, - value: std.ArrayList(u8) = undefined, - value_len: usize = 0, // value content length - cursor_idx: usize = 0, // current cursor position + active: bool, + allocator: std.mem.Allocator, + label: ?[]const u8, + placeholder: ?[]const u8, + size: Size, + require_render: bool, + value: std.ArrayList(u8), + /// value content length + value_len: usize, + /// current cursor position + cursor_idx: usize, - pub fn init(allocator: std.mem.Allocator, label: ?[]const u8, placeholder: ?[]const u8) @This() { + pub fn init(allocator: std.mem.Allocator, label: ?[]const u8, placeholder: ?[]const u8) *@This() { var value = std.ArrayList(u8).init(allocator); value.resize(32) catch @panic("Input.zig: out of memory"); - return .{ - .allocator = allocator, - .value = value, - .label = label, - .placeholder = placeholder, - }; + var this = allocator.create(@This()) catch @panic("Input.zig: Failed to create."); + this.allocator = allocator; + this.active = false; + this.require_render = true; + this.label = null; + this.placeholder = null; + this.value_len = 0; + this.cursor_idx = 0; + this.value = value; + this.label = label; + this.placeholder = placeholder; + return this; } pub fn deinit(this: *@This()) void { this.value.deinit(); - this.* = undefined; + this.allocator.destroy(this); } pub fn getValue(this: *const @This()) []const u8 { diff --git a/src/widget/List.zig b/src/widget/List.zig index cac7ff0..818717a 100644 --- a/src/widget/List.zig +++ b/src/widget/List.zig @@ -14,18 +14,19 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { } const ListItems = std.ArrayList([]const Cell); return struct { - idx: usize = 0, - config: ListType = undefined, - contents: ListItems = undefined, - size: terminal.Size = undefined, - require_render: bool = false, + allocator: std.mem.Allocator, + idx: usize, + config: ListType, + contents: ListItems, + size: terminal.Size, + require_render: bool, const ListType = enum { unordered, ordered, }; - pub fn init(allocator: std.mem.Allocator, config: ListType, children: anytype) @This() { + pub fn init(allocator: std.mem.Allocator, config: ListType, children: anytype) *@This() { const ArgsType = @TypeOf(children); const args_type_info = @typeInfo(ArgsType); if (args_type_info != .@"struct") { @@ -42,15 +43,18 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { } contents.append(child) catch {}; } - return .{ - .config = config, - .contents = contents, - }; + var this = allocator.create(@This()) catch @panic("List.zig: Failed to create."); + this.allocator = allocator; + this.require_render = true; + this.idx = 0; + this.config = config; + this.contents = contents; + return this; } pub fn deinit(this: *@This()) void { this.contents.deinit(); - this.* = undefined; + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) ?Event { diff --git a/src/widget/RawText.zig b/src/widget/RawText.zig index 6d72e9f..2ba9420 100644 --- a/src/widget/RawText.zig +++ b/src/widget/RawText.zig @@ -14,13 +14,14 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { } const Contents = std.ArrayList(u8); return struct { - contents: Contents = undefined, - line_index: std.ArrayList(usize) = undefined, - line: usize = 0, - size: terminal.Size = undefined, - require_render: bool = false, + allocator: std.mem.Allocator, + contents: Contents, + line_index: std.ArrayList(usize), + line: usize, + size: terminal.Size, + require_render: bool, - pub fn init(allocator: std.mem.Allocator, file: std.fs.File) @This() { + pub fn init(allocator: std.mem.Allocator, file: std.fs.File) *@This() { var contents = Contents.init(allocator); var line_index = std.ArrayList(usize).init(allocator); file.reader().readAllArrayList(&contents, std.math.maxInt(usize)) catch {}; @@ -30,16 +31,19 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { line_index.append(i + 1) catch {}; } } - return .{ - .contents = contents, - .line_index = line_index, - }; + var this = allocator.create(@This()) catch @panic("RawText.zig: Failed to create."); + this.allocator = allocator; + this.line = 0; + this.require_render = true; + this.contents = contents; + this.line_index = line_index; + return this; } pub fn deinit(this: *@This()) void { this.contents.deinit(); this.line_index.deinit(); - this.* = undefined; + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) ?Event { diff --git a/src/widget/Spacer.zig b/src/widget/Spacer.zig index 3c608ae..200646f 100644 --- a/src/widget/Spacer.zig +++ b/src/widget/Spacer.zig @@ -11,15 +11,19 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { @compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`."); } return struct { - size: terminal.Size = undefined, - size_changed: bool = false, + allocator: std.mem.Allocator, + size: terminal.Size, + size_changed: bool, - pub fn init() @This() { - return .{}; + pub fn init(allocator: std.mem.Allocator) *@This() { + var this = allocator.create(@This()) catch @panic("Space.zig: Failed to create."); + this.allocator = allocator; + this.size_changed = true; + return this; } pub fn deinit(this: *@This()) void { - this.* = undefined; + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) ?Event { diff --git a/src/widget/Text.zig b/src/widget/Text.zig index a823470..33465db 100644 --- a/src/widget/Text.zig +++ b/src/widget/Text.zig @@ -12,10 +12,11 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { @compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`."); } return struct { - alignment: Alignment = undefined, - contents: []const Cell = undefined, - size: terminal.Size = undefined, - require_render: bool = false, + allocator: std.mem.Allocator, + alignment: Alignment, + contents: []const Cell, + size: terminal.Size, + require_render: bool, const Alignment = enum { default, @@ -26,15 +27,17 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { right, }; - pub fn init(alignment: Alignment, contents: []const Cell) @This() { - return .{ - .alignment = alignment, - .contents = contents, - }; + pub fn init(allocator: std.mem.Allocator, alignment: Alignment, contents: []const Cell) *@This() { + var this = allocator.create(@This()) catch @panic("Text.zig: Failed to create"); + this.allocator = allocator; + this.require_render = true; + this.alignment = alignment; + this.contents = contents; + return this; } pub fn deinit(this: *@This()) void { - this.* = undefined; + this.allocator.destroy(this); } pub fn handle(this: *@This(), event: Event) ?Event {