mirror of
https://github.com/fairyglade/ly.git
synced 2026-03-24 17:26:04 +00:00
Add Label component & make colors custom
This commit also makes Ly more resilient to (impossible) screen resolutions. Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
@@ -17,6 +17,13 @@ pub fn add(self: Position, other: Position) Position {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x + if (condition) other.x else 0,
|
||||
.y = self.y + if (condition) other.y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addX(self: Position, x: usize) Position {
|
||||
return .{
|
||||
.x = self.x + x,
|
||||
@@ -30,3 +37,185 @@ pub fn addY(self: Position, y: usize) Position {
|
||||
.y = self.y + y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addXIf(self: Position, x: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x + if (condition) x else 0,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addYIf(self: Position, y: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y + if (condition) y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addXFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x + other.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addYFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y + other.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addXFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x + if (condition) other.x else 0,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addYFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y + if (condition) other.y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn remove(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x - other.x,
|
||||
.y = self.y - other.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x - if (condition) other.x else 0,
|
||||
.y = self.y - if (condition) other.y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeX(self: Position, x: usize) Position {
|
||||
return .{
|
||||
.x = self.x - x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeY(self: Position, y: usize) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y - y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeXIf(self: Position, x: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x - if (condition) x else 0,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeYIf(self: Position, y: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y - if (condition) y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeXFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x - other.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeYFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y - other.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeXFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x - if (condition) other.x else 0,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn removeYFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = self.y - if (condition) other.y else 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invert(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = other.x - self.x,
|
||||
.y = other.y - self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invertIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = if (condition) other.x - self.x else self.x,
|
||||
.y = if (condition) other.y - self.y else self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invertX(self: Position, width: usize) Position {
|
||||
return .{
|
||||
.x = width - self.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invertY(self: Position, height: usize) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = height - self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invertXIf(self: Position, width: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = if (condition) width - self.x else self.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn invertYIf(self: Position, height: usize, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = if (condition) height - self.y else self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resetXFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = other.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resetYFrom(self: Position, other: Position) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = other.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resetXFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = if (condition) other.x else self.x,
|
||||
.y = self.y,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resetYFromIf(self: Position, other: Position, condition: bool) Position {
|
||||
return .{
|
||||
.x = self.x,
|
||||
.y = if (condition) other.y else self.y,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -201,11 +201,13 @@ pub fn cascade(self: TerminalBuffer) bool {
|
||||
return changed;
|
||||
}
|
||||
|
||||
pub fn drawLabel(self: TerminalBuffer, text: []const u8, x: usize, y: usize) void {
|
||||
drawColorLabel(text, x, y, self.fg, self.bg);
|
||||
}
|
||||
|
||||
pub fn drawColorLabel(text: []const u8, x: usize, y: usize, fg: u32, bg: u32) void {
|
||||
pub fn drawText(
|
||||
text: []const u8,
|
||||
x: usize,
|
||||
y: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) void {
|
||||
const yc: c_int = @intCast(y);
|
||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||
var utf8 = utf8view.iterator();
|
||||
@@ -216,7 +218,14 @@ pub fn drawColorLabel(text: []const u8, x: usize, y: usize, fg: u32, bg: u32) vo
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: usize, max_length: usize) void {
|
||||
pub fn drawConfinedText(
|
||||
text: []const u8,
|
||||
x: usize,
|
||||
y: usize,
|
||||
max_length: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) void {
|
||||
const yc: c_int = @intCast(y);
|
||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||
var utf8 = utf8view.iterator();
|
||||
@@ -224,12 +233,19 @@ pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: us
|
||||
var i: c_int = @intCast(x);
|
||||
while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) {
|
||||
if (i - @as(c_int, @intCast(x)) >= max_length) break;
|
||||
_ = termbox.tb_set_cell(i, yc, codepoint, self.fg, self.bg);
|
||||
_ = termbox.tb_set_cell(i, yc, codepoint, fg, bg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drawCharMultiple(self: TerminalBuffer, char: u32, x: usize, y: usize, length: usize) void {
|
||||
const cell = Cell.init(char, self.fg, self.bg);
|
||||
pub fn drawCharMultiple(
|
||||
char: u32,
|
||||
x: usize,
|
||||
y: usize,
|
||||
length: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) void {
|
||||
const cell = Cell.init(char, fg, bg);
|
||||
for (0..length) |xx| cell.put(x + xx, y);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Cell = @import("../Cell.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const Position = @import("../Position.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const termbox = TerminalBuffer.termbox;
|
||||
|
||||
const CenteredBox = @This();
|
||||
@@ -17,6 +16,9 @@ show_borders: bool,
|
||||
blank_box: bool,
|
||||
top_title: ?[]const u8,
|
||||
bottom_title: ?[]const u8,
|
||||
border_fg: u32,
|
||||
title_fg: u32,
|
||||
bg: u32,
|
||||
left_pos: Position,
|
||||
right_pos: Position,
|
||||
children_pos: Position,
|
||||
@@ -31,6 +33,9 @@ pub fn init(
|
||||
blank_box: bool,
|
||||
top_title: ?[]const u8,
|
||||
bottom_title: ?[]const u8,
|
||||
border_fg: u32,
|
||||
title_fg: u32,
|
||||
bg: u32,
|
||||
) CenteredBox {
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
@@ -42,13 +47,16 @@ pub fn init(
|
||||
.blank_box = blank_box,
|
||||
.top_title = top_title,
|
||||
.bottom_title = bottom_title,
|
||||
.border_fg = border_fg,
|
||||
.title_fg = title_fg,
|
||||
.bg = bg,
|
||||
.left_pos = TerminalBuffer.START_POSITION,
|
||||
.right_pos = TerminalBuffer.START_POSITION,
|
||||
.children_pos = TerminalBuffer.START_POSITION,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn position(self: *CenteredBox, original_pos: Position) void {
|
||||
pub fn positionXY(self: *CenteredBox, original_pos: Position) void {
|
||||
if (self.buffer.width < 2 or self.buffer.height < 2) return;
|
||||
|
||||
self.left_pos = Position.init(
|
||||
@@ -77,33 +85,33 @@ pub fn draw(self: CenteredBox) void {
|
||||
@intCast(self.left_pos.x - 1),
|
||||
@intCast(self.left_pos.y - 1),
|
||||
self.buffer.box_chars.left_up,
|
||||
self.buffer.border_fg,
|
||||
self.buffer.bg,
|
||||
self.border_fg,
|
||||
self.bg,
|
||||
);
|
||||
_ = termbox.tb_set_cell(
|
||||
@intCast(self.right_pos.x),
|
||||
@intCast(self.left_pos.y - 1),
|
||||
self.buffer.box_chars.right_up,
|
||||
self.buffer.border_fg,
|
||||
self.buffer.bg,
|
||||
self.border_fg,
|
||||
self.bg,
|
||||
);
|
||||
_ = termbox.tb_set_cell(
|
||||
@intCast(self.left_pos.x - 1),
|
||||
@intCast(self.right_pos.y),
|
||||
self.buffer.box_chars.left_down,
|
||||
self.buffer.border_fg,
|
||||
self.buffer.bg,
|
||||
self.border_fg,
|
||||
self.bg,
|
||||
);
|
||||
_ = termbox.tb_set_cell(
|
||||
@intCast(self.right_pos.x),
|
||||
@intCast(self.right_pos.y),
|
||||
self.buffer.box_chars.right_down,
|
||||
self.buffer.border_fg,
|
||||
self.buffer.bg,
|
||||
self.border_fg,
|
||||
self.bg,
|
||||
);
|
||||
|
||||
var c1 = Cell.init(self.buffer.box_chars.top, self.buffer.border_fg, self.buffer.bg);
|
||||
var c2 = Cell.init(self.buffer.box_chars.bottom, self.buffer.border_fg, self.buffer.bg);
|
||||
var c1 = Cell.init(self.buffer.box_chars.top, self.border_fg, self.bg);
|
||||
var c2 = Cell.init(self.buffer.box_chars.bottom, self.border_fg, self.bg);
|
||||
|
||||
for (0..self.width) |i| {
|
||||
c1.put(self.left_pos.x + i, self.left_pos.y - 1);
|
||||
@@ -128,20 +136,24 @@ pub fn draw(self: CenteredBox) void {
|
||||
}
|
||||
|
||||
if (self.top_title) |title| {
|
||||
self.buffer.drawConfinedLabel(
|
||||
TerminalBuffer.drawConfinedText(
|
||||
title,
|
||||
self.left_pos.x,
|
||||
self.left_pos.y - 1,
|
||||
self.width,
|
||||
self.title_fg,
|
||||
self.bg,
|
||||
);
|
||||
}
|
||||
|
||||
if (self.bottom_title) |title| {
|
||||
self.buffer.drawConfinedLabel(
|
||||
TerminalBuffer.drawConfinedText(
|
||||
title,
|
||||
self.left_pos.x,
|
||||
self.left_pos.y + self.height,
|
||||
self.width,
|
||||
self.title_fg,
|
||||
self.bg,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ pub fn init(
|
||||
allocator: Allocator,
|
||||
buffer: *TerminalBuffer,
|
||||
width: usize,
|
||||
arrow_fg: u32,
|
||||
arrow_bg: u32,
|
||||
) InfoLine {
|
||||
return .{
|
||||
.label = MessageLabel.init(
|
||||
@@ -31,6 +33,8 @@ pub fn init(
|
||||
null,
|
||||
width,
|
||||
true,
|
||||
arrow_fg,
|
||||
arrow_bg,
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -57,23 +61,26 @@ pub fn clearRendered(self: InfoLine, allocator: Allocator) !void {
|
||||
|
||||
@memset(spaces, ' ');
|
||||
|
||||
self.label.buffer.drawLabel(
|
||||
TerminalBuffer.drawText(
|
||||
spaces,
|
||||
self.label.component_pos.x + 2,
|
||||
self.label.component_pos.y,
|
||||
TerminalBuffer.Color.DEFAULT,
|
||||
TerminalBuffer.Color.DEFAULT,
|
||||
);
|
||||
}
|
||||
|
||||
fn drawItem(label: *MessageLabel, message: Message, x: usize, y: usize, width: usize) void {
|
||||
if (message.width == 0 or width <= message.width) return;
|
||||
if (message.width == 0) return;
|
||||
|
||||
const x_offset = if (label.text_in_center) (width - message.width - 1) / 2 else 0;
|
||||
const x_offset = if (label.text_in_center and width >= message.width) (width - message.width) / 2 else 0;
|
||||
|
||||
label.item_width = message.width + x_offset;
|
||||
TerminalBuffer.drawColorLabel(
|
||||
label.cursor = message.width + x_offset;
|
||||
TerminalBuffer.drawConfinedText(
|
||||
message.text,
|
||||
x + x_offset,
|
||||
y,
|
||||
width,
|
||||
message.fg,
|
||||
message.bg,
|
||||
);
|
||||
|
||||
109
src/tui/components/Label.zig
Normal file
109
src/tui/components/Label.zig
Normal file
@@ -0,0 +1,109 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Cell = @import("../Cell.zig");
|
||||
const Position = @import("../Position.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const termbox = TerminalBuffer.termbox;
|
||||
|
||||
const Label = @This();
|
||||
|
||||
text: []const u8,
|
||||
max_width: ?usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
is_text_allocated: bool,
|
||||
component_pos: Position,
|
||||
children_pos: Position,
|
||||
|
||||
pub fn init(
|
||||
text: []const u8,
|
||||
max_width: ?usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) Label {
|
||||
return .{
|
||||
.text = text,
|
||||
.max_width = max_width,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
.is_text_allocated = false,
|
||||
.component_pos = TerminalBuffer.START_POSITION,
|
||||
.children_pos = TerminalBuffer.START_POSITION,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setTextAlloc(
|
||||
self: *Label,
|
||||
allocator: Allocator,
|
||||
comptime fmt: []const u8,
|
||||
args: anytype,
|
||||
) !void {
|
||||
self.text = try std.fmt.allocPrint(allocator, fmt, args);
|
||||
self.is_text_allocated = true;
|
||||
}
|
||||
|
||||
pub fn setTextBuf(
|
||||
self: *Label,
|
||||
buffer: []u8,
|
||||
comptime fmt: []const u8,
|
||||
args: anytype,
|
||||
) !void {
|
||||
self.text = try std.fmt.bufPrint(buffer, fmt, args);
|
||||
self.is_text_allocated = false;
|
||||
}
|
||||
|
||||
pub fn setText(self: *Label, text: []const u8) void {
|
||||
self.text = text;
|
||||
self.is_text_allocated = false;
|
||||
}
|
||||
|
||||
pub fn deinit(self: Label, allocator: ?Allocator) void {
|
||||
if (self.is_text_allocated) {
|
||||
if (allocator) |alloc| alloc.free(self.text);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn positionX(self: *Label, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = original_pos.addX(self.text.len);
|
||||
}
|
||||
|
||||
pub fn positionY(self: *Label, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = original_pos.addY(1);
|
||||
}
|
||||
|
||||
pub fn positionXY(self: *Label, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = Position.init(
|
||||
self.text.len,
|
||||
1,
|
||||
).add(original_pos);
|
||||
}
|
||||
|
||||
pub fn childrenPosition(self: Label) Position {
|
||||
return self.children_pos;
|
||||
}
|
||||
|
||||
pub fn draw(self: Label) void {
|
||||
if (self.max_width) |width| {
|
||||
TerminalBuffer.drawConfinedText(
|
||||
self.text,
|
||||
self.component_pos.x,
|
||||
self.component_pos.y,
|
||||
width,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
TerminalBuffer.drawText(
|
||||
self.text,
|
||||
self.component_pos.x,
|
||||
self.component_pos.y,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
}
|
||||
@@ -25,6 +25,8 @@ pub fn init(
|
||||
user_list: *UserList,
|
||||
width: usize,
|
||||
text_in_center: bool,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) Session {
|
||||
return .{
|
||||
.label = EnvironmentLabel.init(
|
||||
@@ -35,6 +37,8 @@ pub fn init(
|
||||
user_list,
|
||||
width,
|
||||
text_in_center,
|
||||
fg,
|
||||
bg,
|
||||
),
|
||||
.user_list = user_list,
|
||||
};
|
||||
@@ -70,11 +74,20 @@ fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void {
|
||||
}
|
||||
|
||||
fn drawItem(label: *EnvironmentLabel, env: Env, x: usize, y: usize, width: usize) void {
|
||||
if (width < 3) return;
|
||||
|
||||
const length = @min(env.environment.name.len, width - 3);
|
||||
if (length == 0) return;
|
||||
|
||||
const x_offset = if (label.text_in_center) (width - length - 1) / 2 else 0;
|
||||
const x_offset = if (label.text_in_center and width >= length) (width - length) / 2 else 0;
|
||||
|
||||
label.item_width = length + x_offset;
|
||||
label.buffer.drawLabel(env.environment.name, x + x_offset, y);
|
||||
label.cursor = length + x_offset;
|
||||
TerminalBuffer.drawConfinedText(
|
||||
env.environment.name,
|
||||
x + x_offset,
|
||||
y,
|
||||
width,
|
||||
label.fg,
|
||||
label.bg,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ component_pos: Position,
|
||||
children_pos: Position,
|
||||
masked: bool,
|
||||
maybe_mask: ?u32,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
|
||||
pub fn init(
|
||||
allocator: Allocator,
|
||||
@@ -27,6 +29,8 @@ pub fn init(
|
||||
masked: bool,
|
||||
maybe_mask: ?u32,
|
||||
width: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) Text {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
@@ -40,6 +44,8 @@ pub fn init(
|
||||
.children_pos = TerminalBuffer.START_POSITION,
|
||||
.masked = masked,
|
||||
.maybe_mask = maybe_mask,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -115,14 +121,18 @@ pub fn handle(self: *Text, maybe_event: ?*termbox.tb_event, insert_mode: bool) !
|
||||
pub fn draw(self: Text) void {
|
||||
if (self.masked) {
|
||||
if (self.maybe_mask) |mask| {
|
||||
if (self.width < 1) return;
|
||||
|
||||
const length = @min(self.text.items.len, self.width - 1);
|
||||
if (length == 0) return;
|
||||
|
||||
self.buffer.drawCharMultiple(
|
||||
TerminalBuffer.drawCharMultiple(
|
||||
mask,
|
||||
self.component_pos.x,
|
||||
self.component_pos.y,
|
||||
length,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -139,7 +149,13 @@ pub fn draw(self: Text) void {
|
||||
}
|
||||
};
|
||||
|
||||
self.buffer.drawLabel(visible_slice, self.component_pos.x, self.component_pos.y);
|
||||
TerminalBuffer.drawText(
|
||||
visible_slice,
|
||||
self.component_pos.x,
|
||||
self.component_pos.y,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn clear(self: *Text) void {
|
||||
|
||||
@@ -27,8 +27,10 @@ pub fn init(
|
||||
session: *Session,
|
||||
width: usize,
|
||||
text_in_center: bool,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) !UserList {
|
||||
var userList = UserList{
|
||||
var user_list = UserList{
|
||||
.label = UserLabel.init(
|
||||
allocator,
|
||||
buffer,
|
||||
@@ -37,6 +39,8 @@ pub fn init(
|
||||
session,
|
||||
width,
|
||||
text_in_center,
|
||||
fg,
|
||||
bg,
|
||||
),
|
||||
};
|
||||
|
||||
@@ -60,7 +64,7 @@ pub fn init(
|
||||
allocated_index = true;
|
||||
}
|
||||
|
||||
try userList.label.addItem(.{
|
||||
try user_list.label.addItem(.{
|
||||
.name = username,
|
||||
.session_index = maybe_session_index.?,
|
||||
.allocated_index = allocated_index,
|
||||
@@ -68,7 +72,7 @@ pub fn init(
|
||||
});
|
||||
}
|
||||
|
||||
return userList;
|
||||
return user_list;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *UserList) void {
|
||||
@@ -92,11 +96,20 @@ fn usernameChanged(user: User, maybe_session: ?*Session) void {
|
||||
}
|
||||
|
||||
fn drawItem(label: *UserLabel, user: User, x: usize, y: usize, width: usize) void {
|
||||
if (width < 3) return;
|
||||
|
||||
const length = @min(user.name.len, width - 3);
|
||||
if (length == 0) return;
|
||||
|
||||
const x_offset = if (label.text_in_center) (width - length - 1) / 2 else 0;
|
||||
const x_offset = if (label.text_in_center and width >= length) (width - length) / 2 else 0;
|
||||
|
||||
label.item_width = length + x_offset;
|
||||
label.buffer.drawLabel(user.name, x + x_offset, y);
|
||||
label.cursor = length + x_offset;
|
||||
TerminalBuffer.drawConfinedText(
|
||||
user.name,
|
||||
x + x_offset,
|
||||
y,
|
||||
width,
|
||||
label.fg,
|
||||
label.bg,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
||||
component_pos: Position,
|
||||
children_pos: Position,
|
||||
text_in_center: bool,
|
||||
item_width: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
cursor: usize,
|
||||
draw_item_fn: DrawItemFn,
|
||||
change_item_fn: ?ChangeItemFn,
|
||||
change_item_arg: ?ChangeItemType,
|
||||
@@ -35,6 +37,8 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
||||
change_item_arg: ?ChangeItemType,
|
||||
width: usize,
|
||||
text_in_center: bool,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) Self {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
@@ -45,7 +49,9 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
||||
.component_pos = TerminalBuffer.START_POSITION,
|
||||
.children_pos = TerminalBuffer.START_POSITION,
|
||||
.text_in_center = text_in_center,
|
||||
.item_width = 0,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
.cursor = 0,
|
||||
.draw_item_fn = draw_item_fn,
|
||||
.change_item_fn = change_item_fn,
|
||||
.change_item_arg = change_item_arg,
|
||||
@@ -58,19 +64,19 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
||||
|
||||
pub fn positionX(self: *Self, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.item_width = self.component_pos.x + 2;
|
||||
self.cursor = 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.cursor = 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.cursor = self.component_pos.x + 2;
|
||||
self.children_pos = Position.init(
|
||||
self.width,
|
||||
1,
|
||||
@@ -106,27 +112,28 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
||||
}
|
||||
|
||||
_ = termbox.tb_set_cursor(
|
||||
@intCast(self.component_pos.x + self.item_width + 2),
|
||||
@intCast(self.component_pos.x + self.cursor + 2),
|
||||
@intCast(self.component_pos.y),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self) void {
|
||||
if (self.list.items.len == 0) return;
|
||||
if (self.width < 2) return;
|
||||
|
||||
_ = termbox.tb_set_cell(
|
||||
@intCast(self.component_pos.x),
|
||||
@intCast(self.component_pos.y),
|
||||
'<',
|
||||
self.buffer.fg,
|
||||
self.buffer.bg,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
_ = termbox.tb_set_cell(
|
||||
@intCast(self.component_pos.x + self.width - 1),
|
||||
@intCast(self.component_pos.y),
|
||||
'>',
|
||||
self.buffer.fg,
|
||||
self.buffer.bg,
|
||||
self.fg,
|
||||
self.bg,
|
||||
);
|
||||
|
||||
const current_item = self.list.items[self.current];
|
||||
|
||||
Reference in New Issue
Block a user