extern crate event_loop;
extern crate window as pistoncore_window;
extern crate glutin_window;
use event;
use piston_input::{Event, GenericEvent, AfterRenderEvent};
use self::glutin_window::GlutinWindow;
use self::pistoncore_window::Window as BasicWindow;
use std::time::Duration;
use super::gfx::{GfxContext, G2d};
use super::shader_version::OpenGL;
pub use self::event_loop::WindowEvents;
pub use self::pistoncore_window::{AdvancedWindow, Position, Size, OpenGLWindow,
WindowSettings, BuildFromWindowSettings};
pub use super::gfx::{draw, GlyphCache};
pub struct Window<W: BasicWindow = GlutinWindow> {
pub window: W,
pub context: GfxContext,
}
impl<W> BuildFromWindowSettings for Window<W>
where W: BasicWindow + OpenGLWindow + BuildFromWindowSettings,
W::Event: GenericEvent
{
fn build_from_window_settings(settings: &WindowSettings) -> Result<Window<W>, String> {
let settings = settings.clone().srgb(true);
let mut window: W = try!(settings.build());
let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
let samples = settings.get_samples();
let context = GfxContext::new(&mut window, opengl, samples);
Ok(Window::new(window, context))
}
}
impl<W> Window<W>
where W: BasicWindow, W::Event: GenericEvent
{
pub fn new(window: W, context: GfxContext) -> Self
where W: OpenGLWindow
{
Window {
window: window,
context: context,
}
}
pub fn draw_2d<E, F, U>(&mut self, e: &E, f: F) -> Option<U> where
W: OpenGLWindow,
E: GenericEvent,
F: FnOnce(super::draw::Context, &mut G2d) -> U
{
self.window.make_current();
if let Some(args) = e.render_args() {
Some(self.context.draw_2d(f, args))
} else {
None
}
}
pub fn next_event<E>(&mut self, events: &mut E) -> Option<Event>
where Self: EventWindow<E>,
{
EventWindow::next(self, events)
}
pub fn handle_event(&mut self, event: &Event<W::Event>) {
if let Some(_) = event.after_render_args() {
self.context.after_render();
}
self.context.check_resize(self.window.draw_size());
}
}
impl<W> BasicWindow for Window<W>
where W: BasicWindow
{
type Event = <W as BasicWindow>::Event;
fn should_close(&self) -> bool { self.window.should_close() }
fn set_should_close(&mut self, value: bool) {
self.window.set_should_close(value)
}
fn size(&self) -> Size { self.window.size() }
fn draw_size(&self) -> Size { self.window.draw_size() }
fn swap_buffers(&mut self) { self.window.swap_buffers() }
fn wait_event(&mut self) -> Self::Event {
BasicWindow::wait_event(&mut self.window)
}
fn wait_event_timeout(&mut self, timeout: Duration) -> Option<Self::Event> {
BasicWindow::wait_event_timeout(&mut self.window, timeout)
}
fn poll_event(&mut self) -> Option<Self::Event> {
BasicWindow::poll_event(&mut self.window)
}
}
impl<W> AdvancedWindow for Window<W>
where W: AdvancedWindow
{
fn get_title(&self) -> String { self.window.get_title() }
fn set_title(&mut self, title: String) {
self.window.set_title(title)
}
fn get_exit_on_esc(&self) -> bool { self.window.get_exit_on_esc() }
fn set_exit_on_esc(&mut self, value: bool) {
self.window.set_exit_on_esc(value)
}
fn set_capture_cursor(&mut self, value: bool) {
self.window.set_capture_cursor(value)
}
fn show(&mut self) { self.window.show() }
fn hide(&mut self) { self.window.hide() }
fn get_position(&self) -> Option<Position> {
self.window.get_position()
}
fn set_position<P: Into<Position>>(&mut self, pos: P) {
self.window.set_position(pos)
}
}
impl GlyphCache {
pub fn new(window: &mut Window, width: u32, height: u32) -> GlyphCache {
GlyphCache::new_from_factory(&mut window.context.factory, width, height)
}
}
pub trait EventWindow<E>: BasicWindow {
fn next(&mut self, events: &mut E) -> Option<Event>;
}
impl EventWindow<WindowEvents> for Window {
fn next(&mut self, events: &mut WindowEvents) -> Option<Event> {
events.next(&mut self.window).map(|e| {
self.handle_event(&e);
e
})
}
}
pub fn convert_event<E, B>(event: E, window: &Window<B>) -> Option<event::Input>
where E: GenericEvent,
B: BasicWindow,
{
use Scalar;
let size = window.size();
let (w, h) = (size.width as Scalar, size.height as Scalar);
super::event::convert(event, w, h)
}