diff --git a/examples/direct.zig b/examples/direct.zig index 329aa5b..817a2e4 100644 --- a/examples/direct.zig +++ b/examples/direct.zig @@ -11,6 +11,9 @@ pub fn main() !void { defer renderer.deinit(); var container: App.Container = try .init(gpa, .{ + .border = .{ + .sides = .all, + }, .layout = .{ .direction = .horizontal, .separator = .{ .enabled = true }, @@ -30,10 +33,58 @@ pub fn main() !void { .rectangle = .{ .fill = .green }, }, .{})); - container.resize(&app.model, try renderer.resize()); - container.reposition(&app.model, .{}); - try renderer.render(@TypeOf(container), &container, App.Model, &app.model); - try renderer.flush(); + try app.start(); // needs to become configurable, as what should be enabled / disabled (i.e. show cursor, hide cursor, use alternate screen, etc.) + defer app.stop() catch |err| log.err("Failed to stop application: {any}", .{err}); + + // event loop + event: 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(); + }; + + // handle events + for (0..len) |_| { + const event = app.queue.pop(); + //log.debug("received event: {s}", .{@tagName(event)}); + + // pre event handling + switch (event) { + // NOTE maybe I want to decouple the `key`s from the user input too? i.e. this only makes sense if the output is not echoed! + // otherwise just use gnu's `readline`? + .key => |key| { + if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } })) app.quit(); + }, + // NOTE errors could be displayed in another container in case one was received, etc. to provide the user with feedback + .err => |err| log.err("Received {s} with message: {s}", .{ @errorName(err.err), err.msg }), + else => {}, + } + + // NOTE returned errors should be propagated back to the application + container.handle(&app.model, event) catch |err| app.postEvent(.{ + .err = .{ + .err = err, + .msg = "Container Event handling failed", + }, + }); + + // post event handling + switch (event) { + .quit => break :event, + else => {}, + } + } + // if there are more events to process continue handling them otherwise I can render the next frame + if (app.queue.len() > 0) continue :event; + + container.resize(&app.model, try renderer.resize()); + container.reposition(&app.model, .{}); + try renderer.render(@TypeOf(container), &container, App.Model, &app.model); + try renderer.flush(); + } } pub const panic = App.panic_handler; diff --git a/src/app.zig b/src/app.zig index 92e9eae..d79db80 100644 --- a/src/app.zig +++ b/src/app.zig @@ -71,21 +71,21 @@ pub fn App(comptime M: type, comptime E: type) type { this.quit_event.reset(); this.thread = try Thread.spawn(.{}, @This().run, .{this}); - var termios: posix.termios = undefined; - try terminal.enableRawMode(&termios); - if (this.termios) |_| {} else this.termios = termios; + //var termios: posix.termios = undefined; + //try terminal.enableRawMode(&termios); + //if (this.termios) |_| {} else this.termios = termios; - try terminal.enterAltScreen(); - try terminal.saveScreen(); - try terminal.hideCursor(); - try terminal.enableMouseSupport(); + //try terminal.enterAltScreen(); + //try terminal.saveScreen(); + //try terminal.hideCursor(); + //try terminal.enableMouseSupport(); } pub fn interrupt(this: *@This()) !void { this.quit_event.set(); - try terminal.disableMouseSupport(); - try terminal.restoreScreen(); - try terminal.exitAltScreen(); + //try terminal.disableMouseSupport(); + //try terminal.restoreScreen(); + //try terminal.exitAltScreen(); if (this.thread) |*thread| { thread.join(); this.thread = null;