206 lines
5.5 KiB
Rust

use crate::services::windows::window::{Window, WindowId};
use crate::task::TaskId;
use crate::windows::WindowOwner;
use prometeu_hal::color::Color;
use prometeu_hal::primitives::Rect;
/// PROMETEU Window Manager.
pub struct WindowManager {
pub windows: Vec<Window>,
pub focused: Option<WindowId>,
}
impl Default for WindowManager {
fn default() -> Self {
Self::new()
}
}
impl WindowManager {
pub fn new() -> Self {
Self { windows: Vec::new(), focused: None }
}
pub fn add_window(
&mut self,
title: String,
owner: WindowOwner,
viewport: Rect,
color: Color,
) -> WindowId {
let id = WindowId(self.windows.len() as u32);
let window = Window { id, owner, viewport, has_focus: false, title, color };
self.windows.push(window);
id
}
pub fn remove_window(&mut self, id: WindowId) {
self.windows.retain(|w| w.id != id);
if self.focused == Some(id) {
self.focused = None;
}
}
pub fn remove_all_windows(&mut self) {
self.windows.clear();
self.focused = None;
}
pub fn set_focus(&mut self, id: WindowId) {
self.focused = Some(id);
for window in &mut self.windows {
window.has_focus = window.id == id;
}
}
pub fn focused_window_belongs_to_task(&self, task_id: TaskId) -> bool {
let Some(focused_id) = self.focused else {
return false;
};
self.windows
.iter()
.find(|window| window.id == focused_id)
.is_some_and(|window| window.owner == WindowOwner::Task(task_id))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_window_manager_focus() {
let mut wm = WindowManager::new();
let id1 = wm.add_window(
"Window 1".to_string(),
WindowOwner::Hub,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
let id2 = wm.add_window(
"Window 2".to_string(),
WindowOwner::Hub,
Rect { x: 10, y: 10, w: 10, h: 10 },
Color::WHITE,
);
assert_eq!(wm.windows.len(), 2);
assert_eq!(wm.focused, None);
wm.set_focus(id1);
assert_eq!(wm.focused, Some(id1));
assert!(wm.windows[0].has_focus);
assert!(!wm.windows[1].has_focus);
wm.set_focus(id2);
assert_eq!(wm.focused, Some(id2));
assert!(!wm.windows[0].has_focus);
assert!(wm.windows[1].has_focus);
}
#[test]
fn test_window_manager_remove_window() {
let mut wm = WindowManager::new();
let id = wm.add_window(
"Window".to_string(),
WindowOwner::Hub,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id);
assert_eq!(wm.focused, Some(id));
wm.remove_window(id);
assert_eq!(wm.windows.len(), 0);
assert_eq!(wm.focused, None);
}
#[test]
fn focused_window_belongs_to_task_returns_false_without_focus() {
let mut wm = WindowManager::new();
wm.add_window(
"Task Window".to_string(),
WindowOwner::Task(crate::task::TaskId(1)),
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
#[test]
fn focused_window_belongs_to_task_matches_focused_task_owner() {
let mut wm = WindowManager::new();
let id = wm.add_window(
"Task Window".to_string(),
WindowOwner::Task(crate::task::TaskId(1)),
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id);
assert!(wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
#[test]
fn focused_window_belongs_to_task_rejects_other_task_owner() {
let mut wm = WindowManager::new();
let id = wm.add_window(
"Task Window".to_string(),
WindowOwner::Task(crate::task::TaskId(2)),
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id);
assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
#[test]
fn focused_window_belongs_to_task_rejects_hub_owner() {
let mut wm = WindowManager::new();
let id = wm.add_window(
"Hub Window".to_string(),
WindowOwner::Hub,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id);
assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
#[test]
fn focused_window_belongs_to_task_rejects_overlay_owner() {
let mut wm = WindowManager::new();
let id = wm.add_window(
"Overlay Window".to_string(),
WindowOwner::Overlay,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id);
assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
#[test]
fn focused_window_belongs_to_task_rejects_stale_focus() {
let mut wm = WindowManager::new();
wm.add_window(
"Task Window".to_string(),
WindowOwner::Task(crate::task::TaskId(1)),
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.focused = Some(WindowId(999));
assert!(!wm.focused_window_belongs_to_task(crate::task::TaskId(1)));
}
}