mirror of
https://github.com/fairyglade/ly.git
synced 2026-03-21 22:43:38 +00:00
Add separate big label widget for bigclock
Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
const ly_core = @import("ly-core");
|
||||
const interop = ly_core.interop;
|
||||
|
||||
const en = @import("bigclock/en.zig");
|
||||
const fa = @import("bigclock/fa.zig");
|
||||
const Lang = @import("bigclock/Lang.zig");
|
||||
pub const WIDTH = Lang.WIDTH;
|
||||
pub const HEIGHT = Lang.HEIGHT;
|
||||
pub const SIZE = Lang.SIZE;
|
||||
const enums = @import("enums.zig");
|
||||
const Bigclock = enums.Bigclock;
|
||||
const Cell = @import("tui/Cell.zig");
|
||||
|
||||
pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) ![SIZE]Cell {
|
||||
var cells: [SIZE]Cell = undefined;
|
||||
|
||||
const time = try interop.getTimeOfDay();
|
||||
const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(time.microseconds, 500000) != 0) ' ' else char, bigclock);
|
||||
for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg);
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
pub fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [SIZE]Cell) void {
|
||||
if (x + WIDTH >= tb_width or y + HEIGHT >= tb_height) return;
|
||||
|
||||
for (0..HEIGHT) |yy| {
|
||||
for (0..WIDTH) |xx| {
|
||||
const cell = cells[yy * WIDTH + xx];
|
||||
cell.put(x + xx, y + yy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn toBigNumber(char: u8, bigclock: Bigclock) [SIZE]u21 {
|
||||
const locale_chars = switch (bigclock) {
|
||||
.fa => fa.locale_chars,
|
||||
.en => en.locale_chars,
|
||||
.none => unreachable,
|
||||
};
|
||||
return switch (char) {
|
||||
'0' => locale_chars.ZERO,
|
||||
'1' => locale_chars.ONE,
|
||||
'2' => locale_chars.TWO,
|
||||
'3' => locale_chars.THREE,
|
||||
'4' => locale_chars.FOUR,
|
||||
'5' => locale_chars.FIVE,
|
||||
'6' => locale_chars.SIX,
|
||||
'7' => locale_chars.SEVEN,
|
||||
'8' => locale_chars.EIGHT,
|
||||
'9' => locale_chars.NINE,
|
||||
'p', 'P' => locale_chars.P,
|
||||
'a', 'A' => locale_chars.A,
|
||||
'm', 'M' => locale_chars.M,
|
||||
':' => locale_chars.S,
|
||||
else => locale_chars.E,
|
||||
};
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
const ly_core = @import("ly-core");
|
||||
|
||||
pub const WIDTH = 5;
|
||||
pub const HEIGHT = 5;
|
||||
pub const SIZE = WIDTH * HEIGHT;
|
||||
|
||||
pub const X: u32 = if (ly_core.interop.supportsUnicode()) 0x2593 else '#';
|
||||
pub const O: u32 = 0;
|
||||
|
||||
// zig fmt: off
|
||||
pub const LocaleChars = struct {
|
||||
ZERO: [SIZE]u21,
|
||||
ONE: [SIZE]u21,
|
||||
TWO: [SIZE]u21,
|
||||
THREE: [SIZE]u21,
|
||||
FOUR: [SIZE]u21,
|
||||
FIVE: [SIZE]u21,
|
||||
SIX: [SIZE]u21,
|
||||
SEVEN: [SIZE]u21,
|
||||
EIGHT: [SIZE]u21,
|
||||
NINE: [SIZE]u21,
|
||||
S: [SIZE]u21,
|
||||
E: [SIZE]u21,
|
||||
P: [SIZE]u21,
|
||||
A: [SIZE]u21,
|
||||
M: [SIZE]u21,
|
||||
};
|
||||
// zig fmt: on
|
||||
155
src/main.zig
155
src/main.zig
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const StringList = std.ArrayListUnmanaged([]const u8);
|
||||
const temporary_allocator = std.heap.page_allocator;
|
||||
const builtin = @import("builtin");
|
||||
const build_options = @import("build_options");
|
||||
@@ -19,7 +20,6 @@ const DurFile = @import("animations/DurFile.zig");
|
||||
const GameOfLife = @import("animations/GameOfLife.zig");
|
||||
const Matrix = @import("animations/Matrix.zig");
|
||||
const auth = @import("auth.zig");
|
||||
const bigclock = @import("bigclock.zig");
|
||||
const Config = @import("config/Config.zig");
|
||||
const Lang = @import("config/Lang.zig");
|
||||
const migrator = @import("config/migrator.zig");
|
||||
@@ -31,18 +31,19 @@ const Environment = @import("Environment.zig");
|
||||
const Entry = Environment.Entry;
|
||||
const Animation = @import("tui/Animation.zig");
|
||||
const Position = @import("tui/Position.zig");
|
||||
const bigLabel = @import("tui/components/bigLabel.zig");
|
||||
const BigclockLabel = bigLabel.BigLabel(*UiState);
|
||||
const CenteredBox = @import("tui/components/CenteredBox.zig");
|
||||
const InfoLine = @import("tui/components/InfoLine.zig");
|
||||
const label = @import("tui/components/label.zig");
|
||||
const RegularLabel = label.Label(struct {});
|
||||
const UpdatableLabel = label.Label(*UiState);
|
||||
const Session = @import("tui/components/Session.zig");
|
||||
const Text = @import("tui/components/Text.zig");
|
||||
const UserList = @import("tui/components/UserList.zig");
|
||||
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
||||
const termbox = TerminalBuffer.termbox;
|
||||
|
||||
const StringList = std.ArrayListUnmanaged([]const u8);
|
||||
|
||||
const Label = label.Label;
|
||||
const ly_version_str = "Ly version " ++ build_options.version;
|
||||
|
||||
var session_pid: std.posix.pid_t = -1;
|
||||
@@ -64,7 +65,6 @@ fn ttyControlTransferSignalHandler(_: c_int) callconv(.c) void {
|
||||
TerminalBuffer.shutdownStatic();
|
||||
}
|
||||
|
||||
const NoType = struct {};
|
||||
const UiState = struct {
|
||||
auth_fails: u64,
|
||||
update: bool,
|
||||
@@ -72,20 +72,21 @@ const UiState = struct {
|
||||
labels_max_length: usize,
|
||||
animation_timed_out: bool,
|
||||
animation: *?Animation,
|
||||
shutdown_label: *Label(NoType),
|
||||
restart_label: *Label(NoType),
|
||||
sleep_label: *Label(NoType),
|
||||
hibernate_label: *Label(NoType),
|
||||
brightness_down_label: *Label(NoType),
|
||||
brightness_up_label: *Label(NoType),
|
||||
numlock_label: *Label(*UiState),
|
||||
capslock_label: *Label(*UiState),
|
||||
battery_label: *Label(*UiState),
|
||||
clock_label: *Label(*UiState),
|
||||
session_specifier_label: *Label(*UiState),
|
||||
login_label: *Label(NoType),
|
||||
password_label: *Label(NoType),
|
||||
version_label: *Label(NoType),
|
||||
shutdown_label: *RegularLabel,
|
||||
restart_label: *RegularLabel,
|
||||
sleep_label: *RegularLabel,
|
||||
hibernate_label: *RegularLabel,
|
||||
brightness_down_label: *RegularLabel,
|
||||
brightness_up_label: *RegularLabel,
|
||||
numlock_label: *UpdatableLabel,
|
||||
capslock_label: *UpdatableLabel,
|
||||
battery_label: *UpdatableLabel,
|
||||
clock_label: *UpdatableLabel,
|
||||
session_specifier_label: *UpdatableLabel,
|
||||
login_label: *RegularLabel,
|
||||
password_label: *RegularLabel,
|
||||
version_label: *RegularLabel,
|
||||
bigclock_label: *BigclockLabel,
|
||||
box: *CenteredBox,
|
||||
info_line: *InfoLine,
|
||||
animate: bool,
|
||||
@@ -100,7 +101,9 @@ const UiState = struct {
|
||||
lang: Lang,
|
||||
log_file: *LogFile,
|
||||
battery_buf: [16:0]u8,
|
||||
bigclock_format_buf: [16:0]u8,
|
||||
clock_buf: [64:0]u8,
|
||||
bigclock_buf: [32:0]u8,
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
@@ -336,7 +339,7 @@ pub fn main() !void {
|
||||
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||
|
||||
// Initialize components
|
||||
var shutdown_label = Label(NoType).init(
|
||||
var shutdown_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -345,7 +348,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer shutdown_label.deinit(allocator);
|
||||
|
||||
var restart_label = Label(NoType).init(
|
||||
var restart_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -354,7 +357,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer restart_label.deinit(allocator);
|
||||
|
||||
var sleep_label = Label(NoType).init(
|
||||
var sleep_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -363,7 +366,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer sleep_label.deinit(allocator);
|
||||
|
||||
var hibernate_label = Label(NoType).init(
|
||||
var hibernate_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -372,7 +375,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer hibernate_label.deinit(allocator);
|
||||
|
||||
var brightness_down_label = Label(NoType).init(
|
||||
var brightness_down_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -381,7 +384,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer brightness_down_label.deinit(allocator);
|
||||
|
||||
var brightness_up_label = Label(NoType).init(
|
||||
var brightness_up_label = RegularLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -431,7 +434,7 @@ pub fn main() !void {
|
||||
}
|
||||
}
|
||||
|
||||
var numlock_label = Label(*UiState).init(
|
||||
var numlock_label = UpdatableLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -440,7 +443,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer numlock_label.deinit(null);
|
||||
|
||||
var capslock_label = Label(*UiState).init(
|
||||
var capslock_label = UpdatableLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -449,7 +452,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer capslock_label.deinit(null);
|
||||
|
||||
var battery_label = Label(*UiState).init(
|
||||
var battery_label = UpdatableLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -458,7 +461,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer battery_label.deinit(null);
|
||||
|
||||
var clock_label = Label(*UiState).init(
|
||||
var clock_label = UpdatableLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -467,6 +470,20 @@ pub fn main() !void {
|
||||
);
|
||||
defer clock_label.deinit(null);
|
||||
|
||||
var bigclock_label = BigclockLabel.init(
|
||||
&buffer,
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
buffer.bg,
|
||||
switch (config.bigclock) {
|
||||
.none, .en => .en,
|
||||
.fa => .fa,
|
||||
},
|
||||
&updateBigClock,
|
||||
);
|
||||
defer bigclock_label.deinit(null);
|
||||
|
||||
var box = CenteredBox.init(
|
||||
&buffer,
|
||||
config.margin_box_h,
|
||||
@@ -532,7 +549,7 @@ pub fn main() !void {
|
||||
|
||||
var login: UserList = undefined;
|
||||
|
||||
var session_specifier_label = Label(*UiState).init(
|
||||
var session_specifier_label = UpdatableLabel.init(
|
||||
"",
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -552,7 +569,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer session.deinit();
|
||||
|
||||
var login_label = Label(NoType).init(
|
||||
var login_label = RegularLabel.init(
|
||||
lang.login,
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -633,7 +650,7 @@ pub fn main() !void {
|
||||
try log_file.err("sys", "no users found", .{});
|
||||
}
|
||||
|
||||
var password_label = Label(NoType).init(
|
||||
var password_label = RegularLabel.init(
|
||||
lang.password,
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -653,7 +670,7 @@ pub fn main() !void {
|
||||
);
|
||||
defer password.deinit();
|
||||
|
||||
var version_label = Label(NoType).init(
|
||||
var version_label = RegularLabel.init(
|
||||
ly_version_str,
|
||||
null,
|
||||
buffer.fg,
|
||||
@@ -713,6 +730,7 @@ pub fn main() !void {
|
||||
.login_label = &login_label,
|
||||
.password_label = &password_label,
|
||||
.version_label = &version_label,
|
||||
.bigclock_label = &bigclock_label,
|
||||
.box = &box,
|
||||
.info_line = &info_line,
|
||||
.animate = config.animation != .none,
|
||||
@@ -730,7 +748,9 @@ pub fn main() !void {
|
||||
.lang = lang,
|
||||
.log_file = &log_file,
|
||||
.battery_buf = undefined,
|
||||
.bigclock_format_buf = undefined,
|
||||
.clock_buf = undefined,
|
||||
.bigclock_buf = undefined,
|
||||
};
|
||||
|
||||
// Load last saved username and desktop selection, if any
|
||||
@@ -1204,6 +1224,10 @@ fn updateComponents(state: *UiState) !void {
|
||||
try state.clock_label.update(state);
|
||||
}
|
||||
|
||||
if (state.config.bigclock != .none) {
|
||||
try state.bigclock_label.update(state);
|
||||
}
|
||||
|
||||
try state.session_specifier_label.update(state);
|
||||
|
||||
if (!state.config.hide_keyboard_locks) {
|
||||
@@ -1230,32 +1254,9 @@ fn drawUi(log_file: *LogFile, state: *UiState) !bool {
|
||||
try TerminalBuffer.clearScreenStatic(false);
|
||||
|
||||
if (!state.animation_timed_out) if (state.animation.*) |*a| a.draw();
|
||||
|
||||
if (!state.config.hide_version_string) state.version_label.draw();
|
||||
|
||||
if (state.config.battery_id != null) state.battery_label.draw();
|
||||
|
||||
if (state.config.bigclock != .none and state.box.height + (bigclock.HEIGHT + 2) * 2 < state.buffer.height) {
|
||||
var format_buf: [16:0]u8 = undefined;
|
||||
var clock_buf: [32:0]u8 = undefined;
|
||||
// We need the slice/c-string returned by `bufPrintZ`.
|
||||
const format = try std.fmt.bufPrintZ(&format_buf, "{s}{s}{s}{s}", .{
|
||||
if (state.config.bigclock_12hr) "%I" else "%H",
|
||||
":%M",
|
||||
if (state.config.bigclock_seconds) ":%S" else "",
|
||||
if (state.config.bigclock_12hr) "%P" else "",
|
||||
});
|
||||
const xo = state.buffer.width / 2 - @min(state.buffer.width, (format.len * (bigclock.WIDTH + 1))) / 2;
|
||||
const yo = (state.buffer.height - state.box.height) / 2 - bigclock.HEIGHT - 2;
|
||||
|
||||
const clock_str = interop.timeAsString(&clock_buf, format);
|
||||
|
||||
for (clock_str, 0..) |c, i| {
|
||||
// TODO: Show error
|
||||
const clock_cell = try bigclock.clockCell(state.animate, c, state.buffer.fg, state.buffer.bg, state.config.bigclock);
|
||||
bigclock.alphaBlit(xo + i * (bigclock.WIDTH + 1), yo, state.buffer.width, state.buffer.height, clock_cell);
|
||||
}
|
||||
}
|
||||
if (state.config.bigclock != .none) state.bigclock_label.draw();
|
||||
|
||||
state.box.draw();
|
||||
|
||||
@@ -1308,7 +1309,7 @@ fn drawUi(log_file: *LogFile, state: *UiState) !bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn updateNumlock(self: *Label(*UiState), state: *UiState) !void {
|
||||
fn updateNumlock(self: *UpdatableLabel, state: *UiState) !void {
|
||||
const lock_state = interop.getLockState() catch |err| {
|
||||
self.update_fn = null;
|
||||
try state.info_line.addMessage(state.lang.err_lock_state, state.config.error_bg, state.config.error_fg);
|
||||
@@ -1319,7 +1320,7 @@ fn updateNumlock(self: *Label(*UiState), state: *UiState) !void {
|
||||
self.setText(if (lock_state.numlock) state.lang.numlock else "");
|
||||
}
|
||||
|
||||
fn updateCapslock(self: *Label(*UiState), state: *UiState) !void {
|
||||
fn updateCapslock(self: *UpdatableLabel, state: *UiState) !void {
|
||||
const lock_state = interop.getLockState() catch |err| {
|
||||
self.update_fn = null;
|
||||
try state.info_line.addMessage(state.lang.err_lock_state, state.config.error_bg, state.config.error_fg);
|
||||
@@ -1330,7 +1331,7 @@ fn updateCapslock(self: *Label(*UiState), state: *UiState) !void {
|
||||
self.setText(if (lock_state.capslock) state.lang.capslock else "");
|
||||
}
|
||||
|
||||
fn updateBattery(self: *Label(*UiState), state: *UiState) !void {
|
||||
fn updateBattery(self: *UpdatableLabel, state: *UiState) !void {
|
||||
if (state.config.battery_id) |id| {
|
||||
const battery_percentage = getBatteryPercentage(id) catch |err| {
|
||||
self.update_fn = null;
|
||||
@@ -1347,7 +1348,7 @@ fn updateBattery(self: *Label(*UiState), state: *UiState) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn updateClock(self: *Label(*UiState), state: *UiState) !void {
|
||||
fn updateClock(self: *UpdatableLabel, state: *UiState) !void {
|
||||
if (state.config.clock) |clock| draw_clock: {
|
||||
const clock_str = interop.timeAsString(&state.clock_buf, clock);
|
||||
|
||||
@@ -1362,7 +1363,30 @@ fn updateClock(self: *Label(*UiState), state: *UiState) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn updateSessionSpecifier(self: *Label(*UiState), state: *UiState) !void {
|
||||
fn updateBigClock(self: *BigclockLabel, state: *UiState) !void {
|
||||
if (state.box.height + (bigLabel.CHAR_HEIGHT + 2) * 2 >= state.buffer.height) return;
|
||||
|
||||
const time = try interop.getTimeOfDay();
|
||||
const animate_time = @divTrunc(time.microseconds, 500_000);
|
||||
const separator = if (state.animate and animate_time != 0) " " else ":";
|
||||
const format = try std.fmt.bufPrintZ(
|
||||
&state.bigclock_format_buf,
|
||||
"{s}{s}{s}{s}{s}{s}",
|
||||
.{
|
||||
if (state.config.bigclock_12hr) "%I" else "%H",
|
||||
separator,
|
||||
"%M",
|
||||
if (state.config.bigclock_seconds) separator else "",
|
||||
if (state.config.bigclock_seconds) "%S" else "",
|
||||
if (state.config.bigclock_12hr) "%P" else "",
|
||||
},
|
||||
);
|
||||
|
||||
const clock_str = interop.timeAsString(&state.bigclock_buf, format);
|
||||
self.setText(clock_str);
|
||||
}
|
||||
|
||||
fn updateSessionSpecifier(self: *UpdatableLabel, state: *UiState) !void {
|
||||
const env = state.session.label.list.items[state.session.label.current];
|
||||
self.setText(env.environment.specifier);
|
||||
}
|
||||
@@ -1409,6 +1433,13 @@ fn positionComponents(state: *UiState) void {
|
||||
|
||||
state.box.positionXY(TerminalBuffer.START_POSITION);
|
||||
|
||||
if (state.config.bigclock != .none) {
|
||||
state.bigclock_label.positionXY(Position.init(
|
||||
state.buffer.width / 2 - @min(state.buffer.width, (state.bigclock_label.text.len * (bigLabel.CHAR_WIDTH + 1))) / 2,
|
||||
(state.buffer.height - state.box.height) / 2 - bigLabel.CHAR_HEIGHT - 2,
|
||||
).add(TerminalBuffer.START_POSITION));
|
||||
}
|
||||
|
||||
state.info_line.label.positionY(state.box
|
||||
.childrenPosition());
|
||||
|
||||
|
||||
210
src/tui/components/bigLabel.zig
Normal file
210
src/tui/components/bigLabel.zig
Normal file
@@ -0,0 +1,210 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const ly_core = @import("ly-core");
|
||||
const interop = ly_core.interop;
|
||||
|
||||
const en = @import("bigLabelLocales/en.zig");
|
||||
const fa = @import("bigLabelLocales/fa.zig");
|
||||
const Cell = @import("../Cell.zig");
|
||||
const Position = @import("../Position.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const termbox = TerminalBuffer.termbox;
|
||||
|
||||
pub const CHAR_WIDTH = 5;
|
||||
pub const CHAR_HEIGHT = 5;
|
||||
pub const CHAR_SIZE = CHAR_WIDTH * CHAR_HEIGHT;
|
||||
pub const X: u32 = if (ly_core.interop.supportsUnicode()) 0x2593 else '#';
|
||||
pub const O: u32 = 0;
|
||||
|
||||
// zig fmt: off
|
||||
pub const LocaleChars = struct {
|
||||
ZERO: [CHAR_SIZE]u21,
|
||||
ONE: [CHAR_SIZE]u21,
|
||||
TWO: [CHAR_SIZE]u21,
|
||||
THREE: [CHAR_SIZE]u21,
|
||||
FOUR: [CHAR_SIZE]u21,
|
||||
FIVE: [CHAR_SIZE]u21,
|
||||
SIX: [CHAR_SIZE]u21,
|
||||
SEVEN: [CHAR_SIZE]u21,
|
||||
EIGHT: [CHAR_SIZE]u21,
|
||||
NINE: [CHAR_SIZE]u21,
|
||||
S: [CHAR_SIZE]u21,
|
||||
E: [CHAR_SIZE]u21,
|
||||
P: [CHAR_SIZE]u21,
|
||||
A: [CHAR_SIZE]u21,
|
||||
M: [CHAR_SIZE]u21,
|
||||
};
|
||||
// zig fmt: on
|
||||
|
||||
pub const BigLabelLocale = enum {
|
||||
en,
|
||||
fa,
|
||||
};
|
||||
|
||||
pub fn BigLabel(comptime ContextType: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
buffer: *TerminalBuffer,
|
||||
text: []const u8,
|
||||
max_width: ?usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
locale: BigLabelLocale,
|
||||
update_fn: ?*const fn (*Self, ContextType) anyerror!void,
|
||||
is_text_allocated: bool,
|
||||
component_pos: Position,
|
||||
children_pos: Position,
|
||||
|
||||
pub fn init(
|
||||
buffer: *TerminalBuffer,
|
||||
text: []const u8,
|
||||
max_width: ?usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
locale: BigLabelLocale,
|
||||
update_fn: ?*const fn (*Self, ContextType) anyerror!void,
|
||||
) Self {
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.text = text,
|
||||
.max_width = max_width,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
.locale = locale,
|
||||
.update_fn = update_fn,
|
||||
.is_text_allocated = false,
|
||||
.component_pos = TerminalBuffer.START_POSITION,
|
||||
.children_pos = TerminalBuffer.START_POSITION,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setTextAlloc(
|
||||
self: *Self,
|
||||
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: *Self,
|
||||
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: *Self, text: []const u8) void {
|
||||
self.text = text;
|
||||
self.is_text_allocated = false;
|
||||
}
|
||||
|
||||
pub fn deinit(self: Self, allocator: ?Allocator) void {
|
||||
if (self.is_text_allocated) {
|
||||
if (allocator) |alloc| alloc.free(self.text);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn positionX(self: *Self, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = original_pos.addX(self.text.len * CHAR_WIDTH);
|
||||
}
|
||||
|
||||
pub fn positionY(self: *Self, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = original_pos.addY(CHAR_HEIGHT);
|
||||
}
|
||||
|
||||
pub fn positionXY(self: *Self, original_pos: Position) void {
|
||||
self.component_pos = original_pos;
|
||||
self.children_pos = Position.init(
|
||||
self.text.len * CHAR_WIDTH,
|
||||
CHAR_HEIGHT,
|
||||
).add(original_pos);
|
||||
}
|
||||
|
||||
pub fn childrenPosition(self: Self) Position {
|
||||
return self.children_pos;
|
||||
}
|
||||
|
||||
pub fn draw(self: Self) void {
|
||||
for (self.text, 0..) |c, i| {
|
||||
const clock_cell = clockCell(
|
||||
c,
|
||||
self.fg,
|
||||
self.bg,
|
||||
self.locale,
|
||||
);
|
||||
|
||||
alphaBlit(
|
||||
self.component_pos.x + i * (CHAR_WIDTH + 1),
|
||||
self.component_pos.y,
|
||||
self.buffer.width,
|
||||
self.buffer.height,
|
||||
clock_cell,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(self: *Self, context: ContextType) !void {
|
||||
if (self.update_fn) |update_fn| {
|
||||
return @call(
|
||||
.auto,
|
||||
update_fn,
|
||||
.{ self, context },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn clockCell(char: u8, fg: u32, bg: u32, locale: BigLabelLocale) [CHAR_SIZE]Cell {
|
||||
var cells: [CHAR_SIZE]Cell = undefined;
|
||||
|
||||
//@divTrunc(time.microseconds, 500000) != 0)
|
||||
const clock_chars = toBigNumber(char, locale);
|
||||
for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg);
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
fn alphaBlit(x: usize, y: usize, tb_width: usize, tb_height: usize, cells: [CHAR_SIZE]Cell) void {
|
||||
if (x + CHAR_WIDTH >= tb_width or y + CHAR_HEIGHT >= tb_height) return;
|
||||
|
||||
for (0..CHAR_HEIGHT) |yy| {
|
||||
for (0..CHAR_WIDTH) |xx| {
|
||||
const cell = cells[yy * CHAR_WIDTH + xx];
|
||||
cell.put(x + xx, y + yy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn toBigNumber(char: u8, locale: BigLabelLocale) [CHAR_SIZE]u21 {
|
||||
const locale_chars = switch (locale) {
|
||||
.fa => fa.locale_chars,
|
||||
.en => en.locale_chars,
|
||||
};
|
||||
return switch (char) {
|
||||
'0' => locale_chars.ZERO,
|
||||
'1' => locale_chars.ONE,
|
||||
'2' => locale_chars.TWO,
|
||||
'3' => locale_chars.THREE,
|
||||
'4' => locale_chars.FOUR,
|
||||
'5' => locale_chars.FIVE,
|
||||
'6' => locale_chars.SIX,
|
||||
'7' => locale_chars.SEVEN,
|
||||
'8' => locale_chars.EIGHT,
|
||||
'9' => locale_chars.NINE,
|
||||
'p', 'P' => locale_chars.P,
|
||||
'a', 'A' => locale_chars.A,
|
||||
'm', 'M' => locale_chars.M,
|
||||
':' => locale_chars.S,
|
||||
else => locale_chars.E,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const Lang = @import("Lang.zig");
|
||||
const LocaleChars = Lang.LocaleChars;
|
||||
const X = Lang.X;
|
||||
const O = Lang.O;
|
||||
const bigLabel = @import("../bigLabel.zig");
|
||||
const LocaleChars = bigLabel.LocaleChars;
|
||||
const X = bigLabel.X;
|
||||
const O = bigLabel.O;
|
||||
|
||||
// zig fmt: off
|
||||
pub const locale_chars = LocaleChars{
|
||||
@@ -1,7 +1,7 @@
|
||||
const Lang = @import("Lang.zig");
|
||||
const LocaleChars = Lang.LocaleChars;
|
||||
const X = Lang.X;
|
||||
const O = Lang.O;
|
||||
const bigLabel = @import("../bigLabel.zig");
|
||||
const LocaleChars = bigLabel.LocaleChars;
|
||||
const X = bigLabel.X;
|
||||
const O = bigLabel.O;
|
||||
|
||||
// zig fmt: off
|
||||
pub const locale_chars = LocaleChars{
|
||||
Reference in New Issue
Block a user