feat: add a simple clock status bar widget
This commit is contained in:
parent
fa5da6e6d9
commit
4b97564f29
3 changed files with 112 additions and 0 deletions
|
@ -76,6 +76,12 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = dependency_optimize,
|
.optimize = dependency_optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const zeit_dep = b.dependency("zeit", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = dependency_optimize,
|
||||||
|
});
|
||||||
|
const zeit_mod = zeit_dep.module("zeit");
|
||||||
|
|
||||||
const themes_dep = b.dependency("themes", .{});
|
const themes_dep = b.dependency("themes", .{});
|
||||||
|
|
||||||
const syntax_dep = b.dependency("syntax", .{
|
const syntax_dep = b.dependency("syntax", .{
|
||||||
|
@ -205,6 +211,7 @@ pub fn build(b: *std.Build) void {
|
||||||
.{ .name = "help.md", .module = help_mod },
|
.{ .name = "help.md", .module = help_mod },
|
||||||
.{ .name = "CaseData", .module = zg_dep.module("CaseData") },
|
.{ .name = "CaseData", .module = zg_dep.module("CaseData") },
|
||||||
.{ .name = "fuzzig", .module = fuzzig_dep.module("fuzzig") },
|
.{ .name = "fuzzig", .module = fuzzig_dep.module("fuzzig") },
|
||||||
|
.{ .name = "zeit", .module = zeit_mod },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
.url = "https://github.com/neurocyte/libvaxis/archive/9d3e60d1cda43055d8f58cca1bc1679fb958da4b.tar.gz",
|
.url = "https://github.com/neurocyte/libvaxis/archive/9d3e60d1cda43055d8f58cca1bc1679fb958da4b.tar.gz",
|
||||||
.hash = "12202e2c797387877717a140839a4d583d1258fcdcd1030c8a1e520b6add4ab9e2b0",
|
.hash = "12202e2c797387877717a140839a4d583d1258fcdcd1030c8a1e520b6add4ab9e2b0",
|
||||||
},
|
},
|
||||||
|
.zeit = .{
|
||||||
|
.url = "https://github.com/rockorager/zeit/archive/9cca8ec620a54c3b07cd249f25e5bcb3153d03d7.tar.gz",
|
||||||
|
.hash = "1220755ea2a5aa6bb3713437aaafefd44812169fe43f1da755c3ee6101b85940f441",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"include",
|
"include",
|
||||||
|
|
101
src/tui/status/clock.zig
Normal file
101
src/tui/status/clock.zig
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const tp = @import("thespian");
|
||||||
|
const log = @import("log");
|
||||||
|
const zeit = @import("zeit");
|
||||||
|
|
||||||
|
const Plane = @import("renderer").Plane;
|
||||||
|
|
||||||
|
const Widget = @import("../Widget.zig");
|
||||||
|
const MessageFilter = @import("../MessageFilter.zig");
|
||||||
|
const tui = @import("../tui.zig");
|
||||||
|
const mainview = @import("../mainview.zig");
|
||||||
|
const logview = @import("../logview.zig");
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
plane: Plane,
|
||||||
|
tick_timer: ?tp.Cancellable = null,
|
||||||
|
on_event: ?Widget.EventHandler,
|
||||||
|
tz: zeit.timezone.TimeZone,
|
||||||
|
|
||||||
|
const message_display_time_seconds = 2;
|
||||||
|
const error_display_time_seconds = 4;
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
const Level = enum {
|
||||||
|
info,
|
||||||
|
err,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn create(a: std.mem.Allocator, parent: Plane, event_handler: ?Widget.EventHandler) @import("widget.zig").CreateError!Widget {
|
||||||
|
var env = std.process.getEnvMap(a) catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||||
|
defer env.deinit();
|
||||||
|
const self: *Self = try a.create(Self);
|
||||||
|
self.* = .{
|
||||||
|
.allocator = a,
|
||||||
|
.plane = try Plane.init(&(Widget.Box{}).opts(@typeName(Self)), parent),
|
||||||
|
.on_event = event_handler,
|
||||||
|
.tz = zeit.local(a, &env) catch |e| return tp.exit_error(e, @errorReturnTrace()),
|
||||||
|
};
|
||||||
|
try tui.current().message_filters.add(MessageFilter.bind(self, receive_tick));
|
||||||
|
self.update_tick_timer();
|
||||||
|
return Widget.to(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, a: std.mem.Allocator) void {
|
||||||
|
tui.current().message_filters.remove_ptr(self);
|
||||||
|
if (self.tick_timer) |*t| {
|
||||||
|
t.cancel() catch {};
|
||||||
|
t.deinit();
|
||||||
|
self.tick_timer = null;
|
||||||
|
}
|
||||||
|
self.tz.deinit();
|
||||||
|
self.plane.deinit();
|
||||||
|
a.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
|
var btn: u32 = 0;
|
||||||
|
if (try m.match(.{ "D", tp.any, tp.extract(&btn), tp.more })) {
|
||||||
|
if (self.on_event) |h| h.send(from, m) catch {};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layout(_: *Self) Widget.Layout {
|
||||||
|
return .{ .static = 5 };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(self: *Self, theme: *const Widget.Theme) bool {
|
||||||
|
self.plane.set_base_style(" ", theme.statusbar);
|
||||||
|
self.plane.erase();
|
||||||
|
self.plane.home();
|
||||||
|
|
||||||
|
const now = zeit.instant(.{}) catch return false;
|
||||||
|
const now_local = now.in(&self.tz);
|
||||||
|
const dt = now_local.time();
|
||||||
|
_ = self.plane.print("{d:0>2}:{d:0>2}", .{ dt.hour, dt.minute }) catch {};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_tick(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||||
|
if (try m.match(.{"CLOCK"})) {
|
||||||
|
tui.need_render();
|
||||||
|
self.update_tick_timer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_tick_timer(self: *Self) void {
|
||||||
|
const current_time: usize = @intCast(std.time.milliTimestamp());
|
||||||
|
const ms_delay_until_tick = current_time % std.time.ms_per_s;
|
||||||
|
const s_delay_until_tick = current_time % std.time.ms_per_min;
|
||||||
|
const delay = s_delay_until_tick + ms_delay_until_tick;
|
||||||
|
if (self.tick_timer) |*t| {
|
||||||
|
t.cancel() catch {};
|
||||||
|
t.deinit();
|
||||||
|
self.tick_timer = null;
|
||||||
|
}
|
||||||
|
self.tick_timer = tp.self_pid().delay_send_cancellable(self.allocator, delay, .{"CLOCK"}) catch null;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue