initial commit
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 30s
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 30s
This commit is contained in:
78
src/widget.zig
Normal file
78
src/widget.zig
Normal file
@@ -0,0 +1,78 @@
|
||||
//! Dynamic dispatch for widget implementations.
|
||||
//! Each widget should at last implement these functions:
|
||||
//! - handle(this: *@This(), event: Event) ?Event {}
|
||||
//! - content(this: *@This()) ![]u8 {}
|
||||
//! - deinit(this: *@This()) void {}
|
||||
//!
|
||||
//! Create a `Widget` using `createFrom(object: anytype)` and use them through
|
||||
//! the defined interface. The widget will take care of calling the correct
|
||||
//! implementation of the corresponding underlying type.
|
||||
//!
|
||||
//! Each `Widget` may cache its content and should if the contents will not
|
||||
//! change for a long time.
|
||||
const isTaggedUnion = @import("event.zig").isTaggedUnion;
|
||||
|
||||
pub fn Widget(comptime Event: type) type {
|
||||
if (!isTaggedUnion(Event)) {
|
||||
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
||||
}
|
||||
return struct {
|
||||
const WidgetType = @This();
|
||||
const Ptr = usize;
|
||||
|
||||
const VTable = struct {
|
||||
handle: *const fn (this: *WidgetType, event: Event) ?Event,
|
||||
content: *const fn (this: *WidgetType) anyerror![]u8,
|
||||
deinit: *const fn (this: *WidgetType) void,
|
||||
};
|
||||
|
||||
object: Ptr = undefined,
|
||||
vtable: *const VTable = undefined,
|
||||
|
||||
// Handle the provided `Event` for this `Widget`.
|
||||
pub fn handle(this: *WidgetType, event: Event) ?Event {
|
||||
return this.vtable.handle(this, event);
|
||||
}
|
||||
|
||||
// Return the entire content of this `Widget`.
|
||||
pub fn content(this: *WidgetType) ![]u8 {
|
||||
return try this.vtable.content(this);
|
||||
}
|
||||
|
||||
pub fn deinit(this: *WidgetType) void {
|
||||
this.vtable.deinit(this);
|
||||
this.* = undefined;
|
||||
}
|
||||
|
||||
pub fn createFrom(object: anytype) WidgetType {
|
||||
return WidgetType{
|
||||
.object = @intFromPtr(object),
|
||||
.vtable = &.{
|
||||
.handle = struct {
|
||||
// Handle the provided `Event` for this `Widget`.
|
||||
fn handle(this: *WidgetType, event: Event) ?Event {
|
||||
const widget: @TypeOf(object) = @ptrFromInt(this.object);
|
||||
return widget.handle(event);
|
||||
}
|
||||
}.handle,
|
||||
.content = struct {
|
||||
// Return the entire content of this `Widget`.
|
||||
fn content(this: *WidgetType) ![]u8 {
|
||||
const widget: @TypeOf(object) = @ptrFromInt(this.object);
|
||||
return try widget.content();
|
||||
}
|
||||
}.content,
|
||||
.deinit = struct {
|
||||
fn deinit(this: *WidgetType) void {
|
||||
const widget: @TypeOf(object) = @ptrFromInt(this.object);
|
||||
widget.deinit();
|
||||
}
|
||||
}.deinit,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: import and export of `Widget` implementations (with corresponding intialization using `Event`)
|
||||
pub const RawText = @import("widget/RawText.zig").Widget(Event);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user