mirror of https://github.com/fairyglade/ly.git
111 lines
3.7 KiB
Zig
111 lines
3.7 KiB
Zig
const std = @import("std");
|
|
const enums = @import("../../enums.zig");
|
|
const interop = @import("../../interop.zig");
|
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
|
|
|
pub fn CyclableLabel(comptime ItemType: type) type {
|
|
return struct {
|
|
const Allocator = std.mem.Allocator;
|
|
const ItemList = std.ArrayList(ItemType);
|
|
const DrawItemFn = *const fn (*Self, ItemType, usize, usize) bool;
|
|
|
|
const termbox = interop.termbox;
|
|
|
|
const Self = @This();
|
|
|
|
allocator: Allocator,
|
|
buffer: *TerminalBuffer,
|
|
list: ItemList,
|
|
current: usize,
|
|
visible_length: usize,
|
|
x: usize,
|
|
y: usize,
|
|
first_char_x: usize,
|
|
draw_item_fn: DrawItemFn,
|
|
|
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, max_length: usize, draw_item_fn: DrawItemFn) !Self {
|
|
return .{
|
|
.allocator = allocator,
|
|
.buffer = buffer,
|
|
.list = try ItemList.initCapacity(allocator, max_length),
|
|
.current = 0,
|
|
.visible_length = 0,
|
|
.x = 0,
|
|
.y = 0,
|
|
.first_char_x = 0,
|
|
.draw_item_fn = draw_item_fn,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: Self) void {
|
|
self.list.deinit();
|
|
}
|
|
|
|
pub fn position(self: *Self, x: usize, y: usize, visible_length: usize) void {
|
|
self.x = x;
|
|
self.y = y;
|
|
self.visible_length = visible_length;
|
|
self.first_char_x = x + 2;
|
|
}
|
|
|
|
pub fn addItem(self: *Self, item: ItemType) !void {
|
|
try self.list.append(item);
|
|
self.current = self.list.items.len - 1;
|
|
}
|
|
|
|
pub fn handle(self: *Self, maybe_event: ?*termbox.tb_event, insert_mode: bool) void {
|
|
if (maybe_event) |event| blk: {
|
|
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
|
|
|
switch (event.key) {
|
|
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
|
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
|
else => {
|
|
if (!insert_mode) {
|
|
switch (event.ch) {
|
|
'h' => self.goLeft(),
|
|
'l' => self.goRight(),
|
|
else => {},
|
|
}
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
_ = termbox.tb_set_cursor(@intCast(self.first_char_x), @intCast(self.y));
|
|
}
|
|
|
|
pub fn draw(self: *Self) void {
|
|
if (self.list.items.len == 0) return;
|
|
|
|
const current_item = self.list.items[self.current];
|
|
const x = self.buffer.box_x + self.buffer.margin_box_h;
|
|
const y = self.buffer.box_y + self.buffer.margin_box_v + 2;
|
|
|
|
const continue_drawing = @call(.auto, self.draw_item_fn, .{ self, current_item, x, y });
|
|
if (!continue_drawing) return;
|
|
|
|
_ = termbox.tb_set_cell(@intCast(self.x), @intCast(self.y), '<', self.buffer.fg, self.buffer.bg);
|
|
_ = termbox.tb_set_cell(@intCast(self.x + self.visible_length - 1), @intCast(self.y), '>', self.buffer.fg, self.buffer.bg);
|
|
}
|
|
|
|
fn goLeft(self: *Self) void {
|
|
if (self.current == 0) {
|
|
self.current = self.list.items.len - 1;
|
|
return;
|
|
}
|
|
|
|
self.current -= 1;
|
|
}
|
|
|
|
fn goRight(self: *Self) void {
|
|
if (self.current == self.list.items.len - 1) {
|
|
self.current = 0;
|
|
return;
|
|
}
|
|
|
|
self.current += 1;
|
|
}
|
|
};
|
|
}
|