From 7c9038fbda2daea0a99d97a5e57a906295fb7c0a Mon Sep 17 00:00:00 2001 From: Yves Biener Date: Sat, 16 Nov 2024 18:12:24 +0100 Subject: [PATCH] mod(widget/Text): add alignment options for Text Widget Updated exec example which uses centered text. --- examples/exec.zig | 2 +- src/widget/Text.zig | 106 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/examples/exec.zig b/examples/exec.zig index b0f55be..669230c 100644 --- a/examples/exec.zig +++ b/examples/exec.zig @@ -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" }, diff --git a/src/widget/Text.zig b/src/widget/Text.zig index d262ce2..9a5f977 100644 --- a/src/widget/Text.zig +++ b/src/widget/Text.zig @@ -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; } };