mod(widget/Text): add alignment options for Text Widget
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 36s

Updated exec example which uses centered text.
This commit is contained in:
2024-11-16 18:12:24 +01:00
parent aeac4bdc83
commit 7c9038fbda
2 changed files with 105 additions and 3 deletions

View File

@@ -44,7 +44,7 @@ pub fn main() !void {
Layout.createFrom(framing: {
var framing = Layout.Framing.init(allocator, .{}, .{
.widget = Widget.createFrom(blk: {
var widget = Widget.Text.init(&[_]Cell{
var widget = Widget.Text.init(.center, &[_]Cell{
.{ .content = "Press " },
.{ .content = "Ctrl+n", .style = .{ .fg = .{ .index = 6 } } },
.{ .content = " to launch $EDITOR" },

View File

@@ -12,12 +12,23 @@ 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,
pub fn init(contents: []const Cell) @This() {
const Alignment = enum {
default,
center,
top,
bottom,
left,
right,
};
pub fn init(alignment: Alignment, contents: []const Cell) @This() {
return .{
.alignment = alignment,
.contents = contents,
};
}
@@ -43,7 +54,98 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
return;
}
try renderer.clear(this.size);
try renderer.render(this.size, this.contents);
// 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 = @divExact(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 = @divExact(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 = @divExact(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 = @divExact(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 = @divExact(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;
}
};