use std::vec; use std::vec::Vec; use std::boxed::Box; use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType, TASKBAR_HEIGHT }; use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse, WindowManagerRequest, ShortcutType, InfoType, WindowsVec }; use ming_wm_lib::framebuffer_types::Dimensions; use ming_wm_lib::themes::ThemeInfo; use ming_wm_lib::components::Component; use ming_wm_lib::components::toggle_button::ToggleButton; const PADDING: usize = 4; const META_WIDTH: usize = 175; //of the window button #[derive(Clone)] enum TaskbarMessage { ShowStartMenu, HideStartMenu, Nothing, // } pub struct Taskbar { dimensions: Dimensions, components: Vec + Send>>, windows_in_workspace: WindowsVec, focused_id: usize, } impl WindowLike for Taskbar { fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse { match message { WindowMessage::Init(dimensions) => { self.dimensions = dimensions; self.components = vec![ Box::new(ToggleButton::new("start-button".to_string(), [PADDING, PADDING], [44, self.dimensions[1] - (PADDING * 2)], "Start".to_string(), TaskbarMessage::ShowStartMenu, TaskbarMessage::HideStartMenu)), ]; WindowMessageResponse::JustRedraw }, WindowMessage::Shortcut(shortcut) => { match shortcut { ShortcutType::StartMenu => { let start_index = self.components.iter().position(|c| c.name() == "start-button").unwrap(); let start_response = self.components[start_index].handle_message(WindowMessage::FocusClick); self.handle_taskbar_message(start_response) } _ => WindowMessageResponse::DoNothing, } }, WindowMessage::Info(info) => { if let InfoType::WindowsInWorkspace(windows, focused_id) = info { self.windows_in_workspace = windows; self.focused_id = focused_id; WindowMessageResponse::JustRedraw } else { WindowMessageResponse::DoNothing } }, _ => WindowMessageResponse::DoNothing, } } //simple fn draw(&self, theme_info: &ThemeInfo) -> Vec { let mut instructions = vec![ //top thin white border DrawInstructions::Rect([0, 0], [self.dimensions[0], 1], theme_info.border_left_top), //the actual taskbar background DrawInstructions::Rect([0, 1], [self.dimensions[0], self.dimensions[1] - 1], theme_info.background), ]; for component in &self.components { instructions.extend(component.draw(theme_info)); } for wi in 0..self.windows_in_workspace.len() { //if too many windows to fit in taskbar... if wi > (self.dimensions[0] - 200) / META_WIDTH { // break; } let info = &self.windows_in_workspace[wi]; let name = &info.1; let mut b = ToggleButton::new(name.to_string() + "-window", [PADDING * 2 + 44 + (META_WIDTH + PADDING) * wi, PADDING], [META_WIDTH, self.dimensions[1] - (PADDING * 2)], name.to_string(), TaskbarMessage::Nothing, TaskbarMessage::Nothing); b.inverted = info.0 == self.focused_id; instructions.extend(b.draw(theme_info)); } instructions } //properties fn subtype(&self) -> WindowLikeType { WindowLikeType::Taskbar } fn ideal_dimensions(&self, dimensions: Dimensions) -> Dimensions { [dimensions[0], TASKBAR_HEIGHT] } } impl Taskbar { pub fn new() -> Self { Self { dimensions: [0, 0], components: Vec::new(), windows_in_workspace: Vec::new(), focused_id: 0, } } fn handle_taskbar_message(&mut self, message: Option) -> WindowMessageResponse { if let Some(message) = message { match message { TaskbarMessage::ShowStartMenu => { WindowMessageResponse::Request(WindowManagerRequest::OpenWindow("StartMenu".to_string())) }, TaskbarMessage::HideStartMenu => { WindowMessageResponse::Request(WindowManagerRequest::CloseStartMenu) }, _ => WindowMessageResponse::DoNothing, } } else { //maybe should be JustRedraw? WindowMessageResponse::DoNothing } } }