Packages

A terminal UI framework for Elixir with a high-performance Zig NIF backend.

Current section

Files

Jump to
elixir_opentui zig opentui event-emitter.zig
Raw

zig/opentui/event-emitter.zig

const std = @import("std");
const Allocator = std.mem.Allocator;
pub fn EventEmitter(comptime EventType: type) type {
if (@typeInfo(EventType) != .@"enum") {
@compileError("EventType must be an enum");
}
return struct {
const Self = @This();
pub const Listener = struct {
ctx: *anyopaque,
handle: *const fn (ctx: *anyopaque) void,
};
allocator: Allocator,
listeners: std.EnumMap(EventType, std.ArrayListUnmanaged(Listener)),
pub fn init(allocator: Allocator) Self {
return .{
.allocator = allocator,
.listeners = std.EnumMap(EventType, std.ArrayListUnmanaged(Listener)).init(.{}),
};
}
pub fn deinit(self: *Self) void {
var iter = self.listeners.iterator();
while (iter.next()) |entry| {
entry.value.deinit(self.allocator);
}
}
pub fn on(self: *Self, event: EventType, listener: Listener) !void {
const list_ptr = self.listeners.getPtr(event) orelse {
self.listeners.put(event, .{});
return self.on(event, listener);
};
try list_ptr.append(self.allocator, listener);
}
pub fn off(self: *Self, event: EventType, listener: Listener) void {
const list_ptr = self.listeners.getPtr(event) orelse return;
var i: usize = 0;
while (i < list_ptr.items.len) {
const item = list_ptr.items[i];
if (item.ctx == listener.ctx and item.handle == listener.handle) {
_ = list_ptr.swapRemove(i);
} else {
i += 1;
}
}
}
pub fn emit(self: *Self, event: EventType) void {
const list_ptr = self.listeners.getPtr(event) orelse return;
for (list_ptr.items) |listener| {
listener.handle(listener.ctx);
}
}
};
}