this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

widgets(table): implemented customizable column widths

- Added the `WidthStyle` union to the Table Widget. This allows users to choose from 4 different options for Column Widths.
- Updated the Table Example with demos of the various styles (via comments).

authored by

00JCIV00 and committed by
Tim Culverhouse
a99fd3c2 bbbfbaff

+73 -21
+4 -1
examples/table.zig
··· 78 78 var demo_tbl: vaxis.widgets.Table.TableContext = .{ 79 79 .active_bg = active_bg, 80 80 .selected_bg = selected_bg, 81 - //.col_width = 10, 81 + //.col_width = .{ .static_all = 15 }, 82 + //.col_width = .{ .dynamic_header_len = 3 }, 83 + //.col_width = .{ .static_individual = &.{ 10, 20, 15, 25, 15 } }, 84 + //.col_width = .dynamic_fill, 82 85 //.y_off = 10, 83 86 }; 84 87 defer if (demo_tbl.sel_rows) |rows| alloc.free(rows);
+69 -20
src/widgets/Table.zig
··· 37 37 y_off: usize = 0, 38 38 39 39 /// Column Width 40 + <<<<<<< HEAD 40 41 /// Note, this should be treated as Read Only. The Column Width will be calculated during `drawTable()`. 41 42 col_width: ?usize = 0, 43 + ======= 44 + /// Note, if this is left `null` the Column Width will be dynamically calculated during `drawTable()`. 45 + //col_width: ?usize = null, 46 + col_width: WidthStyle = .dynamic_fill, 47 + }; 48 + 49 + /// Width Styles for `col_width`. 50 + pub const WidthStyle = union(enum) { 51 + /// Dynamically calculate Column Widths such that the entire (or most) of the screen is filled horizontally. 52 + dynamic_fill, 53 + /// Dynamically calculate the Column Width for each Column based on its Header Length and the provided Padding length. 54 + dynamic_header_len: usize, 55 + /// Statically set all Column Widths to the same value. 56 + static_all: usize, 57 + /// Statically set individual Column Widths to specific values. 58 + static_individual: []const usize, 59 + >>>>>>> 7918b49 (widgets(table): implemented customizable column widths) 42 60 }; 43 61 44 62 /// Draw a Table for the TUI. ··· 118 136 .{ .limit = win.height }, 119 137 ); 120 138 121 - table_ctx.col_width = table_win.width / headers.len; 122 - if (table_ctx.col_width % 2 != 0) table_ctx.col_width +|= 1; 123 - while (table_ctx.col_width * headers.len < table_win.width - 1) table_ctx.col_width +|= 1; 124 - 125 139 if (table_ctx.col > headers.len - 1) table_ctx.*.col = headers.len - 1; 140 + var col_start: usize = 0; 126 141 for (headers[0..], 0..) |hdr_txt, idx| { 142 + const col_width = try calcColWidth( 143 + idx, 144 + headers, 145 + table_ctx.col_width, 146 + table_win, 147 + ); 148 + defer col_start += col_width; 127 149 const hdr_bg = 128 150 if (table_ctx.active and idx == table_ctx.col) table_ctx.active_bg else if (idx % 2 == 0) table_ctx.hdr_bg_1 else table_ctx.hdr_bg_2; 129 151 const hdr_win = table_win.child(.{ 130 - .x_off = idx * col_width, 152 + //.x_off = idx * col_width, 153 + .x_off = col_start, 131 154 .y_off = 0, 132 155 .width = .{ .limit = col_width }, 133 156 .height = .{ .limit = 1 }, ··· 179 202 .{ .limit = 1 }, 180 203 ); 181 204 const DataT = @TypeOf(data); 182 - if (DataT == []const u8) { 183 - row_win.fill(.{ .style = .{ .bg = row_bg } }); 184 - var seg = [_]vaxis.Cell.Segment{.{ 185 - .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, 186 - .style = .{ .bg = row_bg }, 187 - }}; 188 - _ = try row_win.print(seg[0..], .{ .wrap = .word }); 189 - return; 190 - } 205 + col_start = 0; 191 206 const item_fields = meta.fields(DataT); 192 207 inline for (item_fields[0..], 0..) |item_field, item_idx| { 208 + const col_width = try calcColWidth( 209 + item_idx, 210 + headers, 211 + table_ctx.col_width, 212 + table_win, 213 + ); 214 + defer col_start += col_width; 193 215 const item = @field(data, item_field.name); 194 216 const ItemT = @TypeOf(item); 195 - const item_win = row_win.initChild( 196 - item_idx * table_ctx.col_width, 197 - 0, 198 - .{ .limit = table_ctx.col_width }, 199 - .{ .limit = 1 }, 200 - ); 217 + const item_win = row_win.child(.{ 218 + //.x_off = item_idx * col_width, 219 + .x_off = col_start, 220 + .y_off = 0, 221 + .width = .{ .limit = col_width }, 222 + .height =.{ .limit = 1 }, 223 + }); 201 224 const item_txt = switch (ItemT) { 202 225 []const u8 => item, 203 226 else => nonStr: { ··· 226 249 } 227 250 } 228 251 } 252 + 253 + /// Calculate the Column Width of `col` using the provided Number of Headers (`num_hdrs`), Width Style (`style`), and Table Window (`table_win`). 254 + pub fn calcColWidth ( 255 + col: usize, 256 + headers: []const []const u8, 257 + style: WidthStyle, 258 + table_win: vaxis.Window, 259 + ) !usize { 260 + return switch (style) { 261 + .dynamic_fill => dynFill: { 262 + var cw = table_win.width / headers.len; 263 + if (cw % 2 != 0) cw +|= 1; 264 + while (cw * headers.len < table_win.width - 1) cw +|= 1; 265 + break :dynFill cw; 266 + }, 267 + .dynamic_header_len => dynHdrs: { 268 + if (col >= headers.len) break :dynHdrs error.NotEnoughStaticWidthsProvided; 269 + break :dynHdrs headers[col].len + (style.dynamic_header_len * 2); 270 + }, 271 + .static_all => style.static_all, 272 + .static_individual => statInd: { 273 + if (col >= headers.len) break :statInd error.NotEnoughStaticWidthsProvided; 274 + break :statInd style.static_individual[col]; 275 + }, 276 + }; 277 + }