Skip to content

Comments

vxfw FlexRow FlexColum and Border should respect context min sizes#306

Open
xiexingwu wants to merge 2 commits intorockorager:mainfrom
xiexingwu:main
Open

vxfw FlexRow FlexColum and Border should respect context min sizes#306
xiexingwu wants to merge 2 commits intorockorager:mainfrom
xiexingwu:main

Conversation

@xiexingwu
Copy link

Problems

  • If FlexRow is provided a minimum height on draw, its children will not fill that minimum height. Similarly for FlexColumn regarding the minimum width.

  • Border does not account for its own width/height when given a non-zero min.

Reproduction

Replace examples/text_input.zig with the following example and run zig build example.

Full example file

const std = @import("std");
const vaxis = @import("vaxis");
const vxfw = vaxis.vxfw;

const Model = struct {
    pub fn widget(self: *Model) vxfw.Widget {
        return .{
            .userdata = self,
            .eventHandler = Model.typeErasedEventHandler,
            .drawFn = Model.typeErasedDrawFn,
        };
    }

    fn typeErasedEventHandler(_: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
        switch (event) {
            .key_press => |key| {
                if (key.matches('c', .{ .ctrl = true })) {
                    ctx.quit = true;
                    return;
                }
            },
            else => {},
        }
    }

    fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface {
        const self: *Model = @ptrCast(@alignCast(ptr));
        const max_size = ctx.max.size();

        const text_1: vxfw.Text = .{ .text = "Some text." };
        const border_1: vxfw.Border = .{
            .child = text_1.widget(),
            .labels = &.{.{ .text = "Box 1", .alignment = .top_left }},
        };

        const text_2: vxfw.Text = .{ .text = "Some more text." };
        const border_2: vxfw.Border = .{
            .child = text_2.widget(),
            .labels = &.{.{ .text = "Box 2", .alignment = .top_left }},
        };

        const flex_row: vxfw.FlexRow = .{
            .children = &.{
                .init(border_2.widget(), 1),
                .init(border_1.widget(), 1),
            },
        };

        const children = try ctx.arena.alloc(vxfw.SubSurface, 1);
        children[0] = .{
            .origin = .{ .row = 0, .col = 0 },
            .surface = try flex_row.draw(ctx.withConstraints(
                .{ .width = 0, .height = max_size.height },
                ctx.max,
            )),
        };

        return .{
            .size = max_size,
            .widget = self.widget(),
            .buffer = &.{},
            .children = children,
        };
    }
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    var app = try vxfw.App.init(allocator);
    defer app.deinit();

    const model = try allocator.create(Model);
    defer allocator.destroy(model);

    try app.run(model.widget(), .{});
}

Relevant snippet draws a FlexRow containing 2 Borders, each containing a Text.

    fn typeErasedDrawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface {
        const self: *Model = @ptrCast(@alignCast(ptr));
        const max_size = ctx.max.size();

        const text_1: vxfw.Text = .{ .text = "Some text." };
        const border_1: vxfw.Border = .{
            .child = text_1.widget(),
            .labels = &.{.{ .text = "Box 1", .alignment = .top_left }},
        };

        const text_2: vxfw.Text = .{ .text = "Some more text." };
        const border_2: vxfw.Border = .{
            .child = text_2.widget(),
            .labels = &.{.{ .text = "Box 2", .alignment = .top_left }},
        };

        const flex_row: vxfw.FlexRow = .{
            .children = &.{
                .init(border_2.widget(), 1),
                .init(border_1.widget(), 1),
            },
        };

        const children = try ctx.arena.alloc(vxfw.SubSurface, 1);
        children[0] = .{
            .origin = .{ .row = 0, .col = 0 },
            .surface = try flex_row.draw(ctx.withConstraints(
                .{ .width = 0, .height = max_size.height },
                ctx.max,
            )),
        };

        return .{
            .size = max_size,
            .widget = self.widget(),
            .buffer = &.{},
            .children = children,
        };
    }

Actual

The borders do not reach the bottom of the canvas.
Screenshot 2026-02-21 at 21 47 19

Expected

The borders reach the bottom of the canvas.
Screenshot 2026-02-21 at 21 45 41

Without the Border fix

The borders overflow the bottom of the canvas.
Screenshot 2026-02-21 at 21 48 43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant