From 3437f4fd20d5aa3110fcf13f46577da41d25ef3a Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 6 Nov 2025 18:16:16 +0100 Subject: [PATCH] refactor: add focus/unfocus to widget vtable --- src/tui/Widget.zig | 26 ++++++++++++++++++++++++++ src/tui/WidgetList.zig | 8 ++++++++ src/tui/WidgetStack.zig | 8 ++++++++ 3 files changed, 42 insertions(+) diff --git a/src/tui/Widget.zig b/src/tui/Widget.zig index a9035ca..3e209ce 100644 --- a/src/tui/Widget.zig +++ b/src/tui/Widget.zig @@ -53,6 +53,8 @@ pub const VTable = struct { unsubscribe: *const fn (ctx: *anyopaque, h: EventHandler) error{NotSupported}!void, get: *const fn (ctx: *anyopaque, name_: []const u8) ?*Self, walk: *const fn (ctx: *anyopaque, walk_ctx: *anyopaque, f: WalkFn, self_widget: *Self) bool, + focus: *const fn (ctx: *anyopaque) void, + unfocus: *const fn (ctx: *anyopaque) void, hover: *const fn (ctx: *anyopaque) bool, type_name: []const u8, }; @@ -141,6 +143,16 @@ pub fn to(pimpl: anytype) Self { return if (comptime @hasDecl(child, "walk")) child.walk(@as(*child, @ptrCast(@alignCast(ctx))), walk_ctx, f, self) else false; } }.walk, + .focus = struct { + pub fn focus(ctx: *anyopaque) void { + if (comptime @hasDecl(child, "focus")) @as(*child, @ptrCast(@alignCast(ctx))).focus(); + } + }.focus, + .unfocus = struct { + pub fn unfocus(ctx: *anyopaque) void { + if (comptime @hasDecl(child, "unfocus")) @as(*child, @ptrCast(@alignCast(ctx))).unfocus(); + } + }.unfocus, .hover = struct { pub fn hover(ctx: *anyopaque) bool { return if (comptime @hasField(child, "hover")) @as(*child, @ptrCast(@alignCast(ctx))).hover else false; @@ -222,6 +234,14 @@ pub fn walk(self: *Self, walk_ctx: *anyopaque, f: WalkFn) bool { return if (self.vtable.walk(self.ptr, walk_ctx, f, self)) true else f(walk_ctx, self); } +pub fn focus(self: *Self) void { + self.vtable.focus(self.ptr); +} + +pub fn unfocus(self: *Self) void { + self.vtable.unfocus(self.ptr); +} + pub fn hover(self: *Self) bool { return self.vtable.hover(self.ptr); } @@ -286,6 +306,12 @@ pub fn empty(allocator: Allocator, parent: Plane, layout_: Layout) !Self { return false; } }.walk, + .focus = struct { + pub fn focus(_: *anyopaque) void {} + }.focus, + .unfocus = struct { + pub fn unfocus(_: *anyopaque) void {} + }.unfocus, .hover = struct { pub fn hover(_: *anyopaque) bool { return false; diff --git a/src/tui/WidgetList.zig b/src/tui/WidgetList.zig index df43c03..300a4cc 100644 --- a/src/tui/WidgetList.zig +++ b/src/tui/WidgetList.zig @@ -404,6 +404,14 @@ pub fn walk(self: *Self, ctx: *anyopaque, f: Widget.WalkFn, self_w: *Widget) boo return f(ctx, self_w); } +pub fn focus(self: *Self) void { + for (self.widgets.items) |*w| w.widget.focus(); +} + +pub fn unfocus(self: *Self) void { + for (self.widgets.items) |*w| w.widget.unfocus(); +} + pub fn hover(self: *Self) bool { for (self.widgets.items) |*w| if (w.widget.hover()) return true; return false; diff --git a/src/tui/WidgetStack.zig b/src/tui/WidgetStack.zig index cfbeddc..b1e0e11 100644 --- a/src/tui/WidgetStack.zig +++ b/src/tui/WidgetStack.zig @@ -100,3 +100,11 @@ pub fn walk(self: *Self, walk_ctx: *anyopaque, f: Widget.WalkFn) bool { } return false; } + +pub fn focus(self: *Self) void { + for (self.widgets.items) |*w| w.widget.focus(); +} + +pub fn unfocus(self: *Self) void { + for (self.widgets.items) |*w| w.widget.unfocus(); +}