WIP: container rendering for borders + container element rendering
This commit is contained in:
@@ -10,8 +10,10 @@ const log = std.log.scoped(.container);
|
||||
|
||||
/// Border configuration struct
|
||||
pub const Border = struct {
|
||||
pub const rounded_border: [6]u21 = .{ '╭', '─', '╮', '│', '╰', '╯' };
|
||||
pub const squared_border: [6]u21 = .{ '┌', '─', '┐', '│', '└', '┘' };
|
||||
/// Color to use for the border
|
||||
color: Color = .default,
|
||||
color: Color = .{ .ansi = .reset },
|
||||
/// Configure the corner type to be used for the border
|
||||
corners: enum(u1) {
|
||||
squared,
|
||||
@@ -27,13 +29,55 @@ pub const Border = struct {
|
||||
/// Configure separator borders between child element to added to the layout
|
||||
separator: struct {
|
||||
enabled: bool = false,
|
||||
color: Color = .default,
|
||||
color: Color = .{ .ansi = .reset },
|
||||
line: enum {
|
||||
line,
|
||||
dotted,
|
||||
// TODO: add more variations which could be used for the separator
|
||||
} = .line,
|
||||
} = .{},
|
||||
|
||||
// NOTE: caller owns `cells` slice and ensures that `cells.len == size.cols * size.rows`
|
||||
pub fn contents(this: @This(), cells: []Cell, size: Size) void {
|
||||
std.debug.assert(cells.len == size.cols * size.rows);
|
||||
|
||||
const frame = switch (this.corners) {
|
||||
.rounded => Border.rounded_border,
|
||||
.squared => Border.squared_border,
|
||||
};
|
||||
std.debug.assert(frame.len == 6);
|
||||
// TODO: respect color configuration
|
||||
// TODO: respect sides configuration
|
||||
// render top and bottom border
|
||||
for (0..size.cols) |col| {
|
||||
const last_row = (size.rows - 1) * size.cols;
|
||||
if (col == 0) {
|
||||
// top left corner
|
||||
cells[col].cp = frame[0];
|
||||
// bottom left corner
|
||||
cells[last_row + col].cp = frame[4];
|
||||
} else if (col == size.cols - 1) {
|
||||
// top right corner
|
||||
cells[col].cp = frame[2];
|
||||
// bottom left corner
|
||||
cells[last_row + col].cp = frame[5];
|
||||
} else {
|
||||
// top side
|
||||
cells[col].cp = frame[1];
|
||||
// bottom side
|
||||
cells[last_row + col].cp = frame[1];
|
||||
}
|
||||
// TODO: fix rendering of styling?
|
||||
cells[col].style = .{ .fg = .{ .ansi = .red }, .attributes = &.{} };
|
||||
cells[last_row + col].style = .{ .fg = .{ .ansi = .red }, .attributes = &.{} };
|
||||
}
|
||||
// render left and right border
|
||||
for (1..size.rows - 1) |row| {
|
||||
const idx = (row * size.cols);
|
||||
cells[idx].cp = frame[3]; // left
|
||||
cells[idx + size.cols - 1].cp = frame[3]; // right
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Rectangle configuration struct
|
||||
@@ -41,7 +85,7 @@ pub const Rectangle = struct {
|
||||
/// `Color` to use to fill the `Rectangle` with
|
||||
/// NOTE: used as background color when rendering! such that it renders the
|
||||
/// children accordingly without removing the coloring of the `Rectangle`
|
||||
fill: Color = .default,
|
||||
fill: Color = .{ .ansi = .reset },
|
||||
/// Configure the corners of the `Rectangle`
|
||||
corners: enum(u1) {
|
||||
squared,
|
||||
@@ -105,6 +149,7 @@ pub fn Container(comptime Event: type) type {
|
||||
@compileError("Provided user event `Event` for `Container(comptime Event: type)`");
|
||||
}
|
||||
return struct {
|
||||
allocator: std.mem.Allocator,
|
||||
size: Size,
|
||||
properties: Properties,
|
||||
elements: std.ArrayList(@This()),
|
||||
@@ -121,6 +166,7 @@ pub fn Container(comptime Event: type) type {
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, properties: Properties) !@This() {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.size = .{ .cols = 0, .rows = 0 },
|
||||
.properties = properties,
|
||||
.elements = std.ArrayList(@This()).init(allocator),
|
||||
@@ -197,7 +243,25 @@ pub fn Container(comptime Event: type) type {
|
||||
offset += rows;
|
||||
},
|
||||
}
|
||||
// TODO; adjust size according to the layout of the `Container`
|
||||
|
||||
// border resizing
|
||||
const sides = this.properties.border.sides;
|
||||
if (sides.top) {
|
||||
element_size.anchor.row += 1;
|
||||
element_size.rows -|= 1;
|
||||
}
|
||||
if (sides.bottom) {
|
||||
element_size.rows -|= 1;
|
||||
}
|
||||
if (sides.left) {
|
||||
element_size.anchor.col += 1;
|
||||
element_size.cols -|= 1;
|
||||
}
|
||||
if (sides.right) {
|
||||
element_size.cols -|= 1;
|
||||
}
|
||||
|
||||
// TODO: adjust size according to the layout of the `Container`
|
||||
if (element.handle(.{ .resize = element_size })) |e| {
|
||||
_ = e;
|
||||
}
|
||||
@@ -219,8 +283,10 @@ pub fn Container(comptime Event: type) type {
|
||||
|
||||
pub fn contents(this: *const @This()) []const Cell {
|
||||
// TODO: use the size and the corresponding contents to determine what should be show in form of a `Cell` array
|
||||
_ = this;
|
||||
return &[0]Cell{};
|
||||
const cells = this.allocator.alloc(Cell, this.size.cols * this.size.rows) catch @panic("Container::contents: Out of memory.");
|
||||
@memset(cells, .{}); // reset all cells
|
||||
this.properties.border.contents(cells, this.size);
|
||||
return cells;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user