use std::ffi::CString;
use std::num::NonZeroU32;
use crate::{CWindowConfig, CWindowEvent};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct WindowConfig {
pub title: Option<String>,
pub default_width: NonZeroU32,
pub default_height: NonZeroU32,
pub default_x: u32,
pub default_y: u32,
pub visible: bool,
pub borderless_fullscreen: bool,
}
pub struct Window {
pub(crate) ptr: *mut (),
}
pub enum WindowEvent {
Other = 1,
CloseRequest,
ScaleFactorChange,
Resume,
RedrawRequest,
}
impl Drop for Window {
fn drop(&mut self) {
unsafe { crate::destroy_window(self.ptr) }
}
}
impl Window {
pub fn new(config: WindowConfig) -> Self {
let title = config
.title
.map(|title| CString::new(title.as_bytes()).unwrap());
let config = CWindowConfig {
default_width: config.default_width.get(),
default_height: config.default_height.get(),
default_x: config.default_x,
default_y: config.default_y,
visible: config.visible,
borderless_fullscreen: config.borderless_fullscreen,
title: title
.as_ref()
.map(|title| title.as_ptr())
.unwrap_or(std::ptr::null()),
};
let window = unsafe { crate::create_window(config) };
drop(title);
Self { ptr: window }
}
pub fn set_visible(&mut self, visible: bool) {
unsafe { crate::set_visible(self.ptr, visible) }
}
pub fn set_title(&mut self, title: &str) {
let string = CString::new(title.to_string().as_bytes()).unwrap();
let bytes = string.as_ptr();
unsafe { crate::set_title(self.ptr, bytes) }
drop(string);
}
pub fn resize(&mut self, width: u32, height: u32) {
unsafe { crate::resize_window(self.ptr, width, height) }
}
pub fn set_fullscreen(&mut self, fullscreen: bool) {
unsafe { crate::set_fullscreen(self.ptr, fullscreen) }
}
fn translate_event(event: CWindowEvent) -> Option<WindowEvent> {
let event = match event {
CWindowEvent::AboutToWait => return None,
CWindowEvent::Other => WindowEvent::Other,
CWindowEvent::CloseRequest => WindowEvent::CloseRequest,
CWindowEvent::ScaleFactorChange => WindowEvent::ScaleFactorChange,
CWindowEvent::Resume => WindowEvent::Resume,
CWindowEvent::RedrawRequest => WindowEvent::RedrawRequest,
};
Some(event)
}
pub fn wait_for_event(&self) {
unsafe { crate::wait_for_event(self.ptr) }
}
pub fn pop_event(&self) -> bool {
unsafe { crate::pop_event(self.ptr) }
}
pub fn wait_for_resume(&mut self) {
unsafe { crate::wait_for_resume(self.ptr) }
}
pub fn run(&mut self, mut handler: impl FnMut(&mut Window, Option<WindowEvent>)) -> ! {
let window_ptr = self.ptr;
unsafe {
let closure = |c_event: CWindowEvent| {
handler(self, Self::translate_event(c_event));
};
let closure_data: Box<Box<dyn FnMut(CWindowEvent)>> = Box::new(Box::new(closure));
crate::set_event_handler(window_ptr, Box::into_raw(closure_data) as *mut _);
}
loop {
if !self.pop_event() {
unsafe { crate::run_event_handler(window_ptr, CWindowEvent::AboutToWait) };
}
}
}
pub fn request_redraw(&mut self) {
unsafe { crate::request_redraw(self.ptr) }
}
}
|