diff --git a/examples/container.zig b/examples/container.zig index 2b4f1e7..5704678 100644 --- a/examples/container.zig +++ b/examples/container.zig @@ -30,56 +30,38 @@ 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(); + const widget = Widget.RawText.init(allocator, file); + break :blk widget; + }), + 50, + }, + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 25, + }, + })), + 70, + }, + .{ + Widget.createFrom(Widget.Spacer.init(allocator)), + 15, + }, + })); defer layout.deinit(); try app.start(); diff --git a/examples/exec.zig b/examples/exec.zig index 669230c..06f7678 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(); try app.start(); diff --git a/examples/padding.zig b/examples/padding.zig index 2f260f9..0b2ef4f 100644 --- a/examples/padding.zig +++ b/examples/padding.zig @@ -30,54 +30,41 @@ 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, + 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(framing: { - var framing = 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(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; - }), - }, - ); - break :framing &framing; - }), - }); - break :layout &padding; - }); + .layout = Layout.createFrom(Layout.Margin.init( + allocator, + .{ + .margin = 10, + }, + .{ + .widget = Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/padding.zig", .{}); + defer file.close(); + const widget = Widget.RawText.init(allocator, file); + break :blk widget; + }), + }, + )), + })), + })); defer layout.deinit(); try app.start(); diff --git a/examples/stack.zig b/examples/stack.zig index 67f4390..f96516f 100644 --- a/examples/stack.zig +++ b/examples/stack.zig @@ -30,97 +30,67 @@ 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( - allocator, - .{ - .style = .{ - .fg = .{ - .index = 6, - }, - }, - .frame = .round, - .title = .{ - .str = "VStack", - .style = .{ - .ul_style = .single, - .ul = .{ .index = 6 }, - .bold = true, - }, - }, - }, - .{ - .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; - }, - ), - }, - ); - break :framing &framing; - }), - Widget.createFrom(blk: { - var spacer = Widget.Spacer.init(); - break :blk &spacer; - }), - }); - break :hstack &hstack; - }), - }); - break :layout &framing; - }); + .{ + .layout = Layout.createFrom(Layout.Margin.init(allocator, .{ + .margin = 10, + }, .{ + .layout = Layout.createFrom(Layout.VStack.init(allocator, .{ + Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); + defer file.close(); + const widget = Widget.RawText.init(allocator, file); + break :blk widget; + }), + Widget.createFrom(Widget.Spacer.init(allocator)), + Widget.createFrom(blk: { + const file = try std.fs.cwd().openFile("./examples/stack.zig", .{}); + defer file.close(); + const widget = Widget.RawText.init(allocator, file); + break :blk widget; + }), + })), + })), + }, + )), + Widget.createFrom(Widget.Spacer.init(allocator)), + })), + })); defer layout.deinit(); try app.start(); diff --git a/src/layout/Framing.zig b/src/layout/Framing.zig index 1399afd..054f660 100644 --- a/src/layout/Framing.zig +++ b/src/layout/Framing.zig @@ -27,6 +27,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, require_render: bool = true, element: Element = undefined, @@ -49,12 +50,13 @@ 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() { + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.config = config; + layout.element = element; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -67,6 +69,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/HContainer.zig b/src/layout/HContainer.zig index f9eefc7..dc368f6 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`? + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, containers: Containers = undefined, events: Events = undefined, - 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), - }; + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.containers = containers; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -106,6 +108,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.containers.deinit(); + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/HStack.zig b/src/layout/HStack.zig index 7574b2d..ede2208 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`? + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, elements: Elements = undefined, events: Events = undefined, - 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), - }; + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.elements = elements; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -74,6 +76,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.elements.deinit(); + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/Margin.zig b/src/layout/Margin.zig index 8d4feb5..45c0d00 100644 --- a/src/layout/Margin.zig +++ b/src/layout/Margin.zig @@ -26,6 +26,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, require_render: bool = false, element: Element = undefined, @@ -40,18 +41,19 @@ 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), - }; + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.config = config; + layout.element = element; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -64,6 +66,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/Padding.zig b/src/layout/Padding.zig index 65295e5..7b18f22 100644 --- a/src/layout/Padding.zig +++ b/src/layout/Padding.zig @@ -26,6 +26,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } const Events = std.ArrayList(Event); return struct { + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, require_render: bool = false, element: Element = undefined, @@ -40,12 +41,13 @@ 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() { + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.config = config; + layout.element = element; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -58,6 +60,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t widget.deinit(); }, } + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/VContainer.zig b/src/layout/VContainer.zig index af1a6f5..711a311 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`? + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, containers: Containers = undefined, events: Events = undefined, - 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), - }; + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.containers = containers; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -106,6 +108,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.containers.deinit(); + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/layout/VStack.zig b/src/layout/VStack.zig index eefe7e2..7720e7e 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`? + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, elements: Elements = undefined, events: Events = undefined, - 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), - }; + const layout = allocator.create(@This()) catch @panic("OOM"); + layout.allocator = allocator; + layout.elements = elements; + layout.events = Events.init(allocator); + return layout; } pub fn deinit(this: *@This()) void { @@ -74,6 +76,8 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t } } this.elements.deinit(); + this.allocator.destroy(this); + this.* = undefined; } pub fn handle(this: *@This(), event: Event) !*Events { diff --git a/src/widget/RawText.zig b/src/widget/RawText.zig index cf9cf29..1d76dd3 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 { + allocator: std.mem.Allocator = undefined, contents: Contents = undefined, line_index: std.ArrayList(usize) = undefined, line: usize = 0, size: terminal.Size = undefined, require_render: bool = false, - 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,15 +31,17 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type { line_index.append(i + 1) catch {}; } } - return .{ - .contents = contents, - .line_index = line_index, - }; + const widget = allocator.create(@This()) catch @panic("OOM"); + widget.allocator = allocator; + widget.contents = contents; + widget.line_index = line_index; + return widget; } pub fn deinit(this: *@This()) void { this.contents.deinit(); this.line_index.deinit(); + this.allocator.destroy(this); this.* = undefined; } diff --git a/src/widget/Spacer.zig b/src/widget/Spacer.zig index 3c608ae..7af4c9c 100644 --- a/src/widget/Spacer.zig +++ b/src/widget/Spacer.zig @@ -11,14 +11,18 @@ 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 { + allocator: std.mem.Allocator = undefined, size: terminal.Size = undefined, size_changed: bool = false, - pub fn init() @This() { - return .{}; + pub fn init(allocator: std.mem.Allocator) *@This() { + const widget = allocator.create(@This()) catch @panic("OOM"); + widget.allocator = allocator; + return widget; } pub fn deinit(this: *@This()) void { + this.allocator.destroy(this); this.* = undefined; } diff --git a/src/widget/Text.zig b/src/widget/Text.zig index 9a5f977..577d26d 100644 --- a/src/widget/Text.zig +++ b/src/widget/Text.zig @@ -12,6 +12,7 @@ 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 { + allocator: std.mem.Allocator = undefined, alignment: Alignment = undefined, contents: []const Cell = undefined, size: terminal.Size = undefined, @@ -26,14 +27,16 @@ 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() { + const widget = allocator.create(@This()) catch @panic("OOM"); + widget.allocator = allocator; + widget.alignment = alignment; + widget.contents = contents; + return widget; } pub fn deinit(this: *@This()) void { + this.allocator.destroy(this); this.* = undefined; }