use std::future::Future;
use unsafe_send_sync::UnsafeSend;
use crate::{application::*, core::prelude::*, window::*};
macro_rules! _def_event {
( $(#[$metas:meta])*, $args_type:ty, $name:ident, $name_async:ident ) => {
$(#[$metas])*
#[cfg(not(feature = "threadsafe"))]
pub fn $name<H>( &mut self, handler: H ) -> &mut Self where
H: FnMut( &$args_type ) + 'static
{
self.events.$name.register( handler );
self
}
$(#[$metas])*
#[cfg(feature = "threadsafe")]
pub fn $name<H>( &mut self, handler: H ) -> &mut Self where
H: FnMut( &$args_type ) + Send + 'static
{
self.events.$name.register( handler );
self
}
$(#[$metas])*
#[cfg(not(feature = "threadsafe"))]
pub fn $name_async<H,F>( &mut self, handler: H ) -> &mut Self where
H: FnMut( &$args_type ) -> F + 'static,
F: Future<Output=()> + 'static
{
self.events.$name.register_async( handler );
self
}
$(#[$metas])*
#[cfg(feature = "threadsafe")]
pub fn $name_async<H,F>( &mut self, handler: H ) -> &mut Self where
H: FnMut( &$args_type ) -> F + Send + 'static,
F: Future<Output=()> + 'static
{
self.events.$name.register_async( handler );
self
}
};
}
macro_rules! def_event {
( $(#[$metas:meta])* $args_type:ty, $name:ident, $name_async:ident ) => {
_def_event!( $(#[$metas])*, $args_type, $name, $name_async );
};
( $(#[$metas:meta])* $name:ident, $name_async:ident ) => {
_def_event!( $(#[$metas])*, WindowHandle, $name, $name_async );
};
}
pub struct WindowBuilder {
pub(crate) borders: bool,
pub(crate) events: Box<WindowEvents>,
pub(crate) height: Option<u32>,
pub(crate) minimizable: bool,
pub(crate) parent: Option<UnsafeSend<WindowHandle>>,
pub(crate) resizable: bool,
pub(crate) title: Option<String>,
pub(crate) width: Option<u32>,
}
struct WindowUserData {
events: Box<WindowEvents>,
}
#[allow(dead_code)]
pub type WindowOptions = cbw_WindowOptions;
impl WindowBuilder {
def_event! { #[doc(hidden)]
on_close, on_close_async
}
def_event! { #[doc(hidden)]
WindowResizeEventArgs, on_resize, on_resize_async
}
pub fn borders(&mut self, value: bool) -> &mut Self {
self.borders = value;
self
}
fn build(self, app: ApplicationHandle) {
let title: &str = match self.title.as_ref() {
None => "",
Some(t) => t,
};
let window_options = WindowOptions {
borders: self.borders,
minimizable: self.minimizable,
resizable: self.resizable,
};
let user_data = Box::new(WindowUserData {
events: unsafe { Box::from_raw(Box::into_raw(self.events)) }, });
let parent_impl_handle = match self.parent {
None => WindowImpl::default(),
Some(parent) => parent.inner.clone(),
};
let _impl_handle = WindowImpl::new(
app.inner,
parent_impl_handle,
title.into(),
self.width as _,
self.height as _,
&window_options,
Box::into_raw(user_data) as _,
);
}
pub fn height(&mut self, height: u32) -> &mut Self {
self.height = Some(height);
self
}
pub fn minimizable(&mut self, value: bool) -> &mut Self {
self.minimizable = value;
self
}
pub fn parent<W>(&mut self, bw: &W) -> &mut Self
where
W: OwnedWindow,
{
self.parent = Some(UnsafeSend::new(bw.window_handle()));
self
}
pub fn new() -> Self {
Self {
borders: true,
height: None,
minimizable: true,
parent: None,
resizable: true,
title: None,
width: None,
events: Box::new(WindowEvents::default()),
}
}
pub fn size(&mut self, width: u32, height: u32) -> &mut Self {
self.width = Some(width);
self.height = Some(height);
self
}
pub fn title<S: Into<String>>(&mut self, title: S) -> &mut Self {
self.title = Some(title.into());
self
}
pub fn width(&mut self, width: u32) -> &mut Self {
self.width = Some(width);
self
}
pub fn resizable(&mut self, resizable: bool) -> &mut Self {
self.resizable = resizable;
self
}
}