Add iterators for events and WindowBuilder

This commit is contained in:
Tomaka17 2014-08-02 08:24:30 +02:00
parent 959613870c
commit 5dda167021
7 changed files with 104 additions and 148 deletions

View file

@ -5,8 +5,6 @@ extern crate gl;
use std::io::stdio::stdin; use std::io::stdio::stdin;
fn main() { fn main() {
use std::default::Default;
// enumerating monitors // enumerating monitors
let monitor = { let monitor = {
for (num, monitor) in init::get_available_monitors().enumerate() { for (num, monitor) in init::get_available_monitors().enumerate() {
@ -23,8 +21,11 @@ fn main() {
monitor monitor
}; };
let window = init::Window::new(None, "Hello world!", &Default::default(), let window = init::WindowBuilder::new()
Some(monitor)).unwrap(); .with_title("Hello world!".to_string())
.with_monitor(monitor)
.build()
.unwrap();
unsafe { window.make_current() }; unsafe { window.make_current() };
@ -40,7 +41,7 @@ fn main() {
gl::ClearColor(0.0, 1.0, 0.0, 1.0); gl::ClearColor(0.0, 1.0, 0.0, 1.0);
while !window.is_closed() { while !window.is_closed() {
println!("{}", window.wait_events()); println!("{}", window.wait_events().collect::<Vec<init::Event>>());
gl::Clear(gl::COLOR_BUFFER_BIT); gl::Clear(gl::COLOR_BUFFER_BIT);

View file

@ -3,9 +3,7 @@ extern crate libc;
extern crate gl; extern crate gl;
fn main() { fn main() {
use std::default::Default; let window = init::Window::new().unwrap();
let window = init::Window::new(None, "Hello world!", &Default::default(), None).unwrap();
unsafe { window.make_current() }; unsafe { window.make_current() };
@ -21,7 +19,7 @@ fn main() {
gl::ClearColor(0.0, 1.0, 0.0, 1.0); gl::ClearColor(0.0, 1.0, 0.0, 1.0);
while !window.is_closed() { while !window.is_closed() {
println!("{}", window.wait_events()); println!("{}", window.wait_events().collect::<Vec<init::Event>>());
gl::Clear(gl::COLOR_BUFFER_BIT); gl::Clear(gl::COLOR_BUFFER_BIT);

View file

@ -1,74 +0,0 @@
use std::default::Default;
#[deriving(Clone,Show)]
#[deprecated = "Will be removed soon (it's not supported anyway)"]
pub struct Hints {
pub resizable: bool,
pub visible: bool,
pub decorated: bool,
pub red_bits: u8,
pub green_bits: u8,
pub blue_bits: u8,
pub alpha_bits: u8,
pub depth_bits: u8,
pub stencil_bits: u8,
pub accum_red_bits: u8,
pub accum_green_bits: u8,
pub accum_blue_bits: u8,
pub accum_alpha_bits: u8,
pub aux_buffers: u8,
pub samples: u8,
pub refresh_rate: u8,
pub stereo: bool,
pub srgb_capable: bool,
pub client_api: ClientAPI,
pub context_version: (u8, u8),
//pub robustness: ,
pub opengl_forward_compat: bool,
pub opengl_debug_context: bool,
pub opengl_profile: Profile,
}
#[deriving(Clone, Show)]
pub enum ClientAPI {
OpenGL,
OpenGLES,
}
#[deriving(Clone, Show)]
pub enum Profile {
AnyProfile,
CompatProfile,
CoreProfile,
}
impl Default for Hints {
fn default() -> Hints {
Hints {
resizable: true,
visible: true,
decorated: true,
red_bits: 8,
green_bits: 8,
blue_bits: 8,
alpha_bits: 8,
depth_bits: 24,
stencil_bits: 8,
accum_red_bits: 0,
accum_green_bits: 0,
accum_blue_bits: 0,
accum_alpha_bits: 0,
aux_buffers: 0,
samples: 0,
refresh_rate: 0,
stereo: false,
srgb_capable: false,
client_api: OpenGL,
context_version: (1, 0),
//robustness: ,
opengl_forward_compat: false,
opengl_debug_context: false,
opengl_profile: AnyProfile,
}
}
}

View file

@ -5,7 +5,6 @@
extern crate libc; extern crate libc;
pub use events::*; pub use events::*;
pub use hints::{Hints, ClientAPI, Profile};
#[cfg(windows)] #[cfg(windows)]
use winimpl = win32; use winimpl = win32;
@ -21,19 +20,63 @@ mod x11;
//mod egl; //mod egl;
mod events; mod events;
mod hints;
/// Identifier for a monitor. /// Identifier for a monitor.
pub struct MonitorID(winimpl::MonitorID); pub struct MonitorID(winimpl::MonitorID);
/// Object that allows you to build windows.
pub struct WindowBuilder {
dimensions: (uint, uint),
title: String,
monitor: Option<winimpl::MonitorID>,
}
impl WindowBuilder {
/// Initializes a new `WindowBuilder` with default values.
pub fn new() -> WindowBuilder {
WindowBuilder {
dimensions: (1024, 768),
title: String::new(),
monitor: None,
}
}
pub fn with_dimensions(mut self, width: uint, height: uint) -> WindowBuilder {
self.dimensions = (width, height);
self
}
pub fn with_title(mut self, title: String) -> WindowBuilder {
self.title = title;
self
}
pub fn with_monitor(mut self, monitor: MonitorID) -> WindowBuilder {
let MonitorID(monitor) = monitor;
self.monitor = Some(monitor);
self
}
/// Builds the window.
///
/// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc.
pub fn build(self) -> Result<Window, String> {
let win = try!(winimpl::Window::new(Some(self.dimensions),
self.title.as_slice(), self.monitor));
Ok(Window{
window: win,
})
}
}
/// Represents an OpenGL context and the Window or environment around it. /// Represents an OpenGL context and the Window or environment around it.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use std::default::Default; /// let window = Window::new().unwrap();
///
/// let window = Window::new(None, "Hello world!", &Default::default(), None).unwrap();
/// ///
/// unsafe { window.make_current() }; /// unsafe { window.make_current() };
/// ///
@ -58,42 +101,14 @@ pub struct Window {
impl Window { impl Window {
/// Creates a new OpenGL context, and a Window for platforms where this is appropriate. /// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
/// ///
/// # Parameters /// This function is equivalent to `WindowBuilder::new().build()`.
///
/// The `dimensions` parameter tell the library what the dimensions of the client area
/// of the window must be. If set to `None`, the library will choose or let the O/S choose.
///
/// The `title` parameter is the title that the window must have.
///
/// The `hints` parameter must be a `Hint` object which contains hints about how the context
/// must be created. This library will *try* to follow the hints, but will still success
/// even if it could not conform to all of them.
///
/// The `monitor` parameter is the identifier of the monitor that this window should fill.
/// If `None`, a windowed window will be created. If `Some(_)`, the window will be fullscreen
/// and will fill the given monitor. Note `MonitorID` does not necessarly represent a
/// *physical* monitor.
///
/// # Return value
///
/// Returns the `Window` object.
/// ///
/// Error should be very rare and only occur in case of permission denied, incompatible system, /// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc. /// out of memory, etc.
#[inline] #[inline]
pub fn new(dimensions: Option<(uint, uint)>, title: &str, pub fn new() -> Result<Window, String> {
hints: &Hints, monitor: Option<MonitorID>) let builder = WindowBuilder::new();
-> Result<Window, String> builder.build()
{
// extracting the monitor ID
let monitor = monitor.map(|id| { let MonitorID(id) = id; id });
// creating the window
let win = try!(winimpl::Window::new(dimensions, title, hints, monitor));
Ok(Window{
window: win,
})
} }
/// Returns true if the window has previously been closed by the user. /// Returns true if the window has previously been closed by the user.
@ -176,32 +191,22 @@ impl Window {
self.window.set_inner_size(x, y) self.window.set_inner_size(x, y)
} }
/// Returns all the events that are currently in window's events queue. /// Returns an iterator to all the events that are currently in the window's events queue.
/// ///
/// Contrary to `wait_events`, this function never blocks. /// Contrary to `wait_events`, this function never blocks.
#[experimental = "Will probably be changed to return an iterator instead of a Vec"]
#[inline] #[inline]
pub fn poll_events(&self) -> Vec<Event> { pub fn poll_events(&self) -> PollEventsIterator {
self.window.poll_events() PollEventsIterator { data: self.window.poll_events() }
} }
/// Returns all the events that are currently in window's events queue. /// Waits for an event, then returns an iterator to all the events that are currently
/// If there are no events in queue, this function will block until there is one. /// in the window's events queue.
/// ///
/// This is equivalent to: /// If there are no events in queue when you call the function,
/// /// this function will block until there is one.
/// ```
/// loop {
/// let events = poll_events();
/// if events.len() >= 1 { return events }
/// }
/// ```
///
/// ...but without the spinlock.
#[inline] #[inline]
#[experimental = "Will probably be changed to return an iterator instead of a Vec"] pub fn wait_events(&self) -> WaitEventsIterator {
pub fn wait_events(&self) -> Vec<Event> { WaitEventsIterator { data: self.window.wait_events() }
self.window.wait_events()
} }
/// Sets the context as the current context. /// Sets the context as the current context.
@ -229,6 +234,32 @@ impl Window {
} }
} }
/// An iterator for the `poll_events` function.
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct PollEventsIterator<'a> {
data: Vec<Event>,
}
impl<'a> Iterator<Event> for PollEventsIterator<'a> {
fn next(&mut self) -> Option<Event> {
self.data.remove(0)
}
}
/// An iterator for the `wait_events` function.
// Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future.
pub struct WaitEventsIterator<'a> {
data: Vec<Event>,
}
impl<'a> Iterator<Event> for WaitEventsIterator<'a> {
fn next(&mut self) -> Option<Event> {
self.data.remove(0)
}
}
/// An iterator for the list of available monitors. /// An iterator for the list of available monitors.
// Implementation note: we retreive the list once, then serve each element by one by one. // Implementation note: we retreive the list once, then serve each element by one by one.
// This may change in the future. // This may change in the future.

View file

@ -6,7 +6,7 @@ use std::sync::atomics::AtomicBool;
use std::ptr; use std::ptr;
use super::{event, ffi}; use super::{event, ffi};
use super::{MonitorID, Window}; use super::{MonitorID, Window};
use {Event, Hints}; use Event;
/// Stores the current window and its events dispatcher. /// Stores the current window and its events dispatcher.
/// ///
@ -15,7 +15,7 @@ use {Event, Hints};
local_data_key!(WINDOW: (ffi::HWND, Sender<Event>)) local_data_key!(WINDOW: (ffi::HWND, Sender<Event>))
pub fn new_window(dimensions: Option<(uint, uint)>, title: &str, pub fn new_window(dimensions: Option<(uint, uint)>, title: &str,
_hints: &Hints, monitor: Option<MonitorID>) monitor: Option<MonitorID>)
-> Result<Window, String> -> Result<Window, String>
{ {
use std::mem; use std::mem;

View file

@ -1,6 +1,6 @@
use std::sync::atomics::AtomicBool; use std::sync::atomics::AtomicBool;
use std::ptr; use std::ptr;
use {Event, Hints}; use Event;
pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
@ -36,10 +36,10 @@ pub struct Window {
impl Window { impl Window {
/// See the docs if the crate root file. /// See the docs if the crate root file.
pub fn new(dimensions: Option<(uint, uint)>, title: &str, pub fn new(dimensions: Option<(uint, uint)>, title: &str,
hints: &Hints, monitor: Option<MonitorID>) monitor: Option<MonitorID>)
-> Result<Window, String> -> Result<Window, String>
{ {
init::new_window(dimensions, title, hints, monitor) init::new_window(dimensions, title, monitor)
} }
/// See the docs if the crate root file. /// See the docs if the crate root file.

View file

@ -1,4 +1,4 @@
use {Event, Hints}; use Event;
use libc; use libc;
use std::{mem, ptr}; use std::{mem, ptr};
use std::sync::atomics::AtomicBool; use std::sync::atomics::AtomicBool;
@ -33,7 +33,7 @@ impl MonitorID {
} }
impl Window { impl Window {
pub fn new(dimensions: Option<(uint, uint)>, title: &str, hints: &Hints, _: Option<MonitorID>) pub fn new(dimensions: Option<(uint, uint)>, title: &str, _: Option<MonitorID>)
-> Result<Window, String> -> Result<Window, String>
{ {
// calling XOpenDisplay // calling XOpenDisplay