mod(renderer): dynamic clear of size for widgets to improve render performance
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 35s

This commit is contained in:
2024-11-13 15:07:26 +01:00
parent 80459a51b1
commit 270ca9b1be
4 changed files with 39 additions and 14 deletions

View File

@@ -22,6 +22,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
const Events = std.ArrayList(Event); const Events = std.ArrayList(Event);
return struct { return struct {
size: terminal.Size = undefined, size: terminal.Size = undefined,
require_render: bool = true,
element: Element = undefined, element: Element = undefined,
events: Events = undefined, events: Events = undefined,
config: Config = undefined, config: Config = undefined,
@@ -68,6 +69,7 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
switch (event) { switch (event) {
.resize => |size| { .resize => |size| {
this.size = size; this.size = size;
this.require_render = true;
log.debug("Event .resize: {{ .anchor = {{ .col = {d}, .row = {d} }}, .cols = {d}, .rows = {d} }}", .{ log.debug("Event .resize: {{ .anchor = {{ .col = {d}, .row = {d} }}, .cols = {d}, .rows = {d} }}", .{
size.anchor.col, size.anchor.col,
size.anchor.row, size.anchor.row,
@@ -167,8 +169,11 @@ pub fn Layout(comptime Event: type, comptime Element: type, comptime Renderer: t
} }
pub fn render(this: *@This(), renderer: *Renderer) !void { pub fn render(this: *@This(), renderer: *Renderer) !void {
if (this.require_render) {
try renderer.clear(this.size); try renderer.clear(this.size);
try this.renderFrame(renderer); try this.renderFrame(renderer);
this.require_render = false;
}
switch ((&this.element).*) { switch ((&this.element).*) {
.layout => |*layout| { .layout => |*layout| {

View File

@@ -128,12 +128,19 @@ pub fn Direct(comptime _: bool) type {
_ = this; _ = this;
_ = size; _ = size;
} }
pub fn clear(this: *@This(), size: Size) !void { pub fn clear(this: *@This(), size: Size) !void {
_ = this; _ = this;
const anchor = size.anchor; std.debug.assert(1028 > size.cols);
// NOTE: clear entire screen for the first content (derived from the anchor being at the very left-top) var buf: [1028]u8 = undefined;
if (anchor.col == 1 and anchor.row == 1) { @memset(buf[0..], ' ');
try terminal.clearScreen(); for (0..size.rows) |r| {
const row: u16 = @truncate(r);
try terminal.setCursorPosition(.{
.col = size.anchor.col,
.row = size.anchor.row + row,
});
_ = try terminal.write(buf[0..size.cols]);
} }
} }

View File

@@ -18,6 +18,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
line_index: std.ArrayList(usize) = undefined, line_index: std.ArrayList(usize) = undefined,
line: usize = 0, line: usize = 0,
size: terminal.Size = undefined, size: terminal.Size = undefined,
require_render: bool = false,
pub fn init(allocator: std.mem.Allocator, file: std.fs.File) @This() { pub fn init(allocator: std.mem.Allocator, file: std.fs.File) @This() {
var contents = Contents.init(allocator); var contents = Contents.init(allocator);
@@ -42,6 +43,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
} }
pub fn handle(this: *@This(), event: Event) ?Event { pub fn handle(this: *@This(), event: Event) ?Event {
var require_render = true;
switch (event) { switch (event) {
// store the received size // store the received size
.resize => |size| { .resize => |size| {
@@ -54,28 +56,33 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
if (key.matches(.{ .cp = 'g' })) { if (key.matches(.{ .cp = 'g' })) {
// top // top
this.line = 0; this.line = 0;
} } else if (key.matches(.{ .cp = 'G' })) {
if (key.matches(.{ .cp = 'G' })) {
// bottom // bottom
this.line = this.line_index.items.len -| 1 -| this.size.rows; this.line = this.line_index.items.len -| 1 -| this.size.rows;
} } else if (key.matches(.{ .cp = 'j' })) {
if (key.matches(.{ .cp = 'j' })) {
// down // down
if (this.line < this.line_index.items.len -| 1 -| this.size.rows) { if (this.line < this.line_index.items.len -| 1 -| this.size.rows) {
this.line +|= 1; this.line +|= 1;
} }
} } else if (key.matches(.{ .cp = 'k' })) {
if (key.matches(.{ .cp = 'k' })) {
// up // up
this.line -|= 1; this.line -|= 1;
} else {
require_render = false;
} }
}, },
else => {}, else => {
require_render = false;
},
} }
this.require_render = require_render;
return null; return null;
} }
pub fn render(this: *@This(), renderer: *Renderer) !void { pub fn render(this: *@This(), renderer: *Renderer) !void {
if (!this.require_render) {
return;
}
try renderer.clear(this.size); try renderer.clear(this.size);
if (this.size.rows >= this.line_index.items.len) { if (this.size.rows >= this.line_index.items.len) {
try renderer.render(this.size, &[_]terminal.Cell{ try renderer.render(this.size, &[_]terminal.Cell{
@@ -96,6 +103,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
.{ .content = this.contents.items[i..x], .style = .{ .dim = true, .fg = .{ .index = 9 } } }, .{ .content = this.contents.items[i..x], .style = .{ .dim = true, .fg = .{ .index = 9 } } },
}); });
} }
this.require_render = false;
} }
}; };
} }

View File

@@ -12,6 +12,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
} }
return struct { return struct {
size: terminal.Size = undefined, size: terminal.Size = undefined,
size_changed: bool = false,
pub fn init() @This() { pub fn init() @This() {
return .{}; return .{};
@@ -25,6 +26,7 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
switch (event) { switch (event) {
.resize => |size| { .resize => |size| {
this.size = size; this.size = size;
this.size_changed = true;
}, },
else => {}, else => {},
} }
@@ -32,7 +34,10 @@ pub fn Widget(comptime Event: type, comptime Renderer: type) type {
} }
pub fn render(this: *@This(), renderer: *Renderer) !void { pub fn render(this: *@This(), renderer: *Renderer) !void {
if (this.size_changed) {
try renderer.clear(this.size); try renderer.clear(this.size);
this.size_changed = false;
}
} }
}; };
} }