From bfbe75f8d36d9e068e63dc264c2896599d6db453 Mon Sep 17 00:00:00 2001 From: Yves Biener Date: Tue, 20 Jan 2026 23:09:16 +0100 Subject: [PATCH] feat(inline): rendering without alternate screen Fix issue with growth resize for containers with corresponding borders, padding and gaps. --- examples/direct.zig | 34 +++++++++++++++++++++------------- src/container.zig | 30 +++++++++++++++++++----------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/examples/direct.zig b/examples/direct.zig index 3aba856..6fd4e7c 100644 --- a/examples/direct.zig +++ b/examples/direct.zig @@ -20,12 +20,12 @@ const QuitText = struct { assert(cells.len == @as(usize, size.x) * @as(usize, size.y)); const y = 0; - const x = size.x / 2 -| (text.len / 2); + const x = 2; const anchor = (y * size.x) + x; for (text, 0..) |cp, idx| { cells[anchor + idx].style.fg = .white; - cells[anchor + idx].style.emphasis = &.{.bold}; + cells[anchor + idx].style.emphasis = &.{ .bold, .underline }; cells[anchor + idx].cp = cp; // NOTE do not write over the contents of this `Container`'s `Size` @@ -35,7 +35,7 @@ const QuitText = struct { }; const Prompt = struct { - len: u16 = 5, + len: u16 = 3, pub fn element(this: *@This()) App.Element { return .{ .ptr = this, @@ -58,16 +58,14 @@ const Prompt = struct { assert(cells.len == @as(usize, size.x) * @as(usize, size.y)); for (0..this.len) |idx| { - cells[idx].style.bg = .red; + cells[idx].style.bg = .blue; cells[idx].style.fg = .black; cells[idx].style.emphasis = &.{.bold}; } - cells[this.len - 1].style.cursor = true; // marks the actual end of the rendering! - - const anchor = 1; - cells[anchor + 0].cp = 'N'; - cells[anchor + 1].cp = 'O'; - cells[anchor + 2].cp = 'R'; + cells[1].cp = '>'; + // leave one clear whitespace after the prompt + cells[this.len].style.bg = .default; + cells[this.len].style.cursor = true; // marks the actual end of the rendering! } }; @@ -86,6 +84,7 @@ pub fn main() !void { var container: App.Container = try .init(gpa, .{ .layout = .{ .direction = .vertical, + .gap = 1, // show empty line between elements to allow navigation through paragraph jumping }, .size = .{ .grow = .horizontal_only, @@ -96,10 +95,12 @@ pub fn main() !void { var quit_text: QuitText = .{}; var intermediate: App.Container = try .init(gpa, .{ .border = .{ - .sides = .all, + .sides = .{ .left = true }, + .color = .grey, }, .layout = .{ .direction = .horizontal, + .padding = .{ .left = 1, .top = 1 }, }, }, quit_text.element()); try intermediate.append(try .init(gpa, .{ @@ -109,11 +110,18 @@ pub fn main() !void { try intermediate.append(try .init(gpa, .{ .rectangle = .{ .fill = .green }, }, .{})); - try container.append(intermediate); + + var padding_container: App.Container = try .init(gpa, .{ + .layout = .{ + .padding = .horizontal(1), + }, + }, .{}); + try padding_container.append(intermediate); + try container.append(padding_container); var prompt: Prompt = .{}; try container.append(try .init(gpa, .{ - .rectangle = .{ .fill = .red }, + .rectangle = .{ .fill = .grey }, .size = .{ .dim = .{ .y = 1 }, }, diff --git a/src/container.zig b/src/container.zig index 1a0b069..5afd7d1 100644 --- a/src/container.zig +++ b/src/container.zig @@ -764,23 +764,31 @@ pub fn Container(Model: type, Event: type) type { const sides = this.properties.border.sides; switch (layout.direction) { - .horizontal => { + .vertical => { if (sides.top) { - available -|= 1; remainder -|= 1; } if (sides.bottom) { - available -|= 1; remainder -|= 1; } - }, - .vertical => { if (sides.left) { available -|= 1; - remainder -|= 1; } if (sides.right) { available -|= 1; + } + }, + .horizontal => { + if (sides.top) { + available -|= 1; + } + if (sides.bottom) { + available -|= 1; + } + if (sides.left) { + remainder -|= 1; + } + if (sides.right) { remainder -|= 1; } }, @@ -815,7 +823,7 @@ pub fn Container(Model: type, Event: type) type { .horizontal => if (child.properties.size.grow == .vertical or child.properties.size.grow == .vertical_only or child.properties.size.grow == .both) { child.size.y = available; }, - .vertical => if (child.properties.size.grow == .horizontal or child.properties.size.grow == .vertical_only or child.properties.size.grow == .both) { + .vertical => if (child.properties.size.grow == .horizontal or child.properties.size.grow == .horizontal_only or child.properties.size.grow == .both) { child.size.x = available; }, } @@ -862,23 +870,23 @@ pub fn Container(Model: type, Event: type) type { }; if (child.properties.size.grow != .fixed and child_size == smallest_size) { switch (layout.direction) { - .horizontal => if (child.properties.size.grow != .vertical) { + .horizontal => if (child.properties.size.grow != .vertical and child.properties.size.grow != .vertical_only) { child.size.x += size_to_correct; remainder -|= size_to_correct; }, - .vertical => if (child.properties.size.grow != .horizontal) { + .vertical => if (child.properties.size.grow != .horizontal and child.properties.size.grow != .horizontal_only) { child.size.y += size_to_correct; remainder -|= size_to_correct; }, } if (overflow > 0) { switch (layout.direction) { - .horizontal => if (child.properties.size.grow != .vertical) { + .horizontal => if (child.properties.size.grow != .vertical and child.properties.size.grow != .vertical_only) { child.size.x += 1; overflow -|= 1; remainder -|= 1; }, - .vertical => if (child.properties.size.grow != .horizontal) { + .vertical => if (child.properties.size.grow != .horizontal and child.properties.size.grow != .horizontal_only) { child.size.y += 1; overflow -|= 1; remainder -|= 1;