feat(inline): rendering without alternate screen
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (pull_request) Successful in 1m10s
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 55s

Fix issue with growth resize for containers with corresponding
borders, padding and gaps.
This commit was merged in pull request #2.
This commit is contained in:
2026-01-20 23:09:16 +01:00
parent 89517b2546
commit bfbe75f8d3
2 changed files with 40 additions and 24 deletions

View File

@@ -20,12 +20,12 @@ const QuitText = struct {
assert(cells.len == @as(usize, size.x) * @as(usize, size.y)); assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
const y = 0; const y = 0;
const x = size.x / 2 -| (text.len / 2); const x = 2;
const anchor = (y * size.x) + x; const anchor = (y * size.x) + x;
for (text, 0..) |cp, idx| { for (text, 0..) |cp, idx| {
cells[anchor + idx].style.fg = .white; cells[anchor + idx].style.fg = .white;
cells[anchor + idx].style.emphasis = &.{.bold}; cells[anchor + idx].style.emphasis = &.{ .bold, .underline };
cells[anchor + idx].cp = cp; cells[anchor + idx].cp = cp;
// NOTE do not write over the contents of this `Container`'s `Size` // NOTE do not write over the contents of this `Container`'s `Size`
@@ -35,7 +35,7 @@ const QuitText = struct {
}; };
const Prompt = struct { const Prompt = struct {
len: u16 = 5, len: u16 = 3,
pub fn element(this: *@This()) App.Element { pub fn element(this: *@This()) App.Element {
return .{ return .{
.ptr = this, .ptr = this,
@@ -58,16 +58,14 @@ const Prompt = struct {
assert(cells.len == @as(usize, size.x) * @as(usize, size.y)); assert(cells.len == @as(usize, size.x) * @as(usize, size.y));
for (0..this.len) |idx| { for (0..this.len) |idx| {
cells[idx].style.bg = .red; cells[idx].style.bg = .blue;
cells[idx].style.fg = .black; cells[idx].style.fg = .black;
cells[idx].style.emphasis = &.{.bold}; cells[idx].style.emphasis = &.{.bold};
} }
cells[this.len - 1].style.cursor = true; // marks the actual end of the rendering! cells[1].cp = '>';
// leave one clear whitespace after the prompt
const anchor = 1; cells[this.len].style.bg = .default;
cells[anchor + 0].cp = 'N'; cells[this.len].style.cursor = true; // marks the actual end of the rendering!
cells[anchor + 1].cp = 'O';
cells[anchor + 2].cp = 'R';
} }
}; };
@@ -86,6 +84,7 @@ pub fn main() !void {
var container: App.Container = try .init(gpa, .{ var container: App.Container = try .init(gpa, .{
.layout = .{ .layout = .{
.direction = .vertical, .direction = .vertical,
.gap = 1, // show empty line between elements to allow navigation through paragraph jumping
}, },
.size = .{ .size = .{
.grow = .horizontal_only, .grow = .horizontal_only,
@@ -96,10 +95,12 @@ pub fn main() !void {
var quit_text: QuitText = .{}; var quit_text: QuitText = .{};
var intermediate: App.Container = try .init(gpa, .{ var intermediate: App.Container = try .init(gpa, .{
.border = .{ .border = .{
.sides = .all, .sides = .{ .left = true },
.color = .grey,
}, },
.layout = .{ .layout = .{
.direction = .horizontal, .direction = .horizontal,
.padding = .{ .left = 1, .top = 1 },
}, },
}, quit_text.element()); }, quit_text.element());
try intermediate.append(try .init(gpa, .{ try intermediate.append(try .init(gpa, .{
@@ -109,11 +110,18 @@ pub fn main() !void {
try intermediate.append(try .init(gpa, .{ try intermediate.append(try .init(gpa, .{
.rectangle = .{ .fill = .green }, .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 = .{}; var prompt: Prompt = .{};
try container.append(try .init(gpa, .{ try container.append(try .init(gpa, .{
.rectangle = .{ .fill = .red }, .rectangle = .{ .fill = .grey },
.size = .{ .size = .{
.dim = .{ .y = 1 }, .dim = .{ .y = 1 },
}, },

View File

@@ -764,23 +764,31 @@ pub fn Container(Model: type, Event: type) type {
const sides = this.properties.border.sides; const sides = this.properties.border.sides;
switch (layout.direction) { switch (layout.direction) {
.horizontal => { .vertical => {
if (sides.top) { if (sides.top) {
available -|= 1;
remainder -|= 1; remainder -|= 1;
} }
if (sides.bottom) { if (sides.bottom) {
available -|= 1;
remainder -|= 1; remainder -|= 1;
} }
},
.vertical => {
if (sides.left) { if (sides.left) {
available -|= 1; available -|= 1;
remainder -|= 1;
} }
if (sides.right) { if (sides.right) {
available -|= 1; available -|= 1;
}
},
.horizontal => {
if (sides.top) {
available -|= 1;
}
if (sides.bottom) {
available -|= 1;
}
if (sides.left) {
remainder -|= 1;
}
if (sides.right) {
remainder -|= 1; 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) { .horizontal => if (child.properties.size.grow == .vertical or child.properties.size.grow == .vertical_only or child.properties.size.grow == .both) {
child.size.y = available; 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; 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) { if (child.properties.size.grow != .fixed and child_size == smallest_size) {
switch (layout.direction) { 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; child.size.x += size_to_correct;
remainder -|= 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; child.size.y += size_to_correct;
remainder -|= size_to_correct; remainder -|= size_to_correct;
}, },
} }
if (overflow > 0) { if (overflow > 0) {
switch (layout.direction) { 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; child.size.x += 1;
overflow -|= 1; overflow -|= 1;
remainder -|= 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; child.size.y += 1;
overflow -|= 1; overflow -|= 1;
remainder -|= 1; remainder -|= 1;