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,
|
palette,
|
||||||
// error handling
|
// error handling
|
||||||
errors,
|
errors,
|
||||||
|
// non alternate screen applications
|
||||||
|
direct,
|
||||||
};
|
};
|
||||||
|
|
||||||
const example = b.option(Examples, "example", "Example to build and/or run. (default: all)") orelse .all;
|
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",
|
.palette => "examples/styles/palette.zig",
|
||||||
// error handling
|
// error handling
|
||||||
.errors => "examples/errors.zig",
|
.errors => "examples/errors.zig",
|
||||||
|
// non-alternate screen
|
||||||
|
.direct => "examples/direct.zig",
|
||||||
.all => unreachable, // should never happen
|
.all => unreachable, // should never happen
|
||||||
}),
|
}),
|
||||||
.target = target,
|
.target = target,
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ pub const Buffered = struct {
|
|||||||
var writer = terminal.writer();
|
var writer = terminal.writer();
|
||||||
const s = this.screen;
|
const s = this.screen;
|
||||||
const vs = this.virtual_screen;
|
const vs = this.virtual_screen;
|
||||||
|
|
||||||
for (0..this.size.y) |row| {
|
for (0..this.size.y) |row| {
|
||||||
for (0..this.size.x) |col| {
|
for (0..this.size.x) |col| {
|
||||||
const idx = (row * 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 std = @import("std");
|
||||||
const meta = std.meta;
|
const meta = std.meta;
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|||||||
Reference in New Issue
Block a user