widgets(table): implemented more header and column options

- Added the `HeaderNames` Type and `header_names` field to `TableContext` to let users choose between automatically getting header names from fields or setting custom names.
- Removed the `headers` parameter from `drawTable()`.
- Added the `ColumnIndexes` Type and `col_indexes` field to `TableContext` to let users choose which columns/fields they actually want to display.
This commit is contained in:
00JCIV00 2024-08-15 00:31:18 -04:00 committed by Tim Culverhouse
parent d1b4e3f010
commit 500488f728
2 changed files with 56 additions and 4 deletions

View file

@ -79,6 +79,9 @@ pub fn main() !void {
var demo_tbl: vaxis.widgets.Table.TableContext = .{
.active_bg = active_bg,
.selected_bg = selected_bg,
.header_names = .{ .custom = &.{ "First", "Last", "Username", "Email", "Phone#" } },
//.header_names = .{ .custom = &.{ "First", "Last", "Email", "Phone#" } },
//.col_indexes = .{ .by_idx = &.{ 0, 1, 3, 4 } },
//.col_width = .{ .static_all = 15 },
//.col_width = .{ .dynamic_header_len = 3 },
//.col_width = .{ .static_individual = &.{ 10, 20, 15, 25, 15 } },
@ -274,7 +277,6 @@ pub fn main() !void {
try vaxis.widgets.Table.drawTable(
event_alloc,
middle_bar,
&.{ "First", "Last", "Username", "Email", "Phone#" },
//users_buf[0..],
user_list,
//user_mal,

View file

@ -49,6 +49,11 @@ pub const TableContext = struct {
/// Note, if this is left `null` the Column Width will be dynamically calculated during `drawTable()`.
//col_width: ?usize = null,
col_width: WidthStyle = .dynamic_fill,
// Header Names
header_names: HeaderNames = .field_names,
// Column Indexes
col_indexes: ColumnIndexes = .all,
};
/// Width Styles for `col_width`.
@ -63,6 +68,22 @@ pub const WidthStyle = union(enum) {
static_individual: []const usize,
};
/// Column Indexes
pub const ColumnIndexes = union(enum) {
/// Use all of the Columns.
all,
/// Use Columns from the specified indexes.
by_idx: []const usize,
};
/// Header Names
pub const HeaderNames = union(enum) {
/// Use Field Names as Headers
field_names,
/// Custom
custom: []const []const u8,
};
/// Draw a Table for the TUI.
pub fn drawTable(
/// This should be an ArenaAllocator that can be deinitialized after each event call.
@ -73,8 +94,6 @@ pub fn drawTable(
alloc: ?mem.Allocator,
/// The parent Window to draw to.
win: vaxis.Window,
/// Headers for the Table
headers: []const []const u8,
/// This must be a Slice, ArrayList, or MultiArrayList.
/// Note, MultiArrayList support currently requires allocation.
data_list: anytype,
@ -131,6 +150,31 @@ pub fn drawTable(
};
defer if (di_is_mal) alloc.?.free(data_items);
// Headers for the Table
var hdrs_buf: [100][]const u8 = undefined;
const headers = hdrs: {
switch (table_ctx.header_names) {
.field_names => {
const DataT = @TypeOf(data_items[0]);
const fields = meta.fields(DataT);
var num_hdrs: usize = 0;
inline for (fields, 0..) |field, idx| contFields: {
switch (table_ctx.col_indexes) {
.all => {},
.by_idx => |idxs| {
if (mem.indexOfScalar(usize, idxs, idx) == null) break :contFields;
},
}
num_hdrs += 1;
hdrs_buf[idx] = field.name;
}
break :hdrs hdrs_buf[0..num_hdrs];
},
.custom => |hdrs| break :hdrs hdrs,
}
};
const table_win = win.initChild(
0,
table_ctx.y_off,
@ -214,7 +258,13 @@ pub fn drawTable(
const DataT = @TypeOf(data);
col_start = 0;
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| contFields: {
switch (table_ctx.col_indexes) {
.all => {},
.by_idx => |idxs| {
if (mem.indexOfScalar(usize, idxs, item_idx) == null) break :contFields;
},
}
const col_width = try calcColWidth(
item_idx,
headers,