use super::{Widget, WidgetAlignment, WidgetClickResult, WidgetContext};
use crate::rendering::{Cell, Theme, VideoBuffer};
use crate::ui::button::ButtonState;
use crate::window::manager::FocusState;
pub struct SystemMenuWidget {
label: &'static str,
state: ButtonState,
menu_open: bool,
}
impl SystemMenuWidget {
const LABEL: &'static str = "System";
pub fn new() -> Self {
Self {
label: Self::LABEL,
state: ButtonState::Normal,
menu_open: false,
}
}
pub fn close_menu(&mut self) {
self.menu_open = false;
}
pub fn toggle_menu(&mut self) {
self.menu_open = !self.menu_open;
}
}
impl Default for SystemMenuWidget {
fn default() -> Self {
Self::new()
}
}
impl Widget for SystemMenuWidget {
fn width(&self) -> u16 {
(self.label.len() as u16) + 4
}
fn render(&self, buffer: &mut VideoBuffer, x: u16, theme: &Theme, ctx: &WidgetContext) {
let bg_color = match ctx.focus {
FocusState::Desktop | FocusState::Topbar => theme.topbar_bg_focused,
FocusState::Window(_) => theme.topbar_bg_unfocused,
};
let (fg_color, btn_bg) = match self.state {
ButtonState::Normal => (theme.window_border_unfocused_fg, bg_color),
ButtonState::Hovered => (theme.button_hovered_fg, theme.button_hovered_bg),
ButtonState::Pressed => (theme.button_pressed_fg, theme.button_pressed_bg),
};
let (fg_color, btn_bg) = if self.menu_open {
(theme.button_pressed_fg, theme.button_pressed_bg)
} else {
(fg_color, btn_bg)
};
let mut current_x = x;
buffer.set(current_x, 0, Cell::new_unchecked('[', fg_color, btn_bg));
current_x += 1;
buffer.set(current_x, 0, Cell::new_unchecked(' ', fg_color, btn_bg));
current_x += 1;
for ch in self.label.chars() {
buffer.set(current_x, 0, Cell::new_unchecked(ch, fg_color, btn_bg));
current_x += 1;
}
buffer.set(current_x, 0, Cell::new_unchecked(' ', fg_color, btn_bg));
current_x += 1;
buffer.set(current_x, 0, Cell::new_unchecked(']', fg_color, btn_bg));
}
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) {
if self.contains(mouse_x, mouse_y, widget_x) {
if self.state != ButtonState::Pressed {
self.state = ButtonState::Hovered;
}
} else if !self.menu_open {
self.state = ButtonState::Normal;
}
}
fn handle_click(&mut self, mouse_x: u16, mouse_y: u16, widget_x: u16) -> WidgetClickResult {
if self.contains(mouse_x, mouse_y, widget_x) {
self.state = ButtonState::Pressed;
self.toggle_menu();
WidgetClickResult::ToggleSystemMenu
} else {
WidgetClickResult::NotHandled
}
}
fn reset_state(&mut self) {
self.state = ButtonState::Normal;
}
fn update(&mut self, _ctx: &WidgetContext) {
}
fn alignment(&self) -> WidgetAlignment {
WidgetAlignment::Right
}
}