From 5dda16702164d59a75d8c36373cf29a8d7f4d58f Mon Sep 17 00:00:00 2001 From: Tomaka17 Date: Sat, 2 Aug 2014 08:24:30 +0200 Subject: Add iterators for events and WindowBuilder --- examples/fullscreen.rs | 11 ++-- examples/window.rs | 6 +- src/hints.rs | 74 ------------------------- src/lib.rs | 147 ++++++++++++++++++++++++++++++------------------- src/win32/init.rs | 4 +- src/win32/mod.rs | 6 +- src/x11/mod.rs | 4 +- 7 files changed, 104 insertions(+), 148 deletions(-) delete mode 100644 src/hints.rs diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index b6141a0..80e6089 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -5,8 +5,6 @@ extern crate gl; use std::io::stdio::stdin; fn main() { - use std::default::Default; - // enumerating monitors let monitor = { for (num, monitor) in init::get_available_monitors().enumerate() { @@ -23,8 +21,11 @@ fn main() { monitor }; - let window = init::Window::new(None, "Hello world!", &Default::default(), - Some(monitor)).unwrap(); + let window = init::WindowBuilder::new() + .with_title("Hello world!".to_string()) + .with_monitor(monitor) + .build() + .unwrap(); unsafe { window.make_current() }; @@ -40,7 +41,7 @@ fn main() { gl::ClearColor(0.0, 1.0, 0.0, 1.0); while !window.is_closed() { - println!("{}", window.wait_events()); + println!("{}", window.wait_events().collect::>()); gl::Clear(gl::COLOR_BUFFER_BIT); diff --git a/examples/window.rs b/examples/window.rs index daa856b..c366ee0 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -3,9 +3,7 @@ extern crate libc; extern crate gl; fn main() { - use std::default::Default; - - let window = init::Window::new(None, "Hello world!", &Default::default(), None).unwrap(); + let window = init::Window::new().unwrap(); unsafe { window.make_current() }; @@ -21,7 +19,7 @@ fn main() { gl::ClearColor(0.0, 1.0, 0.0, 1.0); while !window.is_closed() { - println!("{}", window.wait_events()); + println!("{}", window.wait_events().collect::>()); gl::Clear(gl::COLOR_BUFFER_BIT); diff --git a/src/hints.rs b/src/hints.rs deleted file mode 100644 index aaa9a80..0000000 --- a/src/hints.rs +++ /dev/null @@ -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, - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 83a75a4..155900d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ extern crate libc; pub use events::*; -pub use hints::{Hints, ClientAPI, Profile}; #[cfg(windows)] use winimpl = win32; @@ -21,19 +20,63 @@ mod x11; //mod egl; mod events; -mod hints; /// Identifier for a monitor. pub struct MonitorID(winimpl::MonitorID); +/// Object that allows you to build windows. +pub struct WindowBuilder { + dimensions: (uint, uint), + title: String, + monitor: Option, +} + +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 { + 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. /// /// # Example /// /// ``` -/// use std::default::Default; -/// -/// let window = Window::new(None, "Hello world!", &Default::default(), None).unwrap(); +/// let window = Window::new().unwrap(); /// /// unsafe { window.make_current() }; /// @@ -57,43 +100,15 @@ pub struct Window { impl Window { /// Creates a new OpenGL context, and a Window for platforms where this is appropriate. - /// - /// # Parameters - /// - /// 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. /// + /// This function is equivalent to `WindowBuilder::new().build()`. + /// /// Error should be very rare and only occur in case of permission denied, incompatible system, /// out of memory, etc. #[inline] - pub fn new(dimensions: Option<(uint, uint)>, title: &str, - hints: &Hints, monitor: Option) - -> Result - { - // 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, - }) + pub fn new() -> Result { + let builder = WindowBuilder::new(); + builder.build() } /// 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) } - /// 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. - #[experimental = "Will probably be changed to return an iterator instead of a Vec"] #[inline] - pub fn poll_events(&self) -> Vec { - self.window.poll_events() + pub fn poll_events(&self) -> PollEventsIterator { + PollEventsIterator { data: self.window.poll_events() } } - /// Returns all the events that are currently in window's events queue. - /// If there are no events in queue, this function will block until there is one. - /// - /// This is equivalent to: - /// - /// ``` - /// loop { - /// let events = poll_events(); - /// if events.len() >= 1 { return events } - /// } - /// ``` - /// - /// ...but without the spinlock. + /// Waits for an event, then returns an iterator to all the events that are currently + /// in the window's events queue. + /// + /// If there are no events in queue when you call the function, + /// this function will block until there is one. #[inline] - #[experimental = "Will probably be changed to return an iterator instead of a Vec"] - pub fn wait_events(&self) -> Vec { - self.window.wait_events() + pub fn wait_events(&self) -> WaitEventsIterator { + WaitEventsIterator { data: self.window.wait_events() } } /// 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, +} + +impl<'a> Iterator for PollEventsIterator<'a> { + fn next(&mut self) -> Option { + 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, +} + +impl<'a> Iterator for WaitEventsIterator<'a> { + fn next(&mut self) -> Option { + self.data.remove(0) + } +} + /// An iterator for the list of available monitors. // Implementation note: we retreive the list once, then serve each element by one by one. // This may change in the future. diff --git a/src/win32/init.rs b/src/win32/init.rs index db08a42..ce558dc 100644 --- a/src/win32/init.rs +++ b/src/win32/init.rs @@ -6,7 +6,7 @@ use std::sync::atomics::AtomicBool; use std::ptr; use super::{event, ffi}; use super::{MonitorID, Window}; -use {Event, Hints}; +use Event; /// Stores the current window and its events dispatcher. /// @@ -15,7 +15,7 @@ use {Event, Hints}; local_data_key!(WINDOW: (ffi::HWND, Sender)) pub fn new_window(dimensions: Option<(uint, uint)>, title: &str, - _hints: &Hints, monitor: Option) + monitor: Option) -> Result { use std::mem; diff --git a/src/win32/mod.rs b/src/win32/mod.rs index 7558245..0d44a75 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -1,6 +1,6 @@ use std::sync::atomics::AtomicBool; use std::ptr; -use {Event, Hints}; +use Event; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -36,10 +36,10 @@ pub struct Window { impl Window { /// See the docs if the crate root file. pub fn new(dimensions: Option<(uint, uint)>, title: &str, - hints: &Hints, monitor: Option) + monitor: Option) -> Result { - init::new_window(dimensions, title, hints, monitor) + init::new_window(dimensions, title, monitor) } /// See the docs if the crate root file. diff --git a/src/x11/mod.rs b/src/x11/mod.rs index 76339f5..bc89aed 100644 --- a/src/x11/mod.rs +++ b/src/x11/mod.rs @@ -1,4 +1,4 @@ -use {Event, Hints}; +use Event; use libc; use std::{mem, ptr}; use std::sync::atomics::AtomicBool; @@ -33,7 +33,7 @@ impl MonitorID { } impl Window { - pub fn new(dimensions: Option<(uint, uint)>, title: &str, hints: &Hints, _: Option) + pub fn new(dimensions: Option<(uint, uint)>, title: &str, _: Option) -> Result { // calling XOpenDisplay -- cgit v1.2.3