Improved the Table Widget

- Added support for creating Tables from `ArrayList([]const u8)`.
- Added the `col_width` field to TableContext to help with Mouse support.
This commit is contained in:
00JCIV00 2024-03-27 11:03:53 -04:00 committed by Tim Culverhouse
parent 0329ae9b95
commit 46b82062de

View file

@ -31,6 +31,10 @@ pub const TableContext = struct{
/// Y Offset for drawing to the parent Window. /// Y Offset for drawing to the parent Window.
y_off: usize = 0, y_off: usize = 0,
/// Column Width
/// Note, this should be treated as Read Only. The Column Width will be calculated during `drawTable()`.
col_width: usize = 0,
}; };
/// Draw a Table for the TUI. /// Draw a Table for the TUI.
@ -56,8 +60,9 @@ pub fn drawTable(
.{ .limit = win.height }, .{ .limit = win.height },
); );
var item_width = table_win.width / headers.len; table_ctx.col_width = table_win.width / headers.len;
if (item_width % 2 != 0) item_width += 1; if (table_ctx.col_width % 2 != 0) table_ctx.col_width +|= 1;
while (table_ctx.col_width * headers.len < table_win.width - 1) table_ctx.col_width +|= 1;
if (table_ctx.col > headers.len - 1) table_ctx.*.col = headers.len - 1; if (table_ctx.col > headers.len - 1) table_ctx.*.col = headers.len - 1;
for (headers[0..], 0..) |hdr_txt, idx| { for (headers[0..], 0..) |hdr_txt, idx| {
@ -66,16 +71,16 @@ pub fn drawTable(
else if (idx % 2 == 0) table_ctx.hdr_bg_1 else if (idx % 2 == 0) table_ctx.hdr_bg_1
else table_ctx.hdr_bg_2; else table_ctx.hdr_bg_2;
const hdr_win = table_win.initChild( const hdr_win = table_win.initChild(
idx * item_width, idx * table_ctx.col_width,
0, 0,
.{ .limit = item_width }, .{ .limit = table_ctx.col_width },
.{ .limit = 1 }, .{ .limit = 1 },
); );
var hdr = vaxis.widgets.alignment.center(hdr_win, @min(item_width -| 1, hdr_txt.len +| 1), 1); var hdr = vaxis.widgets.alignment.center(hdr_win, @min(table_ctx.col_width -| 1, hdr_txt.len +| 1), 1);
hdr_win.fill(.{ .style = .{ .bg = hdr_bg } }); hdr_win.fill(.{ .style = .{ .bg = hdr_bg } });
var seg = [_]vaxis.Cell.Segment{.{ var seg = [_]vaxis.Cell.Segment{.{
.text = .text =
if (hdr_txt.len > item_width and alloc != null) try fmt.allocPrint(alloc.?, "{s}...", .{ hdr_txt[0..(item_width -| 4)] }) if (hdr_txt.len > table_ctx.col_width and alloc != null) try fmt.allocPrint(alloc.?, "{s}...", .{ hdr_txt[0..(table_ctx.col_width -| 4)] })
else hdr_txt else hdr_txt
, ,
.style = .{ .style = .{
@ -116,14 +121,26 @@ pub fn drawTable(
.{ .limit = 1 }, .{ .limit = 1 },
); );
const DataT = @TypeOf(data); const DataT = @TypeOf(data);
if (DataT == []const u8) {
row_win.fill(.{ .style = .{ .bg = row_bg } });
var seg = [_]vaxis.Cell.Segment{.{
.text =
if (data.len > table_ctx.col_width and alloc != null) try fmt.allocPrint(alloc.?, "{s}...", .{ data[0..(table_ctx.col_width -| 4)] })
else data
,
.style = .{ .bg = row_bg },
}};
try row_win.wrap(seg[0..]);
return;
}
const item_fields = meta.fields(DataT); const item_fields = meta.fields(DataT);
inline for (item_fields[0..], 0..) |item_field, item_idx| { inline for (item_fields[0..], 0..) |item_field, item_idx| {
const item = @field(data, item_field.name); const item = @field(data, item_field.name);
const ItemT = @TypeOf(item); const ItemT = @TypeOf(item);
const item_win = row_win.initChild( const item_win = row_win.initChild(
item_idx * item_width, item_idx * table_ctx.col_width,
0, 0,
.{ .limit = item_width }, .{ .limit = table_ctx.col_width },
.{ .limit = 1 }, .{ .limit = 1 },
); );
const item_txt = switch (ItemT) { const item_txt = switch (ItemT) {
@ -148,7 +165,7 @@ pub fn drawTable(
item_win.fill(.{ .style = .{ .bg = row_bg } }); item_win.fill(.{ .style = .{ .bg = row_bg } });
var seg = [_]vaxis.Cell.Segment{.{ var seg = [_]vaxis.Cell.Segment{.{
.text = .text =
if (item_txt.len > item_width and alloc != null) try fmt.allocPrint(alloc.?, "{s}...", .{ item_txt[0..(item_width -| 4)] }) if (item_txt.len > table_ctx.col_width and alloc != null) try fmt.allocPrint(alloc.?, "{s}...", .{ item_txt[0..(table_ctx.col_width -| 4)] })
else item_txt else item_txt
, ,
.style = .{ .bg = row_bg }, .style = .{ .bg = row_bg },