feat(element/scrollable): mouse support for scrollbar interaction
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 55s

Fix an issue with the scrollbar contents to work proper with statically
defined `Container` sizes through its `Properties` sizing option.
This commit is contained in:
2025-11-05 22:08:35 +01:00
parent 8ebab702ac
commit ad32e46bc9

View File

@@ -284,6 +284,12 @@ pub fn Scrollable(Model: type, Event: type) type {
container_size.x -= if (this.configuration.x_axis) 1 else 0;
container_size.y -= if (this.configuration.y_axis) 1 else 0;
}
// NOTE this call is at this point required as the container size
// may also be defined through the `Container`'s `Properties`, which
// may define a dimension (for static layouts)
this.container.resize(container_size); // notify the container about the minimal size it should have
// update the calculated size of the container
container_size = this.container.size;
const new_max_anchor_x = container_size.x -| size.x;
const new_max_anchor_y = container_size.y -| size.y;
@@ -293,7 +299,6 @@ pub fn Scrollable(Model: type, Event: type) type {
if (new_max_anchor_y < last_max_anchor_y and this.anchor.y > new_max_anchor_y) this.anchor.y = new_max_anchor_y;
this.size = size;
this.container.resize(container_size); // notify the container about the minimal size it should have
this.container_size = container_size;
}
@@ -342,20 +347,37 @@ pub fn Scrollable(Model: type, Event: type) type {
}
},
.mouse => |mouse| switch (mouse.button) {
Mouse.Button.wheel_up => if (this.container_size.y > this.size.y) {
.wheel_up => if (this.container_size.y > this.size.y) {
this.anchor.y -|= 1;
},
Mouse.Button.wheel_down => if (this.container_size.y > this.size.y) {
.wheel_down => if (this.container_size.y > this.size.y) {
const max_anchor_y = this.container_size.y -| this.size.y;
this.anchor.y = @min(this.anchor.y + 1, max_anchor_y);
},
Mouse.Button.wheel_left => if (this.container_size.x > this.size.x) {
.wheel_left => if (this.container_size.x > this.size.x) {
this.anchor.x -|= 1;
},
Mouse.Button.wheel_right => if (this.container_size.x > this.size.x) {
.wheel_right => if (this.container_size.x > this.size.x) {
const max_anchor_x = this.container_size.x -| this.size.x;
this.anchor.x = @min(this.anchor.x + 1, max_anchor_x);
},
.left => {
// horizontal (-) scrollbar click
if (this.configuration.y_axis and mouse.y == this.size.y - 1) {
const ratio = @as(f32, @floatFromInt(mouse.x)) / @as(f32, @floatFromInt(this.size.x));
const value: u16 = @intFromFloat(ratio * @as(f32, @floatFromInt(this.container_size.x)));
const max_anchor_x = this.container_size.x -| this.size.x;
this.anchor.x = @min(value, max_anchor_x);
}
// vertical (|) scrollbar click
if (this.configuration.x_axis and mouse.x == this.size.x - 1) {
const ratio = @as(f32, @floatFromInt(mouse.y)) / @as(f32, @floatFromInt(this.size.y));
const value: u16 = @intFromFloat(ratio * @as(f32, @floatFromInt(this.container_size.y)));
const max_anchor_y = this.container_size.y -| this.size.y;
this.anchor.y = @min(value, max_anchor_y);
}
},
else => try this.container.handle(model, .{
.mouse = .{
.x = mouse.x + this.anchor.x,