feat(container): introduce fixed_size property for fixed sizing of Containers
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 42s

Moved min_size property from `Container` to the `Scrollable` element,
where it is only used anyway.
This commit is contained in:
2025-03-01 11:56:14 +01:00
parent 35ebe31008
commit 8a7ce78aaf
3 changed files with 79 additions and 38 deletions

View File

@@ -562,7 +562,7 @@ pub fn Container(comptime Event: type) type {
border: Border = .{},
rectangle: Rectangle = .{},
layout: Layout = .{},
min_size: Size = .{},
fixed_size: Size = .{},
};
pub fn init(
@@ -590,24 +590,6 @@ pub fn Container(comptime Event: type) type {
try this.elements.append(element);
}
pub fn minSize(this: @This()) Size {
var size: Size = .{};
const len: u16 = @truncate(this.elements.items.len);
if (len > 0) {
for (this.elements.items) |element| {
size = size.add(element.minSize());
}
var gap = this.properties.layout.gap;
if (this.properties.layout.separator.enabled) gap += 1;
switch (this.properties.layout.direction) {
.horizontal => size.cols += gap * (len - 1),
.vertical => size.rows += gap * (len - 1),
}
}
return size.max(this.properties.min_size);
}
pub fn handle(this: *@This(), event: Event) !void {
switch (event) {
.resize => |size| resize: {
@@ -618,11 +600,32 @@ pub fn Container(comptime Event: type) type {
size.rows,
});
this.size = size;
if (this.properties.fixed_size.cols > 0 and size.cols < this.properties.fixed_size.cols) return error.TooSmall;
if (this.properties.fixed_size.rows > 0 and size.rows < this.properties.fixed_size.rows) return error.TooSmall;
try this.element.handle(event);
if (this.elements.items.len == 0) break :resize;
const layout = this.properties.layout;
var fixed_size_elements: u16 = 0;
var fixed_size: Size = .{};
for (this.elements.items) |element| {
switch (layout.direction) {
.horizontal => if (element.properties.fixed_size.cols > 0) {
fixed_size_elements += 1;
},
.vertical => if (element.properties.fixed_size.rows > 0) {
fixed_size_elements += 1;
},
}
fixed_size = fixed_size.add(element.properties.fixed_size);
}
// check if the available screen is large enough
switch (layout.direction) {
.horizontal => if (fixed_size.cols > size.cols) return error.TooSmall,
.vertical => if (fixed_size.rows > size.rows) return error.TooSmall,
}
const sides = this.properties.border.sides;
const padding = layout.padding;
var gap = layout.gap;
@@ -630,18 +633,28 @@ pub fn Container(comptime Event: type) type {
const len: u16 = @truncate(this.elements.items.len);
const element_cols = blk: {
var cols = size.cols - gap * (len - 1);
var cols = size.cols - fixed_size.cols - gap * (len - 1);
if (sides.left) cols -= 1;
if (sides.right) cols -= 1;
cols -= padding.left + padding.right;
break :blk @divTrunc(cols, len);
if (fixed_size_elements == len) break :blk 0;
if (fixed_size_elements == 0) {
break :blk @divTrunc(cols, len);
} else {
break :blk @divTrunc(cols, len - fixed_size_elements);
}
};
const element_rows = blk: {
var rows = size.rows - gap * (len - 1);
var rows = size.rows - fixed_size.rows - gap * (len - 1);
if (sides.top) rows -= 1;
if (sides.bottom) rows -= 1;
rows -= padding.top + padding.bottom;
break :blk @divTrunc(rows, len);
if (fixed_size_elements == len) break :blk 0;
if (fixed_size_elements == 0) {
break :blk @divTrunc(rows, len);
} else {
break :blk @divTrunc(rows, len - fixed_size_elements);
}
};
var offset: u16 = switch (layout.direction) {
.horizontal => padding.left,
@@ -649,18 +662,28 @@ pub fn Container(comptime Event: type) type {
};
var overflow = switch (layout.direction) {
.horizontal => blk: {
var cols = size.cols - gap * (len - 1);
var cols = size.cols - fixed_size.cols - gap * (len - 1);
if (sides.left) cols -= 1;
if (sides.right) cols -= 1;
cols -= padding.left + padding.right;
break :blk cols - element_cols * len;
if (fixed_size_elements == len) break :blk 0;
if (fixed_size_elements == 0) {
break :blk cols - element_cols * len;
} else {
break :blk cols - element_cols * (len - fixed_size_elements);
}
},
.vertical => blk: {
var rows = size.rows - gap * (len - 1);
var rows = size.rows - fixed_size.rows - gap * (len - 1);
if (sides.top) rows -= 1;
if (sides.bottom) rows -= 1;
rows -= padding.top + padding.bottom;
break :blk rows - element_rows * len;
if (fixed_size_elements == len) break :blk 0;
if (fixed_size_elements == 0) {
break :blk rows - element_rows * len;
} else {
break :blk rows - element_rows * (len - fixed_size_elements);
}
},
};
@@ -668,7 +691,11 @@ pub fn Container(comptime Event: type) type {
var element_size: Size = undefined;
switch (layout.direction) {
.horizontal => {
var cols = element_cols;
// TODO: this should not always be the max size property!
var cols = blk: {
if (element.properties.fixed_size.cols > 0) break :blk element.properties.fixed_size.cols;
break :blk element_cols;
};
if (overflow > 0) {
overflow -|= 1;
cols += 1;
@@ -692,7 +719,10 @@ pub fn Container(comptime Event: type) type {
offset += cols;
},
.vertical => {
var rows = element_rows;
var rows = blk: {
if (element.properties.fixed_size.rows > 0) break :blk element.properties.fixed_size.rows;
break :blk element_rows;
};
if (overflow > 0) {
overflow -|= 1;
rows += 1;