add: Direct Renderer implementation rendering the fixed size of the root Container
A corresponding example has been added, which is very minimalistic as of now, but will add further functionality to test the corresponding workflow that is usual in `zterm` such that it in the best case only a swap in the renderer to switch from alternate mode drawing to direct drawing.
This commit is contained in:
@@ -24,6 +24,8 @@ pub fn build(b: *std.Build) void {
|
||||
palette,
|
||||
// error handling
|
||||
errors,
|
||||
// non alternate screen applications
|
||||
direct,
|
||||
};
|
||||
|
||||
const example = b.option(Examples, "example", "Example to build and/or run. (default: all)") orelse .all;
|
||||
@@ -73,6 +75,8 @@ pub fn build(b: *std.Build) void {
|
||||
.palette => "examples/styles/palette.zig",
|
||||
// error handling
|
||||
.errors => "examples/errors.zig",
|
||||
// non-alternate screen
|
||||
.direct => "examples/direct.zig",
|
||||
.all => unreachable, // should never happen
|
||||
}),
|
||||
.target = target,
|
||||
|
||||
@@ -91,6 +91,7 @@ pub const Buffered = struct {
|
||||
var writer = terminal.writer();
|
||||
const s = this.screen;
|
||||
const vs = this.virtual_screen;
|
||||
|
||||
for (0..this.size.y) |row| {
|
||||
for (0..this.size.x) |col| {
|
||||
const idx = (row * this.size.x) + col;
|
||||
@@ -123,6 +124,87 @@ pub const Buffered = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Direct = struct {
|
||||
gpa: Allocator,
|
||||
size: Point,
|
||||
resized: bool,
|
||||
screen: []Cell,
|
||||
|
||||
pub fn init(gpa: Allocator) @This() {
|
||||
return .{
|
||||
.gpa = gpa,
|
||||
.size = .{},
|
||||
.resized = true,
|
||||
.screen = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.gpa.free(this.screen);
|
||||
}
|
||||
|
||||
pub fn resize(this: *@This()) !Point {
|
||||
// TODO the size in the y-axis is *not fixed* and *not limited*
|
||||
// how can I achive this?
|
||||
this.size = .{};
|
||||
if (!this.resized) {
|
||||
this.gpa.free(this.screen);
|
||||
this.screen = undefined;
|
||||
}
|
||||
this.resized = true;
|
||||
return terminal.getTerminalSize();
|
||||
}
|
||||
|
||||
pub fn clear(this: *@This()) !void {
|
||||
_ = this;
|
||||
try terminal.clearScreen();
|
||||
}
|
||||
|
||||
/// Render provided cells at size (anchor and dimension) into the *virtual screen*.
|
||||
pub fn render(this: *@This(), comptime Container: type, container: *Container, comptime Model: type, model: *const Model) !void {
|
||||
const size: Point = container.size;
|
||||
const origin: Point = container.origin;
|
||||
|
||||
if (this.resized) {
|
||||
this.size = size;
|
||||
const n = @as(usize, this.size.x) * @as(usize, this.size.y);
|
||||
this.screen = try this.gpa.alloc(Cell, n);
|
||||
@memset(this.screen, .{});
|
||||
this.resized = false;
|
||||
}
|
||||
|
||||
const cells: []const Cell = try container.content(model);
|
||||
|
||||
var idx: usize = 0;
|
||||
var vs = this.screen;
|
||||
const anchor: usize = (@as(usize, origin.y) * @as(usize, this.size.x)) + @as(usize, origin.x);
|
||||
|
||||
|
||||
blk: for (0..size.y) |row| {
|
||||
for (0..size.x) |col| {
|
||||
vs[anchor + (row * this.size.x) + col] = cells[idx];
|
||||
idx += 1;
|
||||
|
||||
if (cells.len == idx) break :blk;
|
||||
}
|
||||
}
|
||||
// free immediately
|
||||
container.allocator.free(cells);
|
||||
for (container.elements.items) |*element| try this.render(Container, element, Model, model);
|
||||
}
|
||||
|
||||
pub fn flush(this: *@This()) !void {
|
||||
var writer = terminal.writer();
|
||||
for (0..this.size.y) |row| {
|
||||
for (0..this.size.x) |col| {
|
||||
const idx = (row * this.size.x) + col;
|
||||
const cvs = this.screen[idx];
|
||||
try cvs.value(&writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
const meta = std.meta;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
Reference in New Issue
Block a user