Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 4m26s
156 lines
6.3 KiB
Zig
156 lines
6.3 KiB
Zig
const std = @import("std");
|
|
const terminal = @import("../terminal.zig");
|
|
|
|
const isTaggedUnion = @import("../event.zig").isTaggedUnion;
|
|
const Error = @import("../event.zig").Error;
|
|
const Cell = terminal.Cell;
|
|
|
|
const log = std.log.scoped(.widget_text);
|
|
|
|
pub fn Widget(comptime Event: type, comptime Renderer: type) type {
|
|
if (!isTaggedUnion(Event)) {
|
|
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
|
}
|
|
return struct {
|
|
allocator: std.mem.Allocator,
|
|
alignment: Alignment,
|
|
contents: []const Cell,
|
|
size: terminal.Size,
|
|
require_render: bool,
|
|
|
|
const Alignment = enum {
|
|
default,
|
|
center,
|
|
top,
|
|
bottom,
|
|
left,
|
|
right,
|
|
};
|
|
|
|
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.allocator.destroy(this);
|
|
}
|
|
|
|
pub fn handle(this: *@This(), event: Event) ?Event {
|
|
switch (event) {
|
|
// store the received size
|
|
.resize => |size| {
|
|
this.size = size;
|
|
this.require_render = true;
|
|
},
|
|
else => {},
|
|
}
|
|
return null;
|
|
}
|
|
|
|
pub fn render(this: *@This(), renderer: *Renderer) !void {
|
|
if (!this.require_render) {
|
|
return;
|
|
}
|
|
try renderer.clear(this.size);
|
|
// update size for aligned contents, default will not change size
|
|
const size: terminal.Size = blk: {
|
|
switch (this.alignment) {
|
|
.default => break :blk this.size,
|
|
.center => {
|
|
var length_usize: usize = 0;
|
|
for (this.contents) |content| {
|
|
length_usize += content.content.len;
|
|
}
|
|
const length: u16 = @truncate(length_usize);
|
|
const cols = @min(length, this.size.cols);
|
|
const rows = cols / length;
|
|
break :blk .{
|
|
.anchor = .{
|
|
.col = this.size.anchor.col + @divTrunc(this.size.cols, 2) - @divTrunc(cols, 2),
|
|
.row = this.size.anchor.row + @divTrunc(this.size.rows, 2),
|
|
},
|
|
.rows = rows,
|
|
.cols = cols,
|
|
};
|
|
},
|
|
.top => {
|
|
var length_usize: usize = 0;
|
|
for (this.contents) |content| {
|
|
length_usize += content.content.len;
|
|
}
|
|
const length: u16 = @truncate(length_usize);
|
|
const cols = @min(length, this.size.cols);
|
|
const rows = cols / length;
|
|
break :blk .{
|
|
.anchor = .{
|
|
.col = this.size.anchor.col + @divTrunc(this.size.cols, 2) - @divTrunc(cols, 2),
|
|
.row = this.size.anchor.row,
|
|
},
|
|
.rows = rows,
|
|
.cols = cols,
|
|
};
|
|
},
|
|
.bottom => {
|
|
var length_usize: usize = 0;
|
|
for (this.contents) |content| {
|
|
length_usize += content.content.len;
|
|
}
|
|
const length: u16 = @truncate(length_usize);
|
|
const cols = @min(length, this.size.cols);
|
|
const rows = cols / length;
|
|
break :blk .{
|
|
.anchor = .{
|
|
.col = this.size.anchor.col + @divTrunc(this.size.cols, 2) - @divTrunc(cols, 2),
|
|
.row = this.size.anchor.row + this.size.rows - rows,
|
|
},
|
|
.rows = rows,
|
|
.cols = cols,
|
|
};
|
|
},
|
|
.left => {
|
|
var length_usize: usize = 0;
|
|
for (this.contents) |content| {
|
|
length_usize += content.content.len;
|
|
}
|
|
const length: u16 = @truncate(length_usize);
|
|
const cols = @min(length, this.size.cols);
|
|
const rows = cols / length;
|
|
break :blk .{
|
|
.anchor = .{
|
|
.col = this.size.anchor.col,
|
|
.row = this.size.anchor.row + @divTrunc(this.size.rows, 2) - @divTrunc(rows, 2),
|
|
},
|
|
.rows = rows,
|
|
.cols = cols,
|
|
};
|
|
},
|
|
.right => {
|
|
var length_usize: usize = 0;
|
|
for (this.contents) |content| {
|
|
length_usize += content.content.len;
|
|
}
|
|
const length: u16 = @truncate(length_usize);
|
|
const cols = @min(length, this.size.cols);
|
|
const rows = cols / length;
|
|
break :blk .{
|
|
.anchor = .{
|
|
.col = this.size.anchor.col + this.size.cols - cols,
|
|
.row = this.size.anchor.row + @divTrunc(this.size.rows, 2) - @divTrunc(rows, 2),
|
|
},
|
|
.rows = rows,
|
|
.cols = cols,
|
|
};
|
|
},
|
|
}
|
|
};
|
|
try renderer.render(size, this.contents);
|
|
this.require_render = false;
|
|
}
|
|
};
|
|
}
|