206 lines
5.5 KiB
Rust
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)));
|
|
}
|
|
}
|