mod(element/scrollable): introduce minSize function for Element
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 3m24s
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 3m24s
The minimal required size can the queried from the containing `Element` of the `Container` that is provided to the `Scrollable` to dynamically adjust its size. Currently abritrary nesting is not supported / tested.
This commit is contained in:
@@ -28,7 +28,22 @@ const TextStyles = struct {
|
|||||||
const text = "Example";
|
const text = "Example";
|
||||||
|
|
||||||
pub fn element(this: *@This()) App.Element {
|
pub fn element(this: *@This()) App.Element {
|
||||||
return .{ .ptr = this, .vtable = &.{ .content = content } };
|
return .{
|
||||||
|
.ptr = this,
|
||||||
|
.vtable = &.{
|
||||||
|
.minSize = minSize,
|
||||||
|
.content = content,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minSize(ctx: *anyopaque, size: zterm.Point) zterm.Point {
|
||||||
|
_ = ctx;
|
||||||
|
_ = size;
|
||||||
|
return .{
|
||||||
|
.x = std.meta.fields(zterm.Style.Emphasis).len * TextStyles.text.len,
|
||||||
|
.y = (std.meta.fields(zterm.Color).len - 1) * (std.meta.fields(zterm.Color).len - 2),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
|
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
|
||||||
@@ -102,12 +117,6 @@ pub fn main() !void {
|
|||||||
|
|
||||||
var box = try App.Container.init(allocator, .{
|
var box = try App.Container.init(allocator, .{
|
||||||
.layout = .{ .direction = .vertical },
|
.layout = .{ .direction = .vertical },
|
||||||
.size = .{
|
|
||||||
.dim = .{
|
|
||||||
.x = std.meta.fields(zterm.Style.Emphasis).len * TextStyles.text.len,
|
|
||||||
.y = (std.meta.fields(zterm.Color).len - 1) * (std.meta.fields(zterm.Color).len - 2),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, text_styles.element());
|
}, text_styles.element());
|
||||||
defer box.deinit();
|
defer box.deinit();
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,25 @@ pub fn Element(Model: type, Event: type) type {
|
|||||||
vtable: *const VTable = &.{},
|
vtable: *const VTable = &.{},
|
||||||
|
|
||||||
pub const VTable = struct {
|
pub const VTable = struct {
|
||||||
|
minSize: ?*const fn (ctx: *anyopaque, size: Point) Point = null,
|
||||||
resize: ?*const fn (ctx: *anyopaque, size: Point) void = null,
|
resize: ?*const fn (ctx: *anyopaque, size: Point) void = null,
|
||||||
reposition: ?*const fn (ctx: *anyopaque, origin: Point) void = null,
|
reposition: ?*const fn (ctx: *anyopaque, origin: Point) void = null,
|
||||||
handle: ?*const fn (ctx: *anyopaque, model: *Model, event: Event) anyerror!void = null,
|
handle: ?*const fn (ctx: *anyopaque, model: *Model, event: Event) anyerror!void = null,
|
||||||
content: ?*const fn (ctx: *anyopaque, model: *const Model, cells: []Cell, size: Point) anyerror!void = null,
|
content: ?*const fn (ctx: *anyopaque, model: *const Model, cells: []Cell, size: Point) anyerror!void = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Request the minimal size required for this `Element` the provided
|
||||||
|
/// available *size* can be used as a fallback. This is currently only
|
||||||
|
/// used for `Scrollable` elements, such that the nested element in
|
||||||
|
/// the `Scrollable`'s `Container` can request a minimal size for its
|
||||||
|
/// contents.
|
||||||
|
pub inline fn minSize(this: @This(), size: Point) Point {
|
||||||
|
return if (this.vtable.minSize) |minSize_fn|
|
||||||
|
minSize_fn(this.ptr, size)
|
||||||
|
else
|
||||||
|
size;
|
||||||
|
}
|
||||||
|
|
||||||
/// Resize the corresponding `Element` with the given *size*.
|
/// Resize the corresponding `Element` with the given *size*.
|
||||||
pub inline fn resize(this: @This(), size: Point) void {
|
pub inline fn resize(this: @This(), size: Point) void {
|
||||||
if (this.vtable.resize) |resize_fn|
|
if (this.vtable.resize) |resize_fn|
|
||||||
@@ -242,16 +255,16 @@ pub fn Scrollable(Model: type, Event: type) type {
|
|||||||
const last_max_anchor_y = this.container_size.y -| this.size.y;
|
const last_max_anchor_y = this.container_size.y -| this.size.y;
|
||||||
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.container.resize(size);
|
|
||||||
if (this.configuration.scrollbar) {
|
if (this.configuration.scrollbar) {
|
||||||
if (this.container.properties.size.dim.x > this.size.x or this.container.size.x > this.size.x) this.configuration.y_axis = true;
|
if (this.container.properties.size.dim.x > this.size.x or this.container.size.x > this.size.x) this.configuration.y_axis = true;
|
||||||
if (this.container.properties.size.dim.y > this.size.y or this.container.size.y > this.size.y) this.configuration.x_axis = true;
|
if (this.container.properties.size.dim.y > this.size.y or this.container.size.y > this.size.y) this.configuration.x_axis = true;
|
||||||
|
|
||||||
if (this.configuration.x_axis or this.configuration.y_axis) this.container.resize(.{
|
const min_size = this.container.element.minSize(size);
|
||||||
.x = this.size.x - if (this.configuration.x_axis) @as(u16, 1) else @as(u16, 0),
|
this.container.resize(.{
|
||||||
.y = this.size.y - if (this.configuration.y_axis) @as(u16, 1) else @as(u16, 0),
|
.x = min_size.x - if (this.configuration.x_axis) @as(u16, 1) else @as(u16, 0),
|
||||||
|
.y = min_size.y - if (this.configuration.y_axis) @as(u16, 1) else @as(u16, 0),
|
||||||
});
|
});
|
||||||
}
|
} else this.container.resize(this.container.element.minSize(size)); // notify the container about the minimal size it should have (can be larger)
|
||||||
|
|
||||||
const new_max_anchor_x = this.container.size.x -| size.x;
|
const new_max_anchor_x = this.container.size.x -| size.x;
|
||||||
const new_max_anchor_y = this.container.size.y -| size.y;
|
const new_max_anchor_y = this.container.size.y -| size.y;
|
||||||
|
|||||||
Reference in New Issue
Block a user