fix(container): rendering scrollable elements with separators
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 23s

Added corresponding test cases to test the corresponding rendering of
scrollable elements.
This commit is contained in:
2025-02-27 17:02:16 +01:00
parent 53b69f034c
commit 3b6848f845
7 changed files with 167 additions and 4 deletions

View File

@@ -346,8 +346,8 @@ pub const Layout = packed struct {
for (0..children.len - 1) |idx| {
const child = children[idx];
const anchor = switch (this.direction) {
.horizontal => (child.size.anchor.row * size.cols) + child.size.anchor.col + child.size.cols + gap,
.vertical => ((child.size.anchor.row + child.size.rows + gap) * size.cols) + child.size.anchor.col,
.horizontal => ((child.size.anchor.row -| size.anchor.row) * size.cols) + child.size.anchor.col + child.size.cols + gap -| size.anchor.col,
.vertical => ((child.size.anchor.row + child.size.rows + gap -| size.anchor.row) * size.cols) + child.size.anchor.col -| size.anchor.col,
};
switch (this.direction) {

View File

@@ -164,3 +164,156 @@ pub fn Scrollable(Event: type) type {
}
};
}
// TODO: nested scrollable `Container`s?'
// TODO: reaction only for when the event is actually pushed to the corresponding `Container` rendered container
test "scrollable vertical" {
const event = @import("event.zig");
const testing = @import("testing.zig");
const size: Size = .{
.rows = 20,
.cols = 30,
};
var box: Container(event.SystemEvent) = try .init(std.testing.allocator, .{
.border = .{
.sides = .all,
.color = .red,
},
.layout = .{
.separator = .{
.enabled = true,
.color = .red,
},
.direction = .vertical,
.padding = .all(1),
},
.min_size = .{ .rows = size.rows + 15 },
}, .{});
try box.append(try .init(std.testing.allocator, .{
.rectangle = .{ .fill = .grey },
}, .{}));
try box.append(try .init(std.testing.allocator, .{
.rectangle = .{ .fill = .grey },
}, .{}));
defer box.deinit();
var scrollable: Scrollable(event.SystemEvent) = .init(box);
var container: Container(event.SystemEvent) = try .init(std.testing.allocator, .{
.border = .{
.color = .green,
.sides = .vertical,
},
}, scrollable.element());
defer container.deinit();
const allocator = std.testing.allocator;
var renderer: testing.Renderer = .init(allocator, size);
defer renderer.deinit();
try container.handle(.{ .resize = size });
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.vertical.top.zon"), renderer.screen);
// scroll down 15 times (exactly to the end)
for (0..15) |_| try container.handle(.{
.mouse = .{
.button = .wheel_down,
.kind = .press,
.col = 5,
.row = 5,
},
});
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.vertical.bottom.zon"), renderer.screen);
// further scrolling down will not change anything
try container.handle(.{
.mouse = .{
.button = .wheel_down,
.kind = .press,
.col = 5,
.row = 5,
},
});
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.vertical.bottom.zon"), renderer.screen);
}
test "scrollable horizontal" {
const event = @import("event.zig");
const testing = @import("testing.zig");
const size: Size = .{
.rows = 20,
.cols = 30,
};
var box: Container(event.SystemEvent) = try .init(std.testing.allocator, .{
.border = .{
.sides = .all,
.color = .red,
},
.layout = .{
.separator = .{
.enabled = true,
.color = .red,
},
.direction = .horizontal,
.padding = .all(1),
},
.min_size = .{ .cols = size.cols + 15 },
}, .{});
try box.append(try .init(std.testing.allocator, .{
.rectangle = .{ .fill = .grey },
}, .{}));
try box.append(try .init(std.testing.allocator, .{
.rectangle = .{ .fill = .grey },
}, .{}));
defer box.deinit();
var scrollable: Scrollable(event.SystemEvent) = .init(box);
var container: Container(event.SystemEvent) = try .init(std.testing.allocator, .{
.border = .{
.color = .green,
.sides = .horizontal,
},
}, scrollable.element());
defer container.deinit();
const allocator = std.testing.allocator;
var renderer: testing.Renderer = .init(allocator, size);
defer renderer.deinit();
try container.handle(.{ .resize = size });
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.horizontal.left.zon"), renderer.screen);
// scroll right 15 times (exactly to the end)
for (0..15) |_| try container.handle(.{
.mouse = .{
.button = .wheel_right,
.kind = .press,
.col = 5,
.row = 5,
},
});
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.horizontal.right.zon"), renderer.screen);
// further scrolling right will not change anything
try container.handle(.{
.mouse = .{
.button = .wheel_right,
.kind = .press,
.col = 5,
.row = 5,
},
});
try renderer.render(Container(event.SystemEvent), &container);
try testing.expectEqualCells(renderer.size, @import("test/element/scrollable.horizontal.right.zon"), renderer.screen);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long