this repo has no description
13
fork

Configure Feed

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

vxfw: add Center widget

Center widget centers a child widget within itself

+119
+118
src/vxfw/Center.zig
··· 1 + const std = @import("std"); 2 + const vaxis = @import("../main.zig"); 3 + 4 + const Allocator = std.mem.Allocator; 5 + 6 + const vxfw = @import("vxfw.zig"); 7 + 8 + const Center = @This(); 9 + 10 + child: vxfw.Widget, 11 + 12 + pub fn widget(self: *const Center) vxfw.Widget { 13 + return .{ 14 + .userdata = @constCast(self), 15 + .eventHandler = typeErasedEventHandler, 16 + .drawFn = typeErasedDrawFn, 17 + }; 18 + } 19 + 20 + fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void { 21 + const self: *const Center = @ptrCast(@alignCast(ptr)); 22 + return self.child.handleEvent(ctx, event); 23 + } 24 + 25 + fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 26 + const self: *const Center = @ptrCast(@alignCast(ptr)); 27 + return self.draw(ctx); 28 + } 29 + 30 + /// Cannot have unbounded constraints 31 + pub fn draw(self: *const Center, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 32 + const child_ctx = ctx.withConstraints(.{ .width = 0, .height = 0 }, ctx.max); 33 + const max_size = ctx.max.size(); 34 + const child = try self.child.draw(child_ctx); 35 + 36 + const x = (max_size.width - child.size.width) / 2; 37 + const y = (max_size.height - child.size.height) / 2; 38 + 39 + const children = try ctx.arena.alloc(vxfw.SubSurface, 1); 40 + children[0] = .{ 41 + .origin = .{ .col = x, .row = y }, 42 + .z_index = 0, 43 + .surface = child, 44 + }; 45 + 46 + return .{ 47 + .size = max_size, 48 + .widget = self.widget(), 49 + .buffer = &.{}, 50 + .children = children, 51 + }; 52 + } 53 + 54 + test Center { 55 + const Text = @import("Text.zig"); 56 + // Will be height=1, width=3 57 + const text: Text = .{ .text = "abc" }; 58 + 59 + const center: Center = .{ .child = text.widget() }; 60 + 61 + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); 62 + defer arena.deinit(); 63 + const ucd = try vaxis.Unicode.init(arena.allocator()); 64 + vxfw.DrawContext.init(&ucd, .unicode); 65 + 66 + { 67 + // Center expands to the max size. It must therefore have non-null max width and max height. 68 + // These values are asserted in draw 69 + const ctx: vxfw.DrawContext = .{ 70 + .arena = arena.allocator(), 71 + .min = .{}, 72 + .max = .{ .width = 10, .height = 10 }, 73 + }; 74 + 75 + const surface = try center.draw(ctx); 76 + // Center does not produce any drawable cells 77 + try std.testing.expectEqual(0, surface.buffer.len); 78 + // Center has 1 child 79 + try std.testing.expectEqual(1, surface.children.len); 80 + // Center is the max size 81 + try std.testing.expectEqual(surface.size, ctx.max.size()); 82 + const child = surface.children[0]; 83 + // The child is 1x3 84 + try std.testing.expectEqual(3, child.surface.size.width); 85 + try std.testing.expectEqual(1, child.surface.size.height); 86 + // A centered 1x3 in 10x10 should be at origin 3, 4. The bias is toward the top left corner 87 + try std.testing.expectEqual(4, child.origin.row); 88 + try std.testing.expectEqual(3, child.origin.col); 89 + } 90 + { 91 + // Center expands to the max size. It must therefore have non-null max width and max height. 92 + // These values are asserted in draw 93 + const ctx: vxfw.DrawContext = .{ 94 + .arena = arena.allocator(), 95 + .min = .{}, 96 + .max = .{ .width = 5, .height = 3 }, 97 + }; 98 + 99 + const surface = try center.draw(ctx); 100 + // Center does not produce any drawable cells 101 + try std.testing.expectEqual(0, surface.buffer.len); 102 + // Center has 1 child 103 + try std.testing.expectEqual(1, surface.children.len); 104 + // Center is the max size 105 + try std.testing.expectEqual(surface.size, ctx.max.size()); 106 + const child = surface.children[0]; 107 + // The child is 1x3 108 + try std.testing.expectEqual(3, child.surface.size.width); 109 + try std.testing.expectEqual(1, child.surface.size.height); 110 + // A centered 1x3 in 3x5 should be at origin 1, 1. This is a perfectly centered child 111 + try std.testing.expectEqual(1, child.origin.row); 112 + try std.testing.expectEqual(1, child.origin.col); 113 + } 114 + } 115 + 116 + test "refAllDecls" { 117 + std.testing.refAllDecls(@This()); 118 + }
+1
src/vxfw/vxfw.zig
··· 11 11 pub const App = @import("App.zig"); 12 12 13 13 // Widgets 14 + pub const Center = @import("Center.zig"); 14 15 pub const ListView = @import("ListView.zig"); 15 16 pub const RichText = @import("RichText.zig"); 16 17 pub const Text = @import("Text.zig");