use std::error::Error;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ShellBackend {
Headless,
}
#[derive(Debug, Clone)]
pub struct NativeShell {
pub backend: ShellBackend,
pub window_title: String,
pub width: u32,
pub height: u32,
}
impl NativeShell {
pub fn new(title: &str) -> Self {
Self {
backend: ShellBackend::Headless,
window_title: title.to_string(),
width: 1280,
height: 720,
}
}
pub fn with_size(mut self, w: u32, h: u32) -> Self {
self.width = w;
self.height = h;
self
}
pub fn backend(mut self, backend: ShellBackend) -> Self {
self.backend = backend;
self
}
}
#[derive(Debug, Clone)]
pub struct ShellWindow {
pub id: u32,
pub title: String,
pub width: u32,
pub height: u32,
}
impl ShellWindow {
pub fn set_title(&mut self, title: &str) {
self.title = title.to_string();
}
pub fn resize(&mut self, w: u32, h: u32) {
self.width = w;
self.height = h;
}
pub fn close(self) {
}
}
#[derive(Debug, Clone)]
pub struct ShellError {
pub message: String,
}
impl fmt::Display for ShellError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ShellError: {}", self.message)
}
}
impl Error for ShellError {}
#[derive(Debug, Clone, PartialEq)]
pub enum WindowEvent {
Resized(u32, u32),
Focused,
Unfocused,
CloseRequested,
}
pub fn create_window(shell: &NativeShell) -> Result<ShellWindow, ShellError> {
match shell.backend {
ShellBackend::Headless => Ok(ShellWindow {
id: 0,
title: shell.window_title.clone(),
width: shell.width,
height: shell.height,
}),
}
}
pub fn poll_events(_window: &ShellWindow) -> Vec<WindowEvent> {
Vec::new()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_shell_new_defaults() {
let shell = NativeShell::new("Test App");
assert_eq!(shell.window_title, "Test App");
assert_eq!(shell.width, 1280);
assert_eq!(shell.height, 720);
assert_eq!(shell.backend, ShellBackend::Headless);
}
#[test]
fn test_shell_with_size() {
let shell = NativeShell::new("Sized").with_size(1920, 1080);
assert_eq!(shell.width, 1920);
assert_eq!(shell.height, 1080);
}
#[test]
fn test_shell_backend() {
let shell = NativeShell::new("Backend").backend(ShellBackend::Headless);
assert_eq!(shell.backend, ShellBackend::Headless);
}
#[test]
fn test_shell_builder_chain() {
let shell = NativeShell::new("Chained")
.with_size(800, 600)
.backend(ShellBackend::Headless);
assert_eq!(shell.window_title, "Chained");
assert_eq!(shell.width, 800);
assert_eq!(shell.height, 600);
assert_eq!(shell.backend, ShellBackend::Headless);
}
#[test]
fn test_create_window_headless() {
let shell = NativeShell::new("Headless Win").backend(ShellBackend::Headless);
let window = create_window(&shell).expect("Headless window creation should succeed");
assert_eq!(window.id, 0);
assert_eq!(window.title, "Headless Win");
assert_eq!(window.width, 1280);
assert_eq!(window.height, 720);
}
#[test]
fn test_window_set_title() {
let mut win = ShellWindow {
id: 1,
title: "Old".to_string(),
width: 800,
height: 600,
};
win.set_title("New Title");
assert_eq!(win.title, "New Title");
}
#[test]
fn test_window_resize() {
let mut win = ShellWindow {
id: 1,
title: "Resizable".to_string(),
width: 800,
height: 600,
};
win.resize(1920, 1080);
assert_eq!(win.width, 1920);
assert_eq!(win.height, 1080);
}
#[test]
fn test_window_close() {
let win = ShellWindow {
id: 1,
title: "Closable".to_string(),
width: 800,
height: 600,
};
win.close();
}
#[test]
fn test_poll_events_headless() {
let shell = NativeShell::new("Poll").backend(ShellBackend::Headless);
let window = create_window(&shell).unwrap();
let events = poll_events(&window);
assert!(events.is_empty());
}
#[test]
fn test_shell_error_display() {
let err = ShellError {
message: "something went wrong".to_string(),
};
assert_eq!(format!("{}", err), "ShellError: something went wrong");
}
#[test]
fn test_shell_error_implements_std_error() {
let err = ShellError {
message: "test".to_string(),
};
let _: &dyn Error = &err;
}
#[test]
fn test_window_event_equality() {
assert_eq!(WindowEvent::Focused, WindowEvent::Focused);
assert_eq!(
WindowEvent::Resized(800, 600),
WindowEvent::Resized(800, 600)
);
assert_ne!(WindowEvent::Focused, WindowEvent::Unfocused);
assert_ne!(
WindowEvent::Resized(800, 600),
WindowEvent::Resized(1024, 768)
);
}
}