feat: add support for input box icons

This commit is contained in:
CJ van den Berg 2025-08-13 17:35:04 +02:00
parent 4d2c7d8a8c
commit 92b1354d4d
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
2 changed files with 13 additions and 4 deletions

View file

@ -12,6 +12,8 @@ pub fn Options(context: type) type {
label: []const u8 = "Enter text",
pos: Widget.Box = .{ .y = 0, .x = 0, .w = 12, .h = 1 },
ctx: Context,
padding: u8 = 1,
icon: ?[]const u8 = null,
on_click: *const fn (ctx: context, button: *State(Context)) void = do_nothing,
on_render: *const fn (ctx: context, button: *State(Context), theme: *const Widget.Theme) bool = on_render_default,
@ -29,18 +31,21 @@ pub fn Options(context: type) type {
self.plane.set_style(style_label);
self.plane.fill(" ");
self.plane.home();
for (0..self.opts.padding) |_| _ = self.plane.putchar(" ");
if (self.opts.icon) |icon|
_ = self.plane.print("{s}", .{icon}) catch {};
if (self.text.items.len > 0) {
_ = self.plane.print(" {s} ", .{self.text.items}) catch {};
_ = self.plane.print("{s} ", .{self.text.items}) catch {};
} else {
_ = self.plane.print(" {s} ", .{self.label.items}) catch {};
_ = self.plane.print("{s} ", .{self.label.items}) catch {};
}
if (self.cursor) |cursor| {
const pos: c_int = @intCast(cursor);
if (tui.config().enable_terminal_cursor) {
const y, const x = self.plane.rel_yx_to_abs(0, pos + 1);
const y, const x = self.plane.rel_yx_to_abs(0, pos + self.opts.padding + self.icon_width);
tui.rdr().cursor_enable(y, x, tui.get_cursor_shape()) catch {};
} else {
self.plane.cursor_move_yx(0, pos + 1) catch return false;
self.plane.cursor_move_yx(0, pos + self.opts.padding + self.icon_width) catch return false;
var cell = self.plane.cell_init();
_ = self.plane.at_cursor_cell(&cell) catch return false;
cell.set_style(theme.editor_cursor);
@ -68,6 +73,7 @@ pub fn create(ctx_type: type, allocator: std.mem.Allocator, parent: Plane, opts:
.opts = opts,
.label = std.ArrayList(u8).init(allocator),
.text = std.ArrayList(u8).init(allocator),
.icon_width = @intCast(if (opts.icon) |icon| n.egc_chunk_width(icon, 0, 1) else 0),
};
try self.label.appendSlice(self.opts.label);
self.opts.label = self.label.items;
@ -83,6 +89,7 @@ pub fn State(ctx_type: type) type {
label: std.ArrayList(u8),
opts: Options(ctx_type),
text: std.ArrayList(u8),
icon_width: c_int,
cursor: ?usize = 0,
const Self = @This();

View file

@ -70,6 +70,8 @@ pub fn Create(options: type) type {
.inputbox = (try self.menu.add_header(try InputBox.create(*Self, self.allocator, self.menu.menu.parent, .{
.ctx = self,
.label = options.label,
.padding = 2,
.icon = if (@hasDecl(options, "icon")) options.icon else null,
}))).dynamic_cast(InputBox.State(*Self)) orelse unreachable,
.view_rows = get_view_rows(tui.screen()),
.entries = std.ArrayList(Entry).init(allocator),