mod(example/text): improve event loop; add stick table heading for used emphasis
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 59s
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 59s
This should be the way it should be done all the time, such that you are not rendering for every input, but instead handle all `App.Event`s that happened between the last render and the current. This shares similarities with the continuous event loops, which also batches the events only with the exception that it instead blocks (see `App.Queue.poll`).
This commit is contained in:
@@ -24,6 +24,86 @@ const QuitText = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const TableText = struct {
|
||||
pub fn element(this: *@This()) App.Element {
|
||||
return .{
|
||||
.ptr = this,
|
||||
.vtable = &.{
|
||||
.content = content,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn content(ctx: *anyopaque, _: *const App.Model, cells: []zterm.Cell, size: zterm.Point) !void {
|
||||
_ = ctx;
|
||||
_ = size;
|
||||
var idx: usize = 0;
|
||||
{
|
||||
const text = "Normal ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Bold ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Dim ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Italic ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Underl ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Blink ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Invert ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Hidden ";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
const text = "Strikethrough";
|
||||
for (text) |cp| {
|
||||
cells[idx].cp = cp;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const TextStyles = struct {
|
||||
const text = "Example";
|
||||
|
||||
@@ -109,12 +189,21 @@ pub fn main() !void {
|
||||
|
||||
var container = try App.Container.init(allocator, .{
|
||||
.layout = .{
|
||||
.gap = 2,
|
||||
// .gap = 2,
|
||||
.padding = .{ .top = 5, .bottom = 3, .left = 3, .right = 3 },
|
||||
.direction = .vertical,
|
||||
},
|
||||
}, element);
|
||||
defer container.deinit();
|
||||
|
||||
var table_head: TableText = .{};
|
||||
try container.append(try .init(allocator, .{
|
||||
.size = .{
|
||||
.dim = .{ .y = 1 },
|
||||
.grow = .horizontal,
|
||||
},
|
||||
}, table_head.element()));
|
||||
|
||||
var box = try App.Container.init(allocator, .{
|
||||
.layout = .{ .direction = .vertical },
|
||||
}, text_styles.element());
|
||||
@@ -126,28 +215,39 @@ pub fn main() !void {
|
||||
try app.start();
|
||||
defer app.stop() catch |err| log.err("Failed to stop application: {any}", .{err});
|
||||
|
||||
while (true) {
|
||||
const event = app.nextEvent();
|
||||
log.debug("received event: {s}", .{@tagName(event)});
|
||||
// event loop
|
||||
loop: while (true) {
|
||||
// batch events since last iteration
|
||||
const len = blk: {
|
||||
app.queue.poll();
|
||||
app.queue.lock();
|
||||
defer app.queue.unlock();
|
||||
break :blk app.queue.len();
|
||||
};
|
||||
|
||||
// pre event handling
|
||||
switch (event) {
|
||||
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
|
||||
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
|
||||
else => {},
|
||||
}
|
||||
// handle events
|
||||
for (0..len) |_| {
|
||||
const event = app.queue.pop();
|
||||
log.debug("handling event: {s}", .{@tagName(event)});
|
||||
// pre event handling
|
||||
switch (event) {
|
||||
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
|
||||
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
|
||||
else => {},
|
||||
}
|
||||
|
||||
container.handle(&app.model, event) catch |err| app.postEvent(.{
|
||||
.err = .{
|
||||
.err = err,
|
||||
.msg = "Container Event handling failed",
|
||||
},
|
||||
});
|
||||
container.handle(&app.model, event) catch |err| app.postEvent(.{
|
||||
.err = .{
|
||||
.err = err,
|
||||
.msg = "Container Event handling failed",
|
||||
},
|
||||
});
|
||||
|
||||
// post event handling
|
||||
switch (event) {
|
||||
.quit => break,
|
||||
else => {},
|
||||
// post event handling
|
||||
switch (event) {
|
||||
.quit => break :loop,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
container.resize(try renderer.resize());
|
||||
|
||||
Reference in New Issue
Block a user