mirror of
https://github.com/fairyglade/ly.git
synced 2026-03-25 01:36:05 +00:00
Make handling inputs widget-independent
Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
157
src/main.zig
157
src/main.zig
@@ -66,6 +66,8 @@ fn ttyControlTransferSignalHandler(_: c_int) callconv(.c) void {
|
|||||||
|
|
||||||
const UiState = struct {
|
const UiState = struct {
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
active_widget_index: usize,
|
||||||
|
handlable_widgets: std.ArrayList(*Widget),
|
||||||
auth_fails: u64,
|
auth_fails: u64,
|
||||||
run: bool,
|
run: bool,
|
||||||
update: bool,
|
update: bool,
|
||||||
@@ -97,7 +99,7 @@ const UiState = struct {
|
|||||||
saved_users: SavedUsers,
|
saved_users: SavedUsers,
|
||||||
login: UserList,
|
login: UserList,
|
||||||
password: Text,
|
password: Text,
|
||||||
active_input: enums.Input,
|
password_widget: Widget,
|
||||||
insert_mode: bool,
|
insert_mode: bool,
|
||||||
edge_margin: Position,
|
edge_margin: Position,
|
||||||
config: Config,
|
config: Config,
|
||||||
@@ -780,6 +782,8 @@ pub fn main() !void {
|
|||||||
);
|
);
|
||||||
defer state.password.deinit();
|
defer state.password.deinit();
|
||||||
|
|
||||||
|
state.password_widget = state.password.widget();
|
||||||
|
|
||||||
state.version_label = Label.init(
|
state.version_label = Label.init(
|
||||||
ly_version_str,
|
ly_version_str,
|
||||||
null,
|
null,
|
||||||
@@ -941,12 +945,12 @@ pub fn main() !void {
|
|||||||
state.config.auth_fails,
|
state.config.auth_fails,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.active_widget_index = 0;
|
||||||
state.auth_fails = 0;
|
state.auth_fails = 0;
|
||||||
state.run = true;
|
state.run = true;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
state.animation_timed_out = false;
|
state.animation_timed_out = false;
|
||||||
state.animate = state.config.animation != .none;
|
state.animate = state.config.animation != .none;
|
||||||
state.active_input = state.config.default_input;
|
|
||||||
state.insert_mode = !state.config.vi_mode or state.config.vi_default_mode == .insert;
|
state.insert_mode = !state.config.vi_mode or state.config.vi_default_mode == .insert;
|
||||||
state.edge_margin = Position.init(
|
state.edge_margin = Position.init(
|
||||||
state.config.edge_margin,
|
state.config.edge_margin,
|
||||||
@@ -955,6 +959,8 @@ pub fn main() !void {
|
|||||||
|
|
||||||
// Load last saved username and desktop selection, if any
|
// Load last saved username and desktop selection, if any
|
||||||
// Skip if autologin is active to prevent overriding autologin session
|
// Skip if autologin is active to prevent overriding autologin session
|
||||||
|
var default_input = state.config.default_input;
|
||||||
|
|
||||||
if (state.config.save and !state.is_autologin) {
|
if (state.config.save and !state.is_autologin) {
|
||||||
if (state.saved_users.last_username_index) |index| load_last_user: {
|
if (state.saved_users.last_username_index) |index| load_last_user: {
|
||||||
// If the saved index isn't valid, bail out
|
// If the saved index isn't valid, bail out
|
||||||
@@ -971,7 +977,7 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.active_input = .password;
|
default_input = .password;
|
||||||
|
|
||||||
state.session.label.current = @min(user.session_index, state.session.label.list.items.len - 1);
|
state.session.label.current = @min(user.session_index, state.session.label.list.items.len - 1);
|
||||||
}
|
}
|
||||||
@@ -979,6 +985,10 @@ pub fn main() !void {
|
|||||||
|
|
||||||
// TODO: Layer system where we can put widgets in specific layers (to
|
// TODO: Layer system where we can put widgets in specific layers (to
|
||||||
// allow certain widgets to be below or above others, like animations)
|
// allow certain widgets to be below or above others, like animations)
|
||||||
|
const info_line_widget = state.info_line.widget();
|
||||||
|
const session_widget = state.session.widget();
|
||||||
|
const login_widget = state.login.widget();
|
||||||
|
|
||||||
var widgets: std.ArrayList(Widget) = .empty;
|
var widgets: std.ArrayList(Widget) = .empty;
|
||||||
defer widgets.deinit(state.allocator);
|
defer widgets.deinit(state.allocator);
|
||||||
|
|
||||||
@@ -1012,13 +1022,13 @@ pub fn main() !void {
|
|||||||
try widgets.append(state.allocator, state.capslock_label.widget());
|
try widgets.append(state.allocator, state.capslock_label.widget());
|
||||||
}
|
}
|
||||||
try widgets.append(state.allocator, state.box.widget());
|
try widgets.append(state.allocator, state.box.widget());
|
||||||
try widgets.append(state.allocator, state.info_line.widget());
|
try widgets.append(state.allocator, info_line_widget);
|
||||||
try widgets.append(state.allocator, state.session_specifier_label.widget());
|
try widgets.append(state.allocator, state.session_specifier_label.widget());
|
||||||
try widgets.append(state.allocator, state.session.widget());
|
try widgets.append(state.allocator, session_widget);
|
||||||
try widgets.append(state.allocator, state.login_label.widget());
|
try widgets.append(state.allocator, state.login_label.widget());
|
||||||
try widgets.append(state.allocator, state.login.widget());
|
try widgets.append(state.allocator, login_widget);
|
||||||
try widgets.append(state.allocator, state.password_label.widget());
|
try widgets.append(state.allocator, state.password_label.widget());
|
||||||
try widgets.append(state.allocator, state.password.widget());
|
try widgets.append(state.allocator, state.password_widget);
|
||||||
if (!state.config.hide_version_string) {
|
if (!state.config.hide_version_string) {
|
||||||
try widgets.append(state.allocator, state.version_label.widget());
|
try widgets.append(state.allocator, state.version_label.widget());
|
||||||
}
|
}
|
||||||
@@ -1026,28 +1036,6 @@ pub fn main() !void {
|
|||||||
try widgets.append(state.allocator, cascade.widget());
|
try widgets.append(state.allocator, cascade.widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position components and place cursor accordingly
|
|
||||||
for (widgets.items) |*widget| try widget.update(&state);
|
|
||||||
positionComponents(&state);
|
|
||||||
|
|
||||||
switch (state.active_input) {
|
|
||||||
.info_line => state.info_line.label.handle(null, state.insert_mode),
|
|
||||||
.session => state.session.label.handle(null, state.insert_mode),
|
|
||||||
.login => state.login.label.handle(null, state.insert_mode),
|
|
||||||
.password => state.password.handle(null, state.insert_mode) catch |err| {
|
|
||||||
try state.info_line.addMessage(
|
|
||||||
state.lang.err_alloc,
|
|
||||||
state.config.error_bg,
|
|
||||||
state.config.error_fg,
|
|
||||||
);
|
|
||||||
try state.log_file.err(
|
|
||||||
"tui",
|
|
||||||
"failed to handle password input: {s}",
|
|
||||||
.{@errorName(err)},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
try state.buffer.registerKeybind("Esc", &disableInsertMode);
|
try state.buffer.registerKeybind("Esc", &disableInsertMode);
|
||||||
try state.buffer.registerKeybind("I", &enableInsertMode);
|
try state.buffer.registerKeybind("I", &enableInsertMode);
|
||||||
|
|
||||||
@@ -1057,11 +1045,11 @@ pub fn main() !void {
|
|||||||
|
|
||||||
try state.buffer.registerKeybind("Ctrl+K", &moveCursorUp);
|
try state.buffer.registerKeybind("Ctrl+K", &moveCursorUp);
|
||||||
try state.buffer.registerKeybind("Up", &moveCursorUp);
|
try state.buffer.registerKeybind("Up", &moveCursorUp);
|
||||||
try state.buffer.registerKeybind("J", &viMoseCursorUp);
|
try state.buffer.registerKeybind("K", &viMoveCursorUp);
|
||||||
|
|
||||||
try state.buffer.registerKeybind("Ctrl+J", &moveCursorDown);
|
try state.buffer.registerKeybind("Ctrl+J", &moveCursorDown);
|
||||||
try state.buffer.registerKeybind("Down", &moveCursorDown);
|
try state.buffer.registerKeybind("Down", &moveCursorDown);
|
||||||
try state.buffer.registerKeybind("K", &viMoveCursorDown);
|
try state.buffer.registerKeybind("J", &viMoseCursorDown);
|
||||||
|
|
||||||
try state.buffer.registerKeybind("Tab", &wrapCursor);
|
try state.buffer.registerKeybind("Tab", &wrapCursor);
|
||||||
try state.buffer.registerKeybind("Shift+Tab", &wrapCursorReverse);
|
try state.buffer.registerKeybind("Shift+Tab", &wrapCursorReverse);
|
||||||
@@ -1104,21 +1092,51 @@ pub fn main() !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Position components and place cursor accordingly
|
||||||
if (state.is_autologin) _ = try authenticate(&state);
|
if (state.is_autologin) _ = try authenticate(&state);
|
||||||
|
|
||||||
|
const active_widget = switch (default_input) {
|
||||||
|
.info_line => info_line_widget,
|
||||||
|
.session => session_widget,
|
||||||
|
.login => login_widget,
|
||||||
|
.password => state.password_widget,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run the event loop
|
||||||
|
state.handlable_widgets = .empty;
|
||||||
|
defer state.handlable_widgets.deinit(state.allocator);
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
for (widgets.items) |*widget| {
|
||||||
|
if (widget.vtable.handle_fn != null) {
|
||||||
|
try state.handlable_widgets.append(state.allocator, widget);
|
||||||
|
|
||||||
|
if (widget.id == active_widget.id) state.active_widget_index = i;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (widgets.items) |*widget| try widget.update(&state);
|
||||||
|
positionComponents(&state);
|
||||||
|
|
||||||
while (state.run) {
|
while (state.run) {
|
||||||
if (state.update) {
|
if (state.update) {
|
||||||
for (widgets.items) |*widget| try widget.update(&state);
|
for (widgets.items) |*widget| try widget.update(&state);
|
||||||
|
|
||||||
switch (state.active_input) {
|
// Reset cursor
|
||||||
.info_line => state.info_line.label.handle(null, state.insert_mode),
|
const current_widget = getActiveWidget(&state);
|
||||||
.session => state.session.label.handle(null, state.insert_mode),
|
current_widget.handle(null, state.insert_mode) catch |err| {
|
||||||
.login => state.login.label.handle(null, state.insert_mode),
|
try state.info_line.addMessage(
|
||||||
.password => state.password.handle(null, state.insert_mode) catch |err| {
|
state.lang.err_alloc,
|
||||||
try state.info_line.addMessage(state.lang.err_alloc, state.config.error_bg, state.config.error_fg);
|
state.config.error_bg,
|
||||||
try state.log_file.err("tui", "failed to handle password input: {s}", .{@errorName(err)});
|
state.config.error_fg,
|
||||||
},
|
);
|
||||||
}
|
try state.log_file.err(
|
||||||
|
"tui",
|
||||||
|
"failed to set cursor in active widget: {s}",
|
||||||
|
.{@errorName(err)},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
try TerminalBuffer.clearScreen(false);
|
try TerminalBuffer.clearScreen(false);
|
||||||
|
|
||||||
@@ -1237,19 +1255,20 @@ pub fn main() !void {
|
|||||||
if (maybe_keys) |*keys| {
|
if (maybe_keys) |*keys| {
|
||||||
defer keys.deinit(state.allocator);
|
defer keys.deinit(state.allocator);
|
||||||
|
|
||||||
|
const current_widget = getActiveWidget(&state);
|
||||||
for (keys.items) |key| {
|
for (keys.items) |key| {
|
||||||
switch (state.active_input) {
|
current_widget.handle(key, state.insert_mode) catch |err| {
|
||||||
.info_line => state.info_line.label.handle(key, state.insert_mode),
|
try state.info_line.addMessage(
|
||||||
.session => state.session.label.handle(key, state.insert_mode),
|
state.lang.err_alloc,
|
||||||
.login => state.login.label.handle(key, state.insert_mode),
|
state.config.error_bg,
|
||||||
.password => state.password.handle(key, state.insert_mode) catch {
|
state.config.error_fg,
|
||||||
try state.info_line.addMessage(
|
);
|
||||||
state.lang.err_alloc,
|
try state.log_file.err(
|
||||||
state.config.error_bg,
|
"tui",
|
||||||
state.config.error_fg,
|
"failed to handle active widget: {s}",
|
||||||
);
|
.{@errorName(err)},
|
||||||
},
|
);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
state.update = true;
|
state.update = true;
|
||||||
@@ -1257,6 +1276,16 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn getActiveWidget(state: *UiState) *Widget {
|
||||||
|
return state.handlable_widgets.items[state.active_widget_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setActiveWidget(state: *UiState, widget: *Widget) void {
|
||||||
|
for (state.handlable_widgets.items, 0..) |widg, i| {
|
||||||
|
if (widg.id == widget.id) state.active_widget_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn disableInsertMode(ptr: *anyopaque) !bool {
|
fn disableInsertMode(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
@@ -1279,7 +1308,7 @@ fn enableInsertMode(ptr: *anyopaque) !bool {
|
|||||||
fn clearPassword(ptr: *anyopaque) !bool {
|
fn clearPassword(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (state.active_input == .password) {
|
if (getActiveWidget(state) == &state.password_widget) {
|
||||||
state.password.clear();
|
state.password.clear();
|
||||||
state.update = true;
|
state.update = true;
|
||||||
}
|
}
|
||||||
@@ -1288,34 +1317,38 @@ fn clearPassword(ptr: *anyopaque) !bool {
|
|||||||
|
|
||||||
fn moveCursorUp(ptr: *anyopaque) !bool {
|
fn moveCursorUp(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
if (state.active_widget_index == 0) return false;
|
||||||
|
|
||||||
state.active_input.move(true, false);
|
state.active_widget_index -= 1;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn viMoseCursorUp(ptr: *anyopaque) !bool {
|
fn viMoveCursorUp(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
if (state.insert_mode) return true;
|
if (state.insert_mode) return true;
|
||||||
|
if (state.active_widget_index == 0) return false;
|
||||||
|
|
||||||
state.active_input.move(false, false);
|
state.active_widget_index -= 1;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn moveCursorDown(ptr: *anyopaque) !bool {
|
fn moveCursorDown(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
if (state.active_widget_index == state.handlable_widgets.items.len - 1) return false;
|
||||||
|
|
||||||
state.active_input.move(false, false);
|
state.active_widget_index += 1;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn viMoveCursorDown(ptr: *anyopaque) !bool {
|
fn viMoseCursorDown(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
if (state.insert_mode) return true;
|
if (state.insert_mode) return true;
|
||||||
|
if (state.active_widget_index == state.handlable_widgets.items.len - 1) return false;
|
||||||
|
|
||||||
state.active_input.move(true, false);
|
state.active_widget_index += 1;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1323,7 +1356,7 @@ fn viMoveCursorDown(ptr: *anyopaque) !bool {
|
|||||||
fn wrapCursor(ptr: *anyopaque) !bool {
|
fn wrapCursor(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
state.active_input.move(false, true);
|
state.active_widget_index = (state.active_widget_index + 1) % state.handlable_widgets.items.len;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1331,7 +1364,7 @@ fn wrapCursor(ptr: *anyopaque) !bool {
|
|||||||
fn wrapCursorReverse(ptr: *anyopaque) !bool {
|
fn wrapCursorReverse(ptr: *anyopaque) !bool {
|
||||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
state.active_input.move(true, true);
|
state.active_widget_index = (state.active_widget_index - 1) % state.handlable_widgets.items.len;
|
||||||
state.update = true;
|
state.update = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1500,7 +1533,7 @@ fn authenticate(ptr: *anyopaque) !bool {
|
|||||||
const auth_err = shared_err.readError();
|
const auth_err = shared_err.readError();
|
||||||
if (auth_err) |err| {
|
if (auth_err) |err| {
|
||||||
state.auth_fails += 1;
|
state.auth_fails += 1;
|
||||||
state.active_input = .password;
|
setActiveWidget(state, &state.password_widget);
|
||||||
|
|
||||||
try state.info_line.addMessage(
|
try state.info_line.addMessage(
|
||||||
getAuthErrorMsg(err, state.lang),
|
getAuthErrorMsg(err, state.lang),
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ const keyboard = @import("keyboard.zig");
|
|||||||
const TerminalBuffer = @import("TerminalBuffer.zig");
|
const TerminalBuffer = @import("TerminalBuffer.zig");
|
||||||
|
|
||||||
const VTable = struct {
|
const VTable = struct {
|
||||||
deinit_fn: *const fn (ptr: *anyopaque) void,
|
deinit_fn: ?*const fn (ptr: *anyopaque) void,
|
||||||
realloc_fn: *const fn (ptr: *anyopaque) anyerror!void,
|
realloc_fn: ?*const fn (ptr: *anyopaque) anyerror!void,
|
||||||
draw_fn: *const fn (ptr: *anyopaque) void,
|
draw_fn: *const fn (ptr: *anyopaque) void,
|
||||||
update_fn: *const fn (ptr: *anyopaque, ctx: *anyopaque) anyerror!void,
|
update_fn: ?*const fn (ptr: *anyopaque, ctx: *anyopaque) anyerror!void,
|
||||||
handle_fn: *const fn (ptr: *anyopaque, maybe_key: ?keyboard.Key, insert_mode: bool) anyerror!void,
|
handle_fn: ?*const fn (ptr: *anyopaque, maybe_key: ?keyboard.Key, insert_mode: bool) anyerror!void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
id: u64,
|
||||||
pointer: *anyopaque,
|
pointer: *anyopaque,
|
||||||
vtable: VTable,
|
vtable: VTable,
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ pub fn init(
|
|||||||
pointer: anytype,
|
pointer: anytype,
|
||||||
comptime deinit_fn: ?fn (ptr: @TypeOf(pointer)) void,
|
comptime deinit_fn: ?fn (ptr: @TypeOf(pointer)) void,
|
||||||
comptime realloc_fn: ?fn (ptr: @TypeOf(pointer)) anyerror!void,
|
comptime realloc_fn: ?fn (ptr: @TypeOf(pointer)) anyerror!void,
|
||||||
comptime draw_fn: ?fn (ptr: @TypeOf(pointer)) void,
|
comptime draw_fn: fn (ptr: @TypeOf(pointer)) void,
|
||||||
comptime update_fn: ?fn (ptr: @TypeOf(pointer), ctx: *anyopaque) anyerror!void,
|
comptime update_fn: ?fn (ptr: @TypeOf(pointer), ctx: *anyopaque) anyerror!void,
|
||||||
comptime handle_fn: ?fn (ptr: @TypeOf(pointer), maybe_key: ?keyboard.Key, insert_mode: bool) anyerror!void,
|
comptime handle_fn: ?fn (ptr: @TypeOf(pointer), maybe_key: ?keyboard.Key, insert_mode: bool) anyerror!void,
|
||||||
) Widget {
|
) Widget {
|
||||||
@@ -27,73 +28,64 @@ pub fn init(
|
|||||||
pub fn deinitImpl(ptr: *anyopaque) void {
|
pub fn deinitImpl(ptr: *anyopaque) void {
|
||||||
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (deinit_fn) |func| {
|
return @call(
|
||||||
return @call(
|
.always_inline,
|
||||||
.always_inline,
|
deinit_fn.?,
|
||||||
func,
|
.{impl},
|
||||||
.{impl},
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reallocImpl(ptr: *anyopaque) !void {
|
pub fn reallocImpl(ptr: *anyopaque) !void {
|
||||||
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (realloc_fn) |func| {
|
return @call(
|
||||||
return @call(
|
.always_inline,
|
||||||
.always_inline,
|
realloc_fn.?,
|
||||||
func,
|
.{impl},
|
||||||
.{impl},
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawImpl(ptr: *anyopaque) void {
|
pub fn drawImpl(ptr: *anyopaque) void {
|
||||||
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (draw_fn) |func| {
|
return @call(
|
||||||
return @call(
|
.always_inline,
|
||||||
.always_inline,
|
draw_fn,
|
||||||
func,
|
.{impl},
|
||||||
.{impl},
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateImpl(ptr: *anyopaque, ctx: *anyopaque) !void {
|
pub fn updateImpl(ptr: *anyopaque, ctx: *anyopaque) !void {
|
||||||
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (update_fn) |func| {
|
return @call(
|
||||||
return @call(
|
.always_inline,
|
||||||
.always_inline,
|
update_fn.?,
|
||||||
func,
|
.{ impl, ctx },
|
||||||
.{ impl, ctx },
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handleImpl(ptr: *anyopaque, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
|
pub fn handleImpl(ptr: *anyopaque, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
|
||||||
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
if (handle_fn) |func| {
|
return @call(
|
||||||
return @call(
|
.always_inline,
|
||||||
.always_inline,
|
handle_fn.?,
|
||||||
func,
|
.{ impl, maybe_key, insert_mode },
|
||||||
.{ impl, maybe_key, insert_mode },
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const vtable = VTable{
|
const vtable = VTable{
|
||||||
.deinit_fn = deinitImpl,
|
.deinit_fn = if (deinit_fn != null) deinitImpl else null,
|
||||||
.realloc_fn = reallocImpl,
|
.realloc_fn = if (realloc_fn != null) reallocImpl else null,
|
||||||
.draw_fn = drawImpl,
|
.draw_fn = drawImpl,
|
||||||
.update_fn = updateImpl,
|
.update_fn = if (update_fn != null) updateImpl else null,
|
||||||
.handle_fn = handleImpl,
|
.handle_fn = if (handle_fn != null) handleImpl else null,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
.id = @intFromPtr(Impl.vtable.draw_fn),
|
||||||
.pointer = pointer,
|
.pointer = pointer,
|
||||||
.vtable = Impl.vtable,
|
.vtable = Impl.vtable,
|
||||||
};
|
};
|
||||||
@@ -102,27 +94,31 @@ pub fn init(
|
|||||||
pub fn deinit(self: *Widget) void {
|
pub fn deinit(self: *Widget) void {
|
||||||
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
|
||||||
return @call(
|
if (self.vtable.deinit_fn) |deinit_fn| {
|
||||||
.auto,
|
return @call(
|
||||||
self.vtable.deinit_fn,
|
.auto,
|
||||||
.{impl},
|
deinit_fn,
|
||||||
);
|
.{impl},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn realloc(self: *Widget) !void {
|
pub fn realloc(self: *Widget) !void {
|
||||||
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
|
||||||
return @call(
|
if (self.vtable.realloc_fn) |realloc_fn| {
|
||||||
.auto,
|
return @call(
|
||||||
self.vtable.realloc_fn,
|
.auto,
|
||||||
.{impl},
|
realloc_fn,
|
||||||
);
|
.{impl},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *Widget) void {
|
pub fn draw(self: *Widget) void {
|
||||||
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
|
||||||
return @call(
|
@call(
|
||||||
.auto,
|
.auto,
|
||||||
self.vtable.draw_fn,
|
self.vtable.draw_fn,
|
||||||
.{impl},
|
.{impl},
|
||||||
@@ -132,19 +128,23 @@ pub fn draw(self: *Widget) void {
|
|||||||
pub fn update(self: *Widget, ctx: *anyopaque) !void {
|
pub fn update(self: *Widget, ctx: *anyopaque) !void {
|
||||||
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
|
||||||
return @call(
|
if (self.vtable.update_fn) |update_fn| {
|
||||||
.auto,
|
return @call(
|
||||||
self.vtable.update_fn,
|
.auto,
|
||||||
.{ impl, ctx },
|
update_fn,
|
||||||
);
|
.{ impl, ctx },
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(self: *Widget, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
|
pub fn handle(self: *Widget, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
|
||||||
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
||||||
|
|
||||||
return @call(
|
if (self.vtable.handle_fn) |handle_fn| {
|
||||||
.auto,
|
return @call(
|
||||||
self.vtable.handle_fn,
|
.auto,
|
||||||
.{ impl, maybe_key, insert_mode },
|
handle_fn,
|
||||||
);
|
.{ impl, maybe_key, insert_mode },
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user