use ponsic_winsafe::{graphics::Context, *};
use std::{
any::type_name,
ops::{Deref, DerefMut},
sync::OnceLock,
};
fn window_proc(events: Events, mut data: The<WindowData>) -> Return {
if let Some(mut data) = data.as_mut() {
match events.event {
Event::Paint { context } => {
data.item.draw(context);
Return::Default
}
_ => data.item.handle(events)
}
} else {
Return::Default
}
}
pub trait Proc {
fn handle(&mut self, events: Events) -> Return;
fn draw(&mut self, context: Context);
}
pub struct WindowData {
item: Box<dyn Proc>,
}
pub struct Window {
window: ponsic_winsafe::Window,
data: The<WindowData>,
}
impl Deref for Window {
type Target = ponsic_winsafe::Window;
fn deref(&self) -> &Self::Target {
&self.window
}
}
impl DerefMut for Window {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.window
}
}
impl Window {
pub fn create<T: Proc + 'static>(
rect: Recti,
title: &str,
parent: Option<WindowId>,
item: T,
) -> Result<Self, SystemError> {
static CLASS: OnceLock<Result<Class, SystemError>> = OnceLock::new();
let class = CLASS
.get_or_init(|| -> Result<Class, SystemError> {
let class = Registrar::new(type_name::<Self>())
.set_process(wndproc!(WindowData;window_proc))
.set_cursor(ponsic_winsafe::Cursor::Arrow)
.build()?;
Ok(class)
})
.clone()?;
let data = WindowData {
item: Box::new(item),
};
let window = if let Some(parent) = parent {
class
.make_window(rect)
.set_title(title)
.set_parent(parent)
.set_style(&[WindowStyle::Child])
.bind_data(data)
.build()?
} else {
class
.make_window(rect)
.set_title(title)
.set_style(&[WindowStyle::OverlappedWindow])
.bind_data(data)
.build()?
};
let data = window.data();
Ok(Self { window, data })
}
}
impl AsRef<The<WindowData>> for Window {
fn as_ref(&self) -> &The<WindowData> {
&self.data
}
}
impl AsMut<The<WindowData>> for Window {
fn as_mut(&mut self) -> &mut The<WindowData> {
&mut self.data
}
}