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 TextStyles = struct {
|
||||||
const text = "Example";
|
const text = "Example";
|
||||||
|
|
||||||
@@ -109,12 +189,21 @@ pub fn main() !void {
|
|||||||
|
|
||||||
var container = try App.Container.init(allocator, .{
|
var container = try App.Container.init(allocator, .{
|
||||||
.layout = .{
|
.layout = .{
|
||||||
.gap = 2,
|
// .gap = 2,
|
||||||
.padding = .{ .top = 5, .bottom = 3, .left = 3, .right = 3 },
|
.padding = .{ .top = 5, .bottom = 3, .left = 3, .right = 3 },
|
||||||
|
.direction = .vertical,
|
||||||
},
|
},
|
||||||
}, element);
|
}, element);
|
||||||
defer container.deinit();
|
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, .{
|
var box = try App.Container.init(allocator, .{
|
||||||
.layout = .{ .direction = .vertical },
|
.layout = .{ .direction = .vertical },
|
||||||
}, text_styles.element());
|
}, text_styles.element());
|
||||||
@@ -126,28 +215,39 @@ pub fn main() !void {
|
|||||||
try app.start();
|
try app.start();
|
||||||
defer app.stop() catch |err| log.err("Failed to stop application: {any}", .{err});
|
defer app.stop() catch |err| log.err("Failed to stop application: {any}", .{err});
|
||||||
|
|
||||||
while (true) {
|
// event loop
|
||||||
const event = app.nextEvent();
|
loop: while (true) {
|
||||||
log.debug("received event: {s}", .{@tagName(event)});
|
// 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
|
// handle events
|
||||||
switch (event) {
|
for (0..len) |_| {
|
||||||
.key => |key| if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(),
|
const event = app.queue.pop();
|
||||||
.err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }),
|
log.debug("handling event: {s}", .{@tagName(event)});
|
||||||
else => {},
|
// 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(.{
|
container.handle(&app.model, event) catch |err| app.postEvent(.{
|
||||||
.err = .{
|
.err = .{
|
||||||
.err = err,
|
.err = err,
|
||||||
.msg = "Container Event handling failed",
|
.msg = "Container Event handling failed",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// post event handling
|
// post event handling
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.quit => break,
|
.quit => break :loop,
|
||||||
else => {},
|
else => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.resize(try renderer.resize());
|
container.resize(try renderer.resize());
|
||||||
|
|||||||
Reference in New Issue
Block a user