mod: use allocators for Layout and Widget types
This commit is contained in:
@@ -100,7 +100,8 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
lib_unit_tests.root_module.addImport("zg", zg.module("code_point"));
|
||||
lib_unit_tests.root_module.addImport("interface", interface.module("interface"));
|
||||
lib_unit_tests.root_module.addImport("code_point", zg.module("code_point"));
|
||||
|
||||
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||
|
||||
|
||||
@@ -30,19 +30,19 @@ 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.HContainer.init(allocator, .{
|
||||
var layout = Layout.createFrom(allocator, Layout.HContainer.init(allocator, .{
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
15,
|
||||
},
|
||||
.{
|
||||
Layout.createFrom(Layout.VContainer.init(allocator, .{
|
||||
Layout.createFrom(allocator, Layout.VContainer.init(allocator, .{
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
25,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(blk: {
|
||||
Widget.createFrom(allocator, blk: {
|
||||
const file = try std.fs.cwd().openFile("./src/app.zig", .{});
|
||||
defer file.close();
|
||||
const widget = Widget.RawText.init(allocator, file);
|
||||
@@ -51,14 +51,14 @@ pub fn main() !void {
|
||||
50,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
25,
|
||||
},
|
||||
})),
|
||||
70,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
15,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -31,14 +31,14 @@ 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.VContainer.init(allocator, .{
|
||||
var layout = Layout.createFrom(allocator, Layout.VContainer.init(allocator, .{
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
45,
|
||||
},
|
||||
.{
|
||||
Layout.createFrom(Layout.Framing.init(allocator, .{}, .{
|
||||
.widget = Widget.createFrom(Widget.Text.init(allocator, .center, &[_]Cell{
|
||||
Layout.createFrom(allocator, Layout.Framing.init(allocator, .{}, .{
|
||||
.widget = Widget.createFrom(allocator, Widget.Text.init(allocator, .center, &[_]Cell{
|
||||
.{ .content = "Press " },
|
||||
.{ .content = "Ctrl+n", .style = .{ .fg = .{ .index = 6 } } },
|
||||
.{ .content = " to launch $EDITOR" },
|
||||
@@ -47,7 +47,7 @@ pub fn main() !void {
|
||||
10,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
45,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -30,10 +30,10 @@ 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.Padding.init(allocator, .{
|
||||
var layout = Layout.createFrom(allocator, Layout.Padding.init(allocator, .{
|
||||
.padding = 15,
|
||||
}, .{
|
||||
.layout = Layout.createFrom(Layout.Framing.init(allocator, .{
|
||||
.layout = Layout.createFrom(allocator, Layout.Framing.init(allocator, .{
|
||||
.style = .{
|
||||
.fg = .{
|
||||
.index = 6,
|
||||
@@ -49,13 +49,13 @@ pub fn main() !void {
|
||||
},
|
||||
},
|
||||
}, .{
|
||||
.layout = Layout.createFrom(Layout.Margin.init(
|
||||
.layout = Layout.createFrom(allocator, Layout.Margin.init(
|
||||
allocator,
|
||||
.{
|
||||
.margin = 10,
|
||||
},
|
||||
.{
|
||||
.widget = Widget.createFrom(blk: {
|
||||
.widget = Widget.createFrom(allocator, blk: {
|
||||
const file = try std.fs.cwd().openFile("./examples/padding.zig", .{});
|
||||
defer file.close();
|
||||
const widget = Widget.RawText.init(allocator, file);
|
||||
|
||||
@@ -30,7 +30,7 @@ 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.Framing.init(allocator, .{
|
||||
var layout = Layout.createFrom(allocator, Layout.Framing.init(allocator, .{
|
||||
.style = .{
|
||||
.fg = .{
|
||||
.index = 6,
|
||||
@@ -46,9 +46,9 @@ pub fn main() !void {
|
||||
},
|
||||
},
|
||||
}, .{
|
||||
.layout = Layout.createFrom(Layout.HStack.init(allocator, .{
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Layout.createFrom(Layout.Framing.init(
|
||||
.layout = Layout.createFrom(allocator, Layout.HStack.init(allocator, .{
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
Layout.createFrom(allocator, Layout.Framing.init(
|
||||
allocator,
|
||||
.{
|
||||
.style = .{
|
||||
@@ -67,18 +67,18 @@ pub fn main() !void {
|
||||
},
|
||||
},
|
||||
.{
|
||||
.layout = Layout.createFrom(Layout.Margin.init(allocator, .{
|
||||
.layout = Layout.createFrom(allocator, Layout.Margin.init(allocator, .{
|
||||
.margin = 10,
|
||||
}, .{
|
||||
.layout = Layout.createFrom(Layout.VStack.init(allocator, .{
|
||||
Widget.createFrom(blk: {
|
||||
.layout = Layout.createFrom(allocator, Layout.VStack.init(allocator, .{
|
||||
Widget.createFrom(allocator, 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: {
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, blk: {
|
||||
const file = try std.fs.cwd().openFile("./examples/stack.zig", .{});
|
||||
defer file.close();
|
||||
const widget = Widget.RawText.init(allocator, file);
|
||||
@@ -88,7 +88,7 @@ pub fn main() !void {
|
||||
})),
|
||||
},
|
||||
)),
|
||||
Widget.createFrom(Widget.Spacer.init(allocator)),
|
||||
Widget.createFrom(allocator, Widget.Spacer.init(allocator)),
|
||||
})),
|
||||
}));
|
||||
defer layout.deinit();
|
||||
|
||||
102
examples/tui.zig
Normal file
102
examples/tui.zig
Normal file
@@ -0,0 +1,102 @@
|
||||
const std = @import("std");
|
||||
const zterm = @import("zterm");
|
||||
|
||||
const App = zterm.App(
|
||||
union(enum) {},
|
||||
zterm.Renderer.Direct,
|
||||
true,
|
||||
);
|
||||
const Cell = zterm.Cell;
|
||||
const Key = zterm.Key;
|
||||
const Layout = App.Layout;
|
||||
const Widget = App.Widget;
|
||||
|
||||
const log = std.log.scoped(.tui);
|
||||
|
||||
pub fn main() !void {
|
||||
errdefer |err| log.err("Application Error: {any}", .{err});
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const allocator = arena.allocator();
|
||||
|
||||
var app: App = .{};
|
||||
var renderer: App.Renderer = .{};
|
||||
|
||||
// FIXME: the layout creates an 'incorrect alignment'?
|
||||
var layout = Layout.createFrom(allocator, Layout.VContainer.init(allocator, .{
|
||||
.{
|
||||
Layout.createFrom(allocator, Layout.Framing.init(allocator, .{
|
||||
.title = .{
|
||||
.str = "Welcome to my terminal website",
|
||||
.style = .{
|
||||
.ul = .{ .index = 6 },
|
||||
.ul_style = .single,
|
||||
},
|
||||
},
|
||||
}, .{
|
||||
.layout = Layout.createFrom(allocator, Layout.HContainer.init(allocator, .{
|
||||
.{
|
||||
Widget.createFrom(allocator, Widget.Text.init(allocator, .left, &[1]Cell{
|
||||
.{ .content = "Yves Biener", .style = .{ .bold = true } },
|
||||
})),
|
||||
25,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(allocator, Widget.Text.init(allocator, .center, &[1]Cell{
|
||||
.{ .content = "File name", .style = .{ .bold = true } },
|
||||
})),
|
||||
50,
|
||||
},
|
||||
.{
|
||||
Widget.createFrom(allocator, Widget.Text.init(allocator, .right, &[1]Cell{
|
||||
.{ .content = "Contact", .style = .{ .bold = true, .ul_style = .single } },
|
||||
})),
|
||||
25,
|
||||
},
|
||||
})),
|
||||
})),
|
||||
10,
|
||||
},
|
||||
.{
|
||||
Layout.createFrom(allocator, Layout.Margin.init(allocator, .{ .left = 15, .right = 15 }, .{
|
||||
.widget = Widget.createFrom(allocator, Widget.Text.init(allocator, .default, &[1]Cell{
|
||||
.{ .content = "Does this change anything?", .style = .{ .bold = true, .ul_style = .single } },
|
||||
})),
|
||||
})),
|
||||
90,
|
||||
},
|
||||
}));
|
||||
defer layout.deinit();
|
||||
|
||||
try app.start();
|
||||
defer app.stop() catch unreachable;
|
||||
|
||||
// App.Event loop
|
||||
while (true) {
|
||||
const event = app.nextEvent();
|
||||
|
||||
switch (event) {
|
||||
.quit => break,
|
||||
.resize => |size| {
|
||||
renderer.resize(size);
|
||||
},
|
||||
.key => |key| {
|
||||
// ctrl+c to quit
|
||||
if (Key.matches(key, .{ .cp = 'c', .mod = .{ .ctrl = true } })) {
|
||||
app.quit();
|
||||
}
|
||||
},
|
||||
.err => |err| {
|
||||
log.err("Received {any} with message: {s}", .{ err.err, err.msg });
|
||||
},
|
||||
}
|
||||
|
||||
const events = try layout.handle(event);
|
||||
for (events.items) |e| {
|
||||
app.postEvent(e);
|
||||
}
|
||||
try layout.render(&renderer);
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type {
|
||||
const Type = struct {
|
||||
const LayoutType = @This();
|
||||
const Element = union(enum) {
|
||||
layout: LayoutType,
|
||||
widget: @import("widget.zig").Widget(Event, Renderer),
|
||||
layout: *LayoutType,
|
||||
widget: *@import("widget.zig").Widget(Event, Renderer),
|
||||
};
|
||||
pub const Interface = @import("interface").Interface(.{
|
||||
.handle = fn (anytype, Event) anyerror!*Events,
|
||||
@@ -37,6 +37,7 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type {
|
||||
deinit: *const fn (this: *LayoutType) void,
|
||||
};
|
||||
|
||||
allocator: std.mem.Allocator = undefined,
|
||||
object: *anyopaque = undefined,
|
||||
vtable: *const VTable = undefined,
|
||||
|
||||
@@ -52,34 +53,36 @@ pub fn Layout(comptime Event: type, comptime Renderer: type) type {
|
||||
|
||||
pub fn deinit(this: *LayoutType) void {
|
||||
this.vtable.deinit(this);
|
||||
this.allocator.destroy(this);
|
||||
}
|
||||
|
||||
pub fn createFrom(object: anytype) LayoutType {
|
||||
return LayoutType{
|
||||
.object = @ptrCast(@alignCast(object)),
|
||||
.vtable = &.{
|
||||
.handle = struct {
|
||||
// Handle the provided `Event` for this `Layout`.
|
||||
fn handle(this: *LayoutType, event: Event) !*Events {
|
||||
const layout: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
return try layout.handle(event);
|
||||
}
|
||||
}.handle,
|
||||
.render = struct {
|
||||
// Render the contents of this `Layout`.
|
||||
fn render(this: *LayoutType, renderer: *Renderer) !void {
|
||||
const layout: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
try layout.render(renderer);
|
||||
}
|
||||
}.render,
|
||||
.deinit = struct {
|
||||
fn deinit(this: *LayoutType) void {
|
||||
const layout: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
layout.deinit();
|
||||
}
|
||||
}.deinit,
|
||||
},
|
||||
pub fn createFrom(allocator: std.mem.Allocator, object: anytype) *LayoutType {
|
||||
const layout = allocator.create(LayoutType) catch @panic("layout.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.object = @ptrCast(object);
|
||||
layout.vtable = &.{
|
||||
.handle = struct {
|
||||
// Handle the provided `Event` for this `Layout`.
|
||||
fn handle(this: *LayoutType, event: Event) !*Events {
|
||||
const layout_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
return try layout_ptr.handle(event);
|
||||
}
|
||||
}.handle,
|
||||
.render = struct {
|
||||
// Render the contents of this `Layout`.
|
||||
fn render(this: *LayoutType, renderer: *Renderer) !void {
|
||||
const layout_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
try layout_ptr.render(renderer);
|
||||
}
|
||||
}.render,
|
||||
.deinit = struct {
|
||||
fn deinit(this: *LayoutType) void {
|
||||
const layout_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
layout_ptr.deinit();
|
||||
}
|
||||
}.deinit,
|
||||
};
|
||||
return layout;
|
||||
}
|
||||
|
||||
// import and export of `Layout` implementations
|
||||
|
||||
@@ -51,7 +51,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) *@This() {
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("Framing.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.config = config;
|
||||
layout.element = element;
|
||||
@@ -62,10 +62,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.events.deinit();
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -97,11 +97,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
},
|
||||
};
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -110,11 +110,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
},
|
||||
else => {
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -185,10 +185,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
comptime var total_size = 0;
|
||||
const fields_info = args_type_info.@"struct".fields;
|
||||
var containers = Containers.initCapacity(allocator, fields_info.len) catch @panic("OOM");
|
||||
var containers = Containers.initCapacity(allocator, fields_info.len) catch @panic("HContainer.zig: out of memory");
|
||||
inline for (comptime fields_info) |field| {
|
||||
const child = @field(children, field.name);
|
||||
const ChildType = @TypeOf(child);
|
||||
@@ -88,7 +88,7 @@ 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));
|
||||
}
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("HContainer.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.containers = containers;
|
||||
layout.events = Events.init(allocator);
|
||||
@@ -99,10 +99,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
this.events.deinit();
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -140,11 +140,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
offset += cols;
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -155,11 +155,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
else => {
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -174,10 +174,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
@compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
|
||||
}
|
||||
const fields_info = args_type_info.@"struct".fields;
|
||||
var elements = Elements.initCapacity(allocator, fields_info.len) catch @panic("OOM");
|
||||
var elements = Elements.initCapacity(allocator, fields_info.len) catch @panic("HStack.zig: out of memory");
|
||||
inline for (comptime fields_info) |field| {
|
||||
const child = @field(children, field.name);
|
||||
const ChildType = @TypeOf(child);
|
||||
@@ -56,7 +56,7 @@ 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));
|
||||
}
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("HStack.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.elements = elements;
|
||||
layout.events = Events.init(allocator);
|
||||
@@ -67,10 +67,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
this.events.deinit();
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -115,11 +115,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
offset += cols;
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -130,11 +130,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
else => {
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -149,10 +149,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
config: Config = undefined,
|
||||
|
||||
const Config = struct {
|
||||
margin: ?u8 = undefined,
|
||||
margin: ?u8 = null,
|
||||
left: u8 = 0,
|
||||
right: u8 = 0,
|
||||
top: u8 = 0,
|
||||
@@ -48,7 +48,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
std.debug.assert(config.left + config.right < 100);
|
||||
std.debug.assert(config.top + config.bottom < 100);
|
||||
}
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("Margin.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.config = config;
|
||||
layout.element = element;
|
||||
@@ -59,10 +59,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.events.deinit();
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -116,11 +116,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
// adjust size according to the containing elements
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -129,11 +129,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
},
|
||||
else => {
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -151,10 +151,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
config: Config = undefined,
|
||||
|
||||
const Config = struct {
|
||||
padding: ?u16 = undefined,
|
||||
padding: ?u16 = null,
|
||||
left: u16 = 0,
|
||||
right: u16 = 0,
|
||||
top: u16 = 0,
|
||||
@@ -42,7 +42,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, config: Config, element: Element) *@This() {
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("Padding.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.config = config;
|
||||
layout.element = element;
|
||||
@@ -53,10 +53,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.events.deinit();
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -104,11 +104,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
// adjust size according to the containing elements
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -117,11 +117,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
},
|
||||
else => {
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -139,10 +139,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
|
||||
switch ((&this.element).*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
}
|
||||
comptime var total_size = 0;
|
||||
const fields_info = args_type_info.@"struct".fields;
|
||||
var containers = Containers.initCapacity(allocator, fields_info.len) catch @panic("OOM");
|
||||
var containers = Containers.initCapacity(allocator, fields_info.len) catch @panic("VContainer.zig: out of memory");
|
||||
inline for (comptime fields_info) |field| {
|
||||
const child = @field(children, field.name);
|
||||
const ChildType = @TypeOf(child);
|
||||
@@ -88,7 +88,7 @@ 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));
|
||||
}
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("VContainer.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.containers = containers;
|
||||
layout.events = Events.init(allocator);
|
||||
@@ -99,10 +99,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
this.events.deinit();
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -140,11 +140,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
offset += rows;
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -155,11 +155,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
else => {
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -174,10 +174,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
||||
for (this.containers.items) |*container| {
|
||||
switch (container.element) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
@compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
|
||||
}
|
||||
const fields_info = args_type_info.@"struct".fields;
|
||||
var elements = Elements.initCapacity(allocator, fields_info.len) catch @panic("OOM");
|
||||
var elements = Elements.initCapacity(allocator, fields_info.len) catch @panic("VStack.zig: out of memory");
|
||||
inline for (comptime fields_info) |field| {
|
||||
const child = @field(children, field.name);
|
||||
const ChildType = @TypeOf(child);
|
||||
@@ -56,7 +56,7 @@ 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));
|
||||
}
|
||||
const layout = allocator.create(@This()) catch @panic("OOM");
|
||||
const layout = allocator.create(@This()) catch @panic("VStack.zig: out of memory");
|
||||
layout.allocator = allocator;
|
||||
layout.elements = elements;
|
||||
layout.events = Events.init(allocator);
|
||||
@@ -67,10 +67,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
this.events.deinit();
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
layout.deinit();
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
widget.deinit();
|
||||
},
|
||||
}
|
||||
@@ -114,11 +114,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
};
|
||||
offset += rows;
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(sub_event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -129,11 +129,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
else => {
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
const events = try layout.handle(event);
|
||||
try this.events.appendSlice(events.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
if (widget.handle(event)) |e| {
|
||||
try this.events.append(e);
|
||||
}
|
||||
@@ -148,10 +148,10 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
|
||||
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
||||
for (this.elements.items) |*element| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
.layout => |layout| {
|
||||
try layout.render(renderer);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
.widget => |widget| {
|
||||
try widget.render(renderer);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//!
|
||||
//! When `Widget.render` is called the provided `Renderer` type is expected
|
||||
//! which handles how contents are rendered for a given widget.
|
||||
const std = @import("std");
|
||||
const isTaggedUnion = @import("event.zig").isTaggedUnion;
|
||||
|
||||
const log = @import("std").log.scoped(.widget);
|
||||
@@ -32,6 +33,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
deinit: *const fn (this: *WidgetType) void,
|
||||
};
|
||||
|
||||
allocator: std.mem.Allocator = undefined,
|
||||
object: *anyopaque = undefined,
|
||||
vtable: *const VTable = undefined,
|
||||
|
||||
@@ -58,34 +60,36 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
|
||||
pub fn deinit(this: *WidgetType) void {
|
||||
this.vtable.deinit(this);
|
||||
this.allocator.destroy(this);
|
||||
}
|
||||
|
||||
pub fn createFrom(object: anytype) WidgetType {
|
||||
return WidgetType{
|
||||
.object = @ptrCast(@alignCast(object)),
|
||||
.vtable = &.{
|
||||
.handle = struct {
|
||||
// Handle the provided `Event` for this `Widget`.
|
||||
fn handle(this: *WidgetType, event: Event) ?Event {
|
||||
const widget: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
return widget.handle(event);
|
||||
}
|
||||
}.handle,
|
||||
.render = struct {
|
||||
// Return the entire content of this `Widget`.
|
||||
fn render(this: *WidgetType, renderer: *Renderer) !void {
|
||||
const widget: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
try widget.render(renderer);
|
||||
}
|
||||
}.render,
|
||||
.deinit = struct {
|
||||
fn deinit(this: *WidgetType) void {
|
||||
const widget: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
widget.deinit();
|
||||
}
|
||||
}.deinit,
|
||||
},
|
||||
pub fn createFrom(allocator: std.mem.Allocator, object: anytype) *WidgetType {
|
||||
const widget = allocator.create(WidgetType) catch @panic("widget.zig: out of memory");
|
||||
widget.allocator = allocator;
|
||||
widget.object = @ptrCast(object);
|
||||
widget.vtable = &.{
|
||||
.handle = struct {
|
||||
// Handle the provided `Event` for this `Widget`.
|
||||
fn handle(this: *WidgetType, event: Event) ?Event {
|
||||
const widget_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
return widget_ptr.handle(event);
|
||||
}
|
||||
}.handle,
|
||||
.render = struct {
|
||||
// Return the entire content of this `Widget`.
|
||||
fn render(this: *WidgetType, renderer: *Renderer) !void {
|
||||
const widget_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
try widget_ptr.render(renderer);
|
||||
}
|
||||
}.render,
|
||||
.deinit = struct {
|
||||
fn deinit(this: *WidgetType) void {
|
||||
const widget_ptr: @TypeOf(object) = @ptrCast(@alignCast(this.object));
|
||||
widget_ptr.deinit();
|
||||
}
|
||||
}.deinit,
|
||||
};
|
||||
return widget;
|
||||
}
|
||||
|
||||
// import and export of `Widget` implementations
|
||||
|
||||
@@ -26,15 +26,16 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
var line_index = std.ArrayList(usize).init(allocator);
|
||||
file.reader().readAllArrayList(&contents, std.math.maxInt(usize)) catch {};
|
||||
line_index.append(0) catch {};
|
||||
for (contents.items, 0..) |item, i| {
|
||||
for (contents.items, 1..) |item, i| {
|
||||
if (item == '\n') {
|
||||
line_index.append(i + 1) catch {};
|
||||
line_index.append(i) catch {};
|
||||
}
|
||||
}
|
||||
const widget = allocator.create(@This()) catch @panic("OOM");
|
||||
const widget = allocator.create(@This()) catch @panic("RawText.zig: out of memory");
|
||||
widget.allocator = allocator;
|
||||
widget.contents = contents;
|
||||
widget.line_index = line_index;
|
||||
widget.line = 0;
|
||||
return widget;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
size_changed: bool = false,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) *@This() {
|
||||
const widget = allocator.create(@This()) catch @panic("OOM");
|
||||
const widget = allocator.create(@This()) catch @panic("Spacer.zig: out of memory");
|
||||
widget.allocator = allocator;
|
||||
return widget;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
||||
};
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, alignment: Alignment, contents: []const Cell) *@This() {
|
||||
const widget = allocator.create(@This()) catch @panic("OOM");
|
||||
const widget = allocator.create(@This()) catch @panic("Text.zig: out of memory");
|
||||
widget.allocator = allocator;
|
||||
widget.alignment = alignment;
|
||||
widget.contents = contents;
|
||||
|
||||
Reference in New Issue
Block a user