use crate::application::{ApplicationCallbacks, ApplicationRunning};
use crate::input::*;
use crate::platform::{PlatformWindow, PlatformWindowBuilder};
use crate::*;
use std::mem::transmute;
use std::ops::{Deref, DerefMut};
pub type WindowHandle = platform::WindowHandle;
pub(crate) type Ptr<T> = Box<T>;
#[derive(Debug, Copy, Clone)]
pub enum WindowStyle {
Windowed(Windowed),
}
impl From<Windowed> for WindowStyle {
fn from(style: Windowed) -> Self {
Self::Windowed(style)
}
}
impl Default for WindowStyle {
fn default() -> Self {
Windowed::default().into()
}
}
#[derive(Debug, Copy, Clone)]
pub struct Windowed {
pub origin: Option<Point>,
pub extent: Option<Extent>,
pub extent_min: Option<Extent>,
pub extent_max: Option<Extent>,
pub resizable: bool,
pub decorated: bool,
}
impl Windowed {
pub fn with_origin(mut self, origin: impl Into<Option<Point>>) -> Self {
self.origin = origin.into();
self
}
pub fn with_extent(mut self, extent: impl Into<Option<Extent>>) -> Self {
self.extent = extent.into();
self
}
pub fn with_extent_min(mut self, extent: Option<Extent>) -> Self {
self.extent_min = extent;
self
}
pub fn with_extent_max(mut self, extent: Option<Extent>) -> Self {
self.extent_max = extent;
self
}
pub fn with_resizeable(mut self, resizeable: bool) -> Self {
self.resizable = resizeable;
self
}
pub fn with_decorated(mut self, decorated: bool) -> Self {
self.decorated = decorated;
self
}
}
impl Default for Windowed {
fn default() -> Self {
Self {
origin: None,
extent: None,
extent_min: None,
extent_max: None,
resizable: true,
decorated: true,
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Visibility {
Normal,
Minimized,
Maximized,
}
#[derive(Debug)]
pub struct EventKey {
pub key: VirtualKey,
pub state: KeyState,
}
#[derive(Debug)]
pub struct EventChar {
pub ch: char,
}
#[derive(Debug)]
pub struct EventMouseMove {
pub position: Point,
}
#[derive(Debug)]
pub struct EventMouseButton {
pub button: MouseButton,
pub state: ButtonState,
pub position: Point,
}
#[derive(Debug)]
pub struct EventMouseWheel {
pub delta_y: i32,
pub delta_x: i32,
pub position: Point,
}
#[derive(Debug)]
pub struct EventShown {
pub shown: bool,
}
#[derive(Debug)]
pub struct EventMoved {
pub origin: Point,
}
#[derive(Debug)]
pub struct EventResized {
pub extent: Extent,
}
#[derive(Debug)]
pub struct EventFocused {
pub is_focused: bool,
}
#[derive(Debug)]
pub struct EventClose {}
#[derive(Debug)]
pub struct EventClosing {}
#[derive(Debug)]
pub struct EventClosed {}
#[derive(Debug)]
pub struct EventRedraw {}
#[derive(Debug)]
pub struct EventCreate {}
#[derive(Debug)]
pub struct EventVisibility {
pub visibility: Visibility,
}
#[allow(unused_variables)]
pub trait WindowCallbacks: Sized {
type Error: std::error::Error;
fn on_created(this: &Window<Self>, event: &EventCreate) -> Result<(), Self::Error> {
Ok(())
}
fn on_close(this: &Window<Self>, event: &EventClose) -> Result<bool, Self::Error> {
Ok(true)
}
fn on_closing(this: &Window<Self>, event: &EventClosing) -> Result<(), Self::Error> {
Ok(())
}
fn on_closed(this: &Window<Self>, event: &EventClosed) -> Result<(), Self::Error> {
Ok(())
}
fn redraw_requested(this: &Window<Self>, event: &EventRedraw) -> Result<(), Self::Error> {
Ok(())
}
fn on_shown(this: &Window<Self>, event: &EventShown) -> Result<(), Self::Error> {
Ok(())
}
fn on_visibility(this: &Window<Self>, event: &EventVisibility) -> Result<(), Self::Error> {
Ok(())
}
fn on_moved(this: &Window<Self>, event: &EventMoved) -> Result<(), Self::Error> {
Ok(())
}
fn on_resized(this: &Window<Self>, event: &EventResized) -> Result<(), Self::Error> {
Ok(())
}
fn on_focus(this: &Window<Self>, event: &EventFocused) -> Result<(), Self::Error> {
Ok(())
}
fn on_key(this: &Window<Self>, event: &EventKey) -> Result<(), Self::Error> {
Ok(())
}
fn on_char(this: &Window<Self>, event: &EventChar) -> Result<(), Self::Error> {
Ok(())
}
fn on_mouse_move(this: &Window<Self>, event: &EventMouseMove) -> Result<(), Self::Error> {
Ok(())
}
fn on_mouse_button(this: &Window<Self>, event: &EventMouseButton) -> Result<(), Self::Error> {
Ok(())
}
fn on_mouse_wheel(this: &Window<Self>, event: &EventMouseWheel) -> Result<(), Self::Error> {
Ok(())
}
}
impl WindowCallbacks for () {
type Error = WingmanError;
}
pub struct WindowBuilder<C: WindowCallbacks = ()> {
platform: platform::WindowBuilder<C>,
}
impl WindowBuilder {
fn new() -> Self {
Self {
platform: platform::WindowBuilder::new(()),
}
}
}
impl Default for WindowBuilder {
fn default() -> Self {
Self::new()
}
}
impl<C: WindowCallbacks> WindowBuilder<C> {
pub fn with_callbacks<D: WindowCallbacks>(self, callbacks: D) -> WindowBuilder<D> {
WindowBuilder {
platform: self.platform.with_callbacks(callbacks),
}
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.platform = self.platform.with_title(title.into());
self
}
pub fn with_style(mut self, style: impl Into<WindowStyle>) -> Self {
self.platform = self.platform.with_style(style.into());
self
}
pub fn build<E: From<C::Error>, A: ApplicationCallbacks<Error = E>>(
self,
app: &mut ApplicationRunning<A>,
) -> WingmanResult<WindowPtr<C>> {
Ok(unsafe { transmute(self.platform.build()?) })
}
}
#[repr(transparent)]
pub struct Window<C: WindowCallbacks> {
pub(crate) platform: platform::Window<C>,
}
impl Window<()> {
fn builder() -> WindowBuilder {
WindowBuilder::new()
}
}
pub fn window() -> WindowBuilder {
Window::builder()
}
impl<C: WindowCallbacks> Window<C> {
pub fn handle(&self) -> WindowHandle {
self.platform.handle()
}
pub fn is_closed(&self) -> bool {
self.platform.is_closed()
}
pub fn show(&mut self) -> WingmanResult<()> {
self.platform.show()
}
pub fn set_title(&mut self, title: impl Into<String>) -> WingmanResult<()> {
self.platform.set_title(title.into())
}
pub fn set_pos(&mut self, pos: Point) -> WingmanResult<()> {
self.platform.set_pos(pos)
}
pub fn set_size(&mut self, size: Extent) -> WingmanResult<()> {
self.platform.set_size(size)
}
}
impl<C: WindowCallbacks> Deref for Window<C> {
type Target = C;
fn deref(&self) -> &Self::Target {
self.platform.callbacks()
}
}
impl<C: WindowCallbacks> DerefMut for Window<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.platform.callbacks_mut()
}
}
#[repr(transparent)]
pub struct WindowPtr<C: WindowCallbacks> {
ptr: Ptr<Window<C>>,
}
impl<C: WindowCallbacks> Deref for WindowPtr<C> {
type Target = Window<C>;
fn deref(&self) -> &Self::Target {
self.ptr.as_ref()
}
}
impl<C: WindowCallbacks> DerefMut for WindowPtr<C> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.ptr.as_mut()
}
}