feat(container): negative layout padding
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Has been cancelled
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Has been cancelled
Negative paddings use the current size to calculate the padding from the opposite orientation. For a given dimension (horizontal or vertical) if the size is `30` a padding of `5` would be equivalent to a padding of `-25`. This enables to describe the size of the container using the padding property of the `Layout` and gives users more freedom to describe different layouts.
This commit is contained in:
@@ -195,6 +195,33 @@ pub const Rectangle = packed struct {
|
|||||||
}, &container, @import("test/container/rectangle_with_parent_padding.zon"));
|
}, &container, @import("test/container/rectangle_with_parent_padding.zon"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "fill color padding to show parent fill (negative padding)" {
|
||||||
|
const event = @import("event.zig");
|
||||||
|
const testing = @import("testing.zig");
|
||||||
|
|
||||||
|
var container: Container(event.SystemEvent) = try .init(std.testing.allocator, .{
|
||||||
|
.layout = .{
|
||||||
|
.padding = .{
|
||||||
|
.top = -18,
|
||||||
|
.bottom = -18,
|
||||||
|
.left = -28,
|
||||||
|
.right = -28,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.rectangle = .{ .fill = .green },
|
||||||
|
}, .{});
|
||||||
|
try container.append(try .init(std.testing.allocator, .{
|
||||||
|
.rectangle = .{ .fill = .white },
|
||||||
|
}, .{}));
|
||||||
|
try container.append(try .init(std.testing.allocator, .{}, .{}));
|
||||||
|
defer container.deinit();
|
||||||
|
|
||||||
|
try testing.expectContainerScreen(.{
|
||||||
|
.y = 20,
|
||||||
|
.x = 30,
|
||||||
|
}, &container, @import("test/container/rectangle_with_parent_padding.zon"));
|
||||||
|
}
|
||||||
|
|
||||||
test "fill color spacer with padding" {
|
test "fill color spacer with padding" {
|
||||||
const event = @import("event.zig");
|
const event = @import("event.zig");
|
||||||
const testing = @import("testing.zig");
|
const testing = @import("testing.zig");
|
||||||
@@ -293,23 +320,23 @@ pub const Layout = packed struct {
|
|||||||
direction: enum(u1) { horizontal, vertical } = .horizontal,
|
direction: enum(u1) { horizontal, vertical } = .horizontal,
|
||||||
/// Padding outside of the child elements
|
/// Padding outside of the child elements
|
||||||
padding: packed struct {
|
padding: packed struct {
|
||||||
top: u16 = 0,
|
top: i16 = 0,
|
||||||
bottom: u16 = 0,
|
bottom: i16 = 0,
|
||||||
left: u16 = 0,
|
left: i16 = 0,
|
||||||
right: u16 = 0,
|
right: i16 = 0,
|
||||||
|
|
||||||
/// Create a padding with equivalent padding in all four directions.
|
/// Create a padding with equivalent padding in all four directions.
|
||||||
pub fn all(padding: u16) @This() {
|
pub fn all(padding: i16) @This() {
|
||||||
return .{ .top = padding, .bottom = padding, .left = padding, .right = padding };
|
return .{ .top = padding, .bottom = padding, .left = padding, .right = padding };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a padding with equivalent padding in the left and right directions; others directions remain the default value.
|
/// Create a padding with equivalent padding in the left and right directions; others directions remain the default value.
|
||||||
pub fn horizontal(padding: u16) @This() {
|
pub fn horizontal(padding: i16) @This() {
|
||||||
return .{ .left = padding, .right = padding };
|
return .{ .left = padding, .right = padding };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a padding with equivalent padding in the top and bottom directions; others directions remain the default value.
|
/// Create a padding with equivalent padding in the top and bottom directions; others directions remain the default value.
|
||||||
pub fn vertical(padding: u16) @This() {
|
pub fn vertical(padding: i16) @This() {
|
||||||
return .{ .top = padding, .bottom = padding };
|
return .{ .top = padding, .bottom = padding };
|
||||||
}
|
}
|
||||||
} = .{},
|
} = .{},
|
||||||
@@ -326,6 +353,11 @@ pub const Layout = packed struct {
|
|||||||
} = .line,
|
} = .line,
|
||||||
} = .{},
|
} = .{},
|
||||||
|
|
||||||
|
/// Calculate the absolute offset for the provided `padding` if it is negative to get the absolute padding for the given `size`.
|
||||||
|
pub fn getAbsolutePadding(padding: i16, size: u16) u16 {
|
||||||
|
return if (padding >= 0) @intCast(padding) else size -| @as(u16, @intCast(-padding));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn content(this: @This(), comptime C: type, cells: []Cell, origin: Point, size: Point, children: []const C) void {
|
pub fn content(this: @This(), comptime C: type, cells: []Cell, origin: Point, size: Point, children: []const C) void {
|
||||||
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
|
||||||
|
|
||||||
@@ -609,8 +641,8 @@ pub fn Container(comptime Event: type) type {
|
|||||||
this.element.reposition(origin);
|
this.element.reposition(origin);
|
||||||
|
|
||||||
var offset = origin.add(.{
|
var offset = origin.add(.{
|
||||||
.x = layout.padding.left,
|
.x = Layout.getAbsolutePadding(layout.padding.left, this.size.x),
|
||||||
.y = layout.padding.top,
|
.y = Layout.getAbsolutePadding(layout.padding.top, this.size.y),
|
||||||
});
|
});
|
||||||
|
|
||||||
const sides = this.properties.border.sides;
|
const sides = this.properties.border.sides;
|
||||||
@@ -642,8 +674,8 @@ pub fn Container(comptime Event: type) type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (this.elements.items.len > 0) switch (layout.direction) {
|
if (this.elements.items.len > 0) switch (layout.direction) {
|
||||||
.horizontal => size.x += layout.padding.left + layout.padding.right,
|
.horizontal => size.x += Layout.getAbsolutePadding(layout.padding.left, this.size.x) + Layout.getAbsolutePadding(layout.padding.right, this.size.x),
|
||||||
.vertical => size.y += layout.padding.top + layout.padding.bottom,
|
.vertical => size.y += Layout.getAbsolutePadding(layout.padding.top, this.size.y) + Layout.getAbsolutePadding(layout.padding.bottom, this.size.y),
|
||||||
};
|
};
|
||||||
|
|
||||||
const sides = this.properties.border.sides;
|
const sides = this.properties.border.sides;
|
||||||
@@ -691,16 +723,16 @@ pub fn Container(comptime Event: type) type {
|
|||||||
fn grow_resize(this: *@This(), max_size: Point) void {
|
fn grow_resize(this: *@This(), max_size: Point) void {
|
||||||
const layout = this.properties.layout;
|
const layout = this.properties.layout;
|
||||||
var remainder = switch (layout.direction) {
|
var remainder = switch (layout.direction) {
|
||||||
.horizontal => max_size.x -| (layout.padding.left + layout.padding.right),
|
.horizontal => max_size.x -| (Layout.getAbsolutePadding(layout.padding.left, this.size.x) + Layout.getAbsolutePadding(layout.padding.right, this.size.x)),
|
||||||
.vertical => max_size.y -| (layout.padding.top + layout.padding.bottom),
|
.vertical => max_size.y -| (Layout.getAbsolutePadding(layout.padding.top, this.size.y) + Layout.getAbsolutePadding(layout.padding.bottom, this.size.y)),
|
||||||
};
|
};
|
||||||
remainder -|= layout.gap * @as(u16, @truncate(this.elements.items.len -| 1));
|
remainder -|= layout.gap * @as(u16, @truncate(this.elements.items.len -| 1));
|
||||||
|
|
||||||
if (layout.separator.enabled) remainder -|= @as(u16, @truncate(this.elements.items.len -| 1));
|
if (layout.separator.enabled) remainder -|= @as(u16, @truncate(this.elements.items.len -| 1));
|
||||||
|
|
||||||
var available = switch (layout.direction) {
|
var available = switch (layout.direction) {
|
||||||
.horizontal => max_size.y -| (layout.padding.top + layout.padding.bottom),
|
.horizontal => max_size.y -| (Layout.getAbsolutePadding(layout.padding.top, this.size.y) + Layout.getAbsolutePadding(layout.padding.bottom, this.size.y)),
|
||||||
.vertical => max_size.x -| (layout.padding.left + layout.padding.right),
|
.vertical => max_size.x -| (Layout.getAbsolutePadding(layout.padding.left, this.size.x) + Layout.getAbsolutePadding(layout.padding.right, this.size.x)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const sides = this.properties.border.sides;
|
const sides = this.properties.border.sides;
|
||||||
@@ -836,6 +868,7 @@ pub fn Container(comptime Event: type) type {
|
|||||||
|
|
||||||
pub fn resize(this: *@This(), size: Point) void {
|
pub fn resize(this: *@This(), size: Point) void {
|
||||||
// NOTE assume that this function is only called for the root `Container`
|
// NOTE assume that this function is only called for the root `Container`
|
||||||
|
this.size = size;
|
||||||
const fit_size = this.fit_resize();
|
const fit_size = this.fit_resize();
|
||||||
// if (fit_size.y > size.y or fit_size.x > size.x) @panic("error: cannot render in available space");
|
// if (fit_size.y > size.y or fit_size.x > size.x) @panic("error: cannot render in available space");
|
||||||
switch (this.properties.size.grow) {
|
switch (this.properties.size.grow) {
|
||||||
|
|||||||
Reference in New Issue
Block a user