this repo has no description
1const std = @import("std");
2const vaxis = @import("../main.zig");
3
4const Allocator = std.mem.Allocator;
5
6const vxfw = @import("vxfw.zig");
7
8const SizedBox = @This();
9
10child: vxfw.Widget,
11size: vxfw.Size,
12
13pub fn widget(self: *const SizedBox) vxfw.Widget {
14 return .{
15 .userdata = @constCast(self),
16 .drawFn = typeErasedDrawFn,
17 };
18}
19
20fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) Allocator.Error!vxfw.Surface {
21 const self: *const SizedBox = @ptrCast(@alignCast(ptr));
22 const max: vxfw.MaxSize = .{
23 .width = if (ctx.max.width) |max_w| max_w else self.size.width,
24 .height = if (ctx.max.height) |max_h| max_h else self.size.height,
25 };
26 const min: vxfw.Size = .{
27 .width = @min(@max(ctx.min.width, self.size.width), max.width.?),
28 .height = @min(@max(ctx.min.height, self.size.height), max.height.?),
29 };
30 return self.child.draw(ctx.withConstraints(min, max));
31}
32
33test SizedBox {
34 // Create a test widget that saves the constraints it was given
35 const TestWidget = struct {
36 min: vxfw.Size,
37 max: vxfw.MaxSize,
38
39 pub fn widget(self: *@This()) vxfw.Widget {
40 return .{
41 .userdata = self,
42 .drawFn = @This().typeErasedDrawFn,
43 };
44 }
45
46 fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface {
47 const self: *@This() = @ptrCast(@alignCast(ptr));
48 self.min = ctx.min;
49 self.max = ctx.max;
50 return .{
51 .size = ctx.min,
52 .widget = self.widget(),
53 .buffer = &.{},
54 .children = &.{},
55 };
56 }
57 };
58
59 // Boiler plate draw context
60 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
61 defer arena.deinit();
62 const ucd = try vaxis.Unicode.init(arena.allocator());
63 vxfw.DrawContext.init(&ucd, .unicode);
64
65 var draw_ctx: vxfw.DrawContext = .{
66 .arena = arena.allocator(),
67 .min = .{},
68 .max = .{ .width = 16, .height = 16 },
69 .cell_size = .{ .width = 10, .height = 20 },
70 };
71
72 var test_widget: TestWidget = .{ .min = .{}, .max = .{} };
73
74 // SizedBox tries to draw the child widget at the specified size. It will shrink to fit within
75 // constraints
76 const sized_box: SizedBox = .{
77 .child = test_widget.widget(),
78 .size = .{ .width = 10, .height = 10 },
79 };
80
81 const box_widget = sized_box.widget();
82 {
83 const result = try box_widget.draw(draw_ctx);
84 // The sized box is smaller than the constraints, so we should be the desired size
85 try std.testing.expectEqual(sized_box.size, result.size);
86 }
87
88 {
89 draw_ctx.max.height = 8;
90 const result = try box_widget.draw(draw_ctx);
91 // The sized box is smaller than the constraints, so we should be that size
92 try std.testing.expectEqual(@as(vxfw.Size, .{ .width = 10, .height = 8 }), result.size);
93 }
94
95 draw_ctx.max.width = 8;
96 _ = try box_widget.draw(draw_ctx);
97 // The sized box is smaller than the constraints, so we should be that size
98 try std.testing.expectEqual(@as(vxfw.Size, .{ .width = 8, .height = 8 }), test_widget.min);
99 try std.testing.expectEqual(@as(vxfw.Size, .{ .width = 8, .height = 8 }), test_widget.max.size());
100}
101
102test "refAllDecls" {
103 std.testing.refAllDecls(@This());
104}