this repo has no description
13
fork

Configure Feed

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

widgets(table): implemented optional active row contents callback & context

- Added `active_content_fn` as an optional callback function that can be provided to `TableContext` to vertically expand the active row with additional info.
- Added `active_ctx` and `active_y_off` to support the `active_content_fn`.
- Updated the Table Widget example with

authored by

00JCIV00 and committed by
Tim Culverhouse
999b0f4f a99fd3c2

+95 -27
+56 -2
examples/table.zig
··· 40 40 var loop: vaxis.Loop(union(enum) { 41 41 key_press: vaxis.Key, 42 42 winsize: vaxis.Winsize, 43 + table_upd, 43 44 }) = .{ .tty = &tty, .vaxis = &vx }; 44 45 try loop.init(); 45 46 try loop.start(); ··· 89 90 // TUI State 90 91 var active: ActiveSection = .mid; 91 92 var moving = false; 93 + var see_content = false; 92 94 93 95 // Create an Arena Allocator for easy allocations on each Event. 94 96 var event_arena = heap.ArenaAllocator.init(alloc); ··· 157 159 else try rows_list.append(demo_tbl.row); 158 160 demo_tbl.sel_rows = try rows_list.toOwnedSlice(); 159 161 } 162 + // See Row Content 163 + if (key.matches(vaxis.Key.enter, .{})) see_content = !see_content; 160 164 }, 161 165 .btm => { 162 166 if (key.matchesAny(&.{ vaxis.Key.up, 'k' }, .{}) and moving) active = .mid ··· 183 187 moving = false; 184 188 }, 185 189 .winsize => |ws| try vx.resize(alloc, tty.anyWriter(), ws), 186 - //else => {}, 190 + else => {}, 191 + } 192 + 193 + // Content 194 + seeRow: { 195 + if (!see_content) { 196 + demo_tbl.active_content_fn = null; 197 + demo_tbl.active_ctx = &{}; 198 + break :seeRow; 199 + } 200 + const RowContext = struct{ 201 + row: []const u8, 202 + bg: vaxis.Color, 203 + }; 204 + const row_ctx = RowContext{ 205 + .row = try fmt.allocPrint(event_alloc, "Row #: {d}", .{ demo_tbl.row }), 206 + .bg = demo_tbl.active_bg, 207 + }; 208 + demo_tbl.active_ctx = &row_ctx; 209 + demo_tbl.active_content_fn = struct{ 210 + fn see(win: *vaxis.Window, ctx_raw: *const anyopaque) !usize { 211 + const ctx: *const RowContext = @alignCast(@ptrCast(ctx_raw)); 212 + win.height = 5; 213 + const see_win = win.child(.{ 214 + .x_off = 0, 215 + .y_off = 1, 216 + .width = .{ .limit = win.width }, 217 + .height = .{ .limit = 4 }, 218 + }); 219 + see_win.fill(.{ .style = .{ .bg = ctx.bg } }); 220 + const content_logo = 221 + \\ 222 + \\░█▀▄░█▀█░█░█░░░█▀▀░█▀█░█▀█░▀█▀░█▀▀░█▀█░▀█▀ 223 + \\░█▀▄░█░█░█▄█░░░█░░░█░█░█░█░░█░░█▀▀░█░█░░█░ 224 + \\░▀░▀░▀▀▀░▀░▀░░░▀▀▀░▀▀▀░▀░▀░░▀░░▀▀▀░▀░▀░░▀░ 225 + ; 226 + const content_segs: []const vaxis.Cell.Segment = &.{ 227 + .{ 228 + .text = ctx.row, 229 + .style = .{ .bg = ctx.bg }, 230 + }, 231 + .{ 232 + .text = content_logo, 233 + .style = .{ .bg = ctx.bg }, 234 + }, 235 + }; 236 + _ = try see_win.print(content_segs, .{}); 237 + return see_win.height; 238 + } 239 + }.see; 240 + loop.postEvent(.table_upd); 187 241 } 188 242 189 243 // Sections ··· 200 254 .height = .{ .limit = win.height / top_div }, 201 255 }); 202 256 for (title_segs[0..]) |*title_seg| 203 - title_seg.*.style.bg = if (active == .top) selected_bg else other_bg; 257 + title_seg.style.bg = if (active == .top) selected_bg else other_bg; 204 258 top_bar.fill(.{ .style = .{ 205 259 .bg = if (active == .top) selected_bg else other_bg, 206 260 } });
+39 -25
src/widgets/Table.zig
··· 19 19 20 20 /// Active status of the Table. 21 21 active: bool = false, 22 + /// Active Content Callback Function. 23 + /// If available, this will be called to vertically expand the active row with additional info. 24 + active_content_fn: ?*const fn(*vaxis.Window, *const anyopaque) anyerror!usize = null, 25 + /// Active Content Context 26 + /// This will be provided to the `active_content` callback when called. 27 + active_ctx: *const anyopaque = &{}, 28 + /// Y Offset for rows beyond the Active Content. 29 + /// (This will be calculated automatically) 30 + active_y_off: usize = 0, 22 31 23 32 /// The Background Color for the Active Row and Column Header. 24 33 selected_bg: vaxis.Cell.Color, ··· 37 46 y_off: usize = 0, 38 47 39 48 /// Column Width 40 - <<<<<<< HEAD 41 - /// Note, this should be treated as Read Only. The Column Width will be calculated during `drawTable()`. 42 - col_width: ?usize = 0, 43 - ======= 44 49 /// Note, if this is left `null` the Column Width will be dynamically calculated during `drawTable()`. 45 50 //col_width: ?usize = null, 46 51 col_width: WidthStyle = .dynamic_fill, ··· 56 61 static_all: usize, 57 62 /// Statically set individual Column Widths to specific values. 58 63 static_individual: []const usize, 59 - >>>>>>> 7918b49 (widgets(table): implemented customizable column widths) 60 64 }; 61 65 62 66 /// Draw a Table for the TUI. ··· 136 140 .{ .limit = win.height }, 137 141 ); 138 142 139 - if (table_ctx.col > headers.len - 1) table_ctx.*.col = headers.len - 1; 143 + if (table_ctx.col > headers.len - 1) table_ctx.col = headers.len - 1; 140 144 var col_start: usize = 0; 141 145 for (headers[0..], 0..) |hdr_txt, idx| { 142 146 const col_width = try calcColWidth( ··· 149 153 const hdr_bg = 150 154 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; 151 155 const hdr_win = table_win.child(.{ 152 - //.x_off = idx * col_width, 153 156 .x_off = col_start, 154 157 .y_off = 0, 155 158 .width = .{ .limit = col_width }, ··· 168 171 _ = try hdr.print(seg[0..], .{ .wrap = .word }); 169 172 } 170 173 171 - const max_items = if (data_items.len > table_win.height -| 1) table_win.height -| 1 else data_items.len; 172 - var end = table_ctx.*.start + max_items; 174 + if (table_ctx.active_content_fn == null) table_ctx.active_y_off = 0; 175 + const max_items = 176 + if (data_items.len > table_win.height -| 1) table_win.height -| 1 177 + else data_items.len; 178 + var end = table_ctx.start + max_items; 179 + if (table_ctx.row + table_ctx.active_y_off >= end -| 1) 180 + end -|= table_ctx.active_y_off; 173 181 if (end > data_items.len) end = data_items.len; 174 - table_ctx.*.start = tableStart: { 182 + table_ctx.start = tableStart: { 175 183 if (table_ctx.row == 0) 176 184 break :tableStart 0; 177 185 if (table_ctx.row < table_ctx.start) 178 186 break :tableStart table_ctx.start - (table_ctx.start - table_ctx.row); 179 187 if (table_ctx.row >= data_items.len - 1) 180 - table_ctx.*.row = data_items.len - 1; 181 - if (table_ctx.row >= end) 188 + table_ctx.row = data_items.len - 1; 189 + if (table_ctx.row >= end) 182 190 break :tableStart table_ctx.start + (table_ctx.row - end + 1); 183 191 break :tableStart table_ctx.start; 184 192 }; 185 - end = table_ctx.*.start + max_items; 193 + end = table_ctx.start + max_items; 194 + if (table_ctx.row + table_ctx.active_y_off >= end -| 1) 195 + end -|= table_ctx.active_y_off; 186 196 if (end > data_items.len) end = data_items.len; 187 - for (data_items[table_ctx.start..end], 0..) |data, idx| { 197 + table_ctx.active_y_off = 0; 198 + for (data_items[table_ctx.start..end], 0..) |data, row| { 188 199 const row_bg = rowBG: { 189 - if (table_ctx.active and table_ctx.start + idx == table_ctx.row) 200 + if (table_ctx.active and table_ctx.start + row == table_ctx.row) 190 201 break :rowBG table_ctx.active_bg; 191 202 if (table_ctx.sel_rows) |rows| { 192 - if (mem.indexOfScalar(usize, rows, table_ctx.start + idx) != null) break :rowBG table_ctx.selected_bg; 203 + if (mem.indexOfScalar(usize, rows, table_ctx.start + row) != null) break :rowBG table_ctx.selected_bg; 193 204 } 194 - if (idx % 2 == 0) break :rowBG table_ctx.row_bg_1; 205 + if (row % 2 == 0) break :rowBG table_ctx.row_bg_1; 195 206 break :rowBG table_ctx.row_bg_2; 196 207 }; 197 - 198 - const row_win = table_win.initChild( 199 - 0, 200 - 1 + idx, 201 - .{ .limit = table_win.width }, 202 - .{ .limit = 1 }, 203 - ); 208 + var row_win = table_win.child(.{ 209 + .x_off = 0, 210 + .y_off = 1 + row + table_ctx.active_y_off, 211 + .width = .{ .limit = table_win.width }, 212 + .height = .{ .limit = 1 }, 213 + }); 214 + if (table_ctx.start + row == table_ctx.row) { 215 + table_ctx.active_y_off = if (table_ctx.active_content_fn) |content| try content(&row_win, table_ctx.active_ctx) else 0; 216 + //if (table_ctx.row + table_ctx.active_y_off >= end) 217 + // try drawTable(alloc, win, headers, data_list, table_ctx); 218 + } 204 219 const DataT = @TypeOf(data); 205 220 col_start = 0; 206 221 const item_fields = meta.fields(DataT); ··· 215 230 const item = @field(data, item_field.name); 216 231 const ItemT = @TypeOf(item); 217 232 const item_win = row_win.child(.{ 218 - //.x_off = item_idx * col_width, 219 233 .x_off = col_start, 220 234 .y_off = 0, 221 235 .width = .{ .limit = col_width },