this repo has no description
13
fork

Configure Feed

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

vxfw: add Padding widget

+149
+148
src/vxfw/Padding.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 Padding = @This(); 9 + const PadValues = struct { 10 + left: u16 = 0, 11 + right: u16 = 0, 12 + top: u16 = 0, 13 + bottom: u16 = 0, 14 + }; 15 + 16 + child: vxfw.Widget, 17 + padding: PadValues = .{}, 18 + 19 + /// Vertical padding will be divided by 2 to approximate equal padding 20 + pub fn all(padding: u16) PadValues { 21 + return .{ 22 + .left = padding, 23 + .right = padding, 24 + .top = padding / 2, 25 + .bottom = padding / 2, 26 + }; 27 + } 28 + 29 + pub fn horizontal(padding: u16) PadValues { 30 + return .{ 31 + .left = padding, 32 + .right = padding, 33 + }; 34 + } 35 + 36 + pub fn vertical(padding: u16) PadValues { 37 + return .{ 38 + .top = padding, 39 + .bottom = padding, 40 + }; 41 + } 42 + 43 + pub fn widget(self: *const Padding) vxfw.Widget { 44 + return .{ 45 + .userdata = @constCast(self), 46 + .eventHandler = typeErasedEventHandler, 47 + .drawFn = typeErasedDrawFn, 48 + }; 49 + } 50 + 51 + fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void { 52 + const self: *const Padding = @ptrCast(@alignCast(ptr)); 53 + return self.child.handleEvent(ctx, event); 54 + } 55 + 56 + fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 57 + const self: *const Padding = @ptrCast(@alignCast(ptr)); 58 + return self.draw(ctx); 59 + } 60 + 61 + pub fn draw(self: *const Padding, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface { 62 + const pad = self.padding; 63 + if (pad.left > 0 or pad.right > 0) 64 + std.debug.assert(ctx.max.width != null); 65 + if (pad.top > 0 or pad.bottom > 0) 66 + std.debug.assert(ctx.max.height != null); 67 + const inner_min: vxfw.Size = .{ 68 + .width = ctx.min.width -| (pad.right + pad.left), 69 + .height = ctx.min.height -| (pad.top + pad.bottom), 70 + }; 71 + 72 + const max_width: ?u16 = if (ctx.max.width) |max| 73 + max -| (pad.right + pad.left) 74 + else 75 + null; 76 + const max_height: ?u16 = if (ctx.max.height) |max| 77 + max -| (pad.top + pad.bottom) 78 + else 79 + null; 80 + 81 + const inner_max: vxfw.MaxSize = .{ 82 + .width = max_width, 83 + .height = max_height, 84 + }; 85 + 86 + const child_surface = try self.child.draw(ctx.withConstraints(inner_min, inner_max)); 87 + 88 + const children = try ctx.arena.alloc(vxfw.SubSurface, 1); 89 + children[0] = .{ 90 + .surface = child_surface, 91 + .z_index = 0, 92 + .origin = .{ .row = pad.top, .col = pad.left }, 93 + }; 94 + 95 + const size = .{ 96 + .width = child_surface.size.width + (pad.right + pad.left), 97 + .height = child_surface.size.height + (pad.top + pad.bottom), 98 + }; 99 + 100 + // Create the padding surface 101 + return .{ 102 + .size = size, 103 + .widget = self.widget(), 104 + .buffer = &.{}, 105 + .children = children, 106 + }; 107 + } 108 + 109 + test Padding { 110 + const Text = @import("Text.zig"); 111 + // Will be height=1, width=3 112 + const text: Text = .{ .text = "abc" }; 113 + 114 + const padding: Padding = .{ 115 + .child = text.widget(), 116 + .padding = horizontal(1), 117 + }; 118 + 119 + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); 120 + defer arena.deinit(); 121 + const ucd = try vaxis.Unicode.init(arena.allocator()); 122 + vxfw.DrawContext.init(&ucd, .unicode); 123 + 124 + // Center expands to the max size. It must therefore have non-null max width and max height. 125 + // These values are asserted in draw 126 + const ctx: vxfw.DrawContext = .{ 127 + .arena = arena.allocator(), 128 + .min = .{}, 129 + .max = .{ .width = 10, .height = 10 }, 130 + }; 131 + 132 + const pad_widget = padding.widget(); 133 + 134 + const surface = try pad_widget.draw(ctx); 135 + // Padding does not produce any drawable cells 136 + try std.testing.expectEqual(0, surface.buffer.len); 137 + // Padding has 1 child 138 + try std.testing.expectEqual(1, surface.children.len); 139 + const child = surface.children[0]; 140 + // Padding is the child size + padding 141 + try std.testing.expectEqual(child.surface.size.width + 2, surface.size.width); 142 + try std.testing.expectEqual(0, child.origin.row); 143 + try std.testing.expectEqual(1, child.origin.col); 144 + } 145 + 146 + test "refAllDecls" { 147 + std.testing.refAllDecls(@This()); 148 + }
+1
src/vxfw/vxfw.zig
··· 16 16 pub const FlexColumn = @import("FlexColumn.zig"); 17 17 pub const FlexRow = @import("FlexRow.zig"); 18 18 pub const ListView = @import("ListView.zig"); 19 + pub const Padding = @import("Padding.zig"); 19 20 pub const RichText = @import("RichText.zig"); 20 21 pub const Text = @import("Text.zig"); 21 22 pub const TextField = @import("TextField.zig");