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
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 35s
This commit is contained in:
@@ -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| {
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user