Completely refactor widget placement code

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-02-08 14:53:36 +01:00
parent 8c08359e51
commit bca38856b1
9 changed files with 477 additions and 209 deletions

View File

@@ -1,12 +1,13 @@
const std = @import("std");
const TerminalBuffer = @import("../TerminalBuffer.zig");
const Position = @import("../Position.zig");
pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) type {
return struct {
const Allocator = std.mem.Allocator;
const ItemList = std.ArrayListUnmanaged(ItemType);
const DrawItemFn = *const fn (*Self, ItemType, usize, usize) bool;
const DrawItemFn = *const fn (*Self, ItemType, usize, usize, usize) void;
const ChangeItemFn = *const fn (ItemType, ?ChangeItemType) void;
const termbox = TerminalBuffer.termbox;
@@ -17,26 +18,34 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
buffer: *TerminalBuffer,
list: ItemList,
current: usize,
visible_length: usize,
x: usize,
y: usize,
first_char_x: usize,
width: usize,
component_pos: Position,
children_pos: Position,
text_in_center: bool,
item_width: usize,
draw_item_fn: DrawItemFn,
change_item_fn: ?ChangeItemFn,
change_item_arg: ?ChangeItemType,
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, draw_item_fn: DrawItemFn, change_item_fn: ?ChangeItemFn, change_item_arg: ?ChangeItemType) Self {
pub fn init(
allocator: Allocator,
buffer: *TerminalBuffer,
draw_item_fn: DrawItemFn,
change_item_fn: ?ChangeItemFn,
change_item_arg: ?ChangeItemType,
width: usize,
text_in_center: bool,
) Self {
return .{
.allocator = allocator,
.buffer = buffer,
.list = .empty,
.current = 0,
.visible_length = 0,
.x = 0,
.y = 0,
.first_char_x = 0,
.text_in_center = false,
.width = width,
.component_pos = TerminalBuffer.START_POSITION,
.children_pos = TerminalBuffer.START_POSITION,
.text_in_center = text_in_center,
.item_width = 0,
.draw_item_fn = draw_item_fn,
.change_item_fn = change_item_fn,
.change_item_arg = change_item_arg,
@@ -47,14 +56,29 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
self.list.deinit(self.allocator);
}
pub fn position(self: *Self, x: usize, y: usize, visible_length: usize, text_in_center: ?bool) void {
self.x = x;
self.y = y;
self.visible_length = visible_length;
self.first_char_x = x + 2;
if (text_in_center) |value| {
self.text_in_center = value;
}
pub fn positionX(self: *Self, original_pos: Position) void {
self.component_pos = original_pos;
self.item_width = self.component_pos.x + 2;
self.children_pos = original_pos.addX(self.width);
}
pub fn positionY(self: *Self, original_pos: Position) void {
self.component_pos = original_pos;
self.item_width = self.component_pos.x + 2;
self.children_pos = original_pos.addY(1);
}
pub fn positionXY(self: *Self, original_pos: Position) void {
self.component_pos = original_pos;
self.item_width = self.component_pos.x + 2;
self.children_pos = Position.init(
self.width,
1,
).add(original_pos);
}
pub fn childrenPosition(self: Self) Position {
return self.children_pos;
}
pub fn addItem(self: *Self, item: ItemType) !void {
@@ -81,28 +105,51 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
}
}
_ = termbox.tb_set_cursor(@intCast(self.first_char_x), @intCast(self.y));
_ = termbox.tb_set_cursor(
@intCast(self.component_pos.x + self.item_width + 2),
@intCast(self.component_pos.y),
);
}
pub fn draw(self: *Self) void {
if (self.list.items.len == 0) return;
_ = termbox.tb_set_cell(
@intCast(self.component_pos.x),
@intCast(self.component_pos.y),
'<',
self.buffer.fg,
self.buffer.bg,
);
_ = termbox.tb_set_cell(
@intCast(self.component_pos.x + self.width - 1),
@intCast(self.component_pos.y),
'>',
self.buffer.fg,
self.buffer.bg,
);
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 x = self.component_pos.x + 2;
const y = self.component_pos.y;
const width = self.width - 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);
@call(
.auto,
self.draw_item_fn,
.{ self, current_item, x, y, width },
);
}
fn goLeft(self: *Self) void {
self.current = if (self.current == 0) self.list.items.len - 1 else self.current - 1;
if (self.change_item_fn) |change_item_fn| {
@call(.auto, change_item_fn, .{ self.list.items[self.current], self.change_item_arg });
@call(
.auto,
change_item_fn,
.{ self.list.items[self.current], self.change_item_arg },
);
}
}
@@ -110,7 +157,11 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
self.current = if (self.current == self.list.items.len - 1) 0 else self.current + 1;
if (self.change_item_fn) |change_item_fn| {
@call(.auto, change_item_fn, .{ self.list.items[self.current], self.change_item_arg });
@call(
.auto,
change_item_fn,
.{ self.list.items[self.current], self.change_item_arg },
);
}
}
};