use super::{Widget, WidgetAlignment, WidgetClickResult, WidgetContext};
use crate::rendering::{Cell, Theme, VideoBuffer};
use crate::window::manager::FocusState;
use chrono::{Local, Timelike};
pub struct DateTimeWidget {
show_date: bool,
hovered: bool,
cached_time: String,
last_second: u32,
}
impl DateTimeWidget {
pub fn new(show_date: bool) -> Self {
Self {
show_date,
hovered: false,
cached_time: String::new(),
last_second: 60, }
}
fn refresh_time_if_needed(&mut self) {
let now = Local::now();
let current_second = now.second();
if current_second != self.last_second || self.cached_time.is_empty() {
self.last_second = current_second;
self.cached_time = if self.show_date {
now.format("%a %b %d, %H:%M").to_string()
} else {
now.format("%H:%M:%S").to_string()
};
}
}
}
impl Default for DateTimeWidget {
fn default() -> Self {
Self::new(false)
}
}
impl Widget for DateTimeWidget {
fn width(&self) -> u16 {
(self.cached_time.len() + 2) as u16
}
fn render(&self, buffer: &mut VideoBuffer, x: u16, theme: &Theme, ctx: &WidgetContext) {
let time_str = format!(" {} ", &self.cached_time);
let bg_color = match ctx.focus {
FocusState::Desktop | FocusState::Topbar => theme.topbar_bg_focused,
FocusState::Window(_) => theme.topbar_bg_unfocused,
};
let fg_color = theme.window_border_unfocused_fg;
for (i, ch) in time_str.chars().enumerate() {
buffer.set(x + i as u16, 0, Cell::new_unchecked(ch, fg_color, bg_color));
}
}
fn is_visible(&self, _ctx: &WidgetContext) -> bool {
true }
fn contains(&self, point_x: u16, point_y: u16, widget_x: u16) -> bool {
point_y == 0 && point_x >= widget_x && point_x < widget_x + self.width()
}
fn update_hover(&mut self, mouse_x: u16, mouse_y: u16, widget_x: u16) {
self.hovered = self.contains(mouse_x, mouse_y, widget_x);
}
fn handle_click(&mut self, mouse_x: u16, mouse_y: u16, widget_x: u16) -> WidgetClickResult {
if self.contains(mouse_x, mouse_y, widget_x) {
WidgetClickResult::OpenCalendar
} else {
WidgetClickResult::NotHandled
}
}
fn reset_state(&mut self) {
self.hovered = false;
}
fn update(&mut self, ctx: &WidgetContext) {
if self.show_date != ctx.show_date_in_clock {
self.show_date = ctx.show_date_in_clock;
self.last_second = 60; }
self.refresh_time_if_needed();
}
fn alignment(&self) -> WidgetAlignment {
WidgetAlignment::Center
}
}