diff options
-rw-r--r-- | examples/ggez/main.rs | 26 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/runtime.rs | 106 | ||||
-rw-r--r-- | src/user_interface.rs | 116 |
4 files changed, 135 insertions, 117 deletions
diff --git a/examples/ggez/main.rs b/examples/ggez/main.rs index 4719418e..11ea6492 100644 --- a/examples/ggez/main.rs +++ b/examples/ggez/main.rs @@ -27,7 +27,8 @@ pub fn main() -> ggez::GameResult { struct Game { spritesheet: graphics::Image, - runtime: iced::Runtime, + cache: Option<iced::Cache>, + events: Vec<iced::Event>, tour: Tour, } @@ -38,7 +39,8 @@ impl Game { Ok(Game { spritesheet: graphics::Image::new(context, "/ui.png").unwrap(), - runtime: iced::Runtime::new(), + cache: Some(iced::Cache::default()), + events: Vec::new(), tour: Tour::new(), }) } @@ -52,11 +54,11 @@ impl event::EventHandler for Game { fn mouse_button_down_event( &mut self, _context: &mut ggez::Context, - button: mouse::MouseButton, + _button: mouse::MouseButton, _x: f32, _y: f32, ) { - self.runtime.on_event(iced::Event::Mouse( + self.events.push(iced::Event::Mouse( iced::input::mouse::Event::Input { state: iced::input::ButtonState::Pressed, button: iced::input::mouse::Button::Left, // TODO: Map `button` @@ -67,11 +69,11 @@ impl event::EventHandler for Game { fn mouse_button_up_event( &mut self, _context: &mut ggez::Context, - button: mouse::MouseButton, + _button: mouse::MouseButton, _x: f32, _y: f32, ) { - self.runtime.on_event(iced::Event::Mouse( + self.events.push(iced::Event::Mouse( iced::input::mouse::Event::Input { state: iced::input::ButtonState::Released, button: iced::input::mouse::Button::Left, // TODO: Map `button` @@ -87,7 +89,7 @@ impl event::EventHandler for Game { _dx: f32, _dy: f32, ) { - self.runtime.on_event(iced::Event::Mouse( + self.events.push(iced::Event::Mouse( iced::input::mouse::Event::CursorMoved { x, y }, )); } @@ -130,11 +132,17 @@ impl event::EventHandler for Game { let renderer = &mut Renderer::new(context, self.spritesheet.clone()); - let mut ui = self.runtime.compute(content.into(), renderer); + let mut ui = iced::UserInterface::build( + content.into(), + renderer, + self.cache.take().unwrap(), + ); - let messages = ui.update(); + let messages = ui.update(self.events.drain(..)); let cursor = ui.draw(renderer); + self.cache = Some(ui.into_cache()); + renderer.flush(); (messages, cursor) @@ -15,8 +15,8 @@ mod node; mod point; mod rectangle; mod renderer; -mod runtime; mod style; +mod user_interface; mod vector; #[doc(no_inline)] @@ -31,7 +31,7 @@ pub use node::Node; pub use point::Point; pub use rectangle::Rectangle; pub use renderer::Renderer; -pub use runtime::{Interface, Runtime}; pub use style::{Align, Justify, Style}; +pub use user_interface::{Cache, UserInterface}; pub use vector::Vector; pub use widget::*; diff --git a/src/runtime.rs b/src/runtime.rs deleted file mode 100644 index 926e29ea..00000000 --- a/src/runtime.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::{input::mouse, Column, Element, Event, Layout, MouseCursor, Point}; - -use std::hash::Hasher; -use stretch::result; - -pub struct Runtime { - cache: Cache, - events: Vec<Event>, - cursor_position: Point, -} - -impl Runtime { - pub fn new() -> Runtime { - // We use this as a placeholder to initialize the cache. - // This way, we can avoid the overhead of using an `Option` - // in `compute`. - let root: Element<'_, (), ()> = Column::new().into(); - - let hasher = &mut crate::Hasher::default(); - root.hash(hasher); - - Runtime { - cache: Cache { - hash: hasher.finish(), - layout: root.compute_layout(&()), - }, - events: Vec::new(), - cursor_position: Point::new(0.0, 0.0), - } - } - - pub fn on_event(&mut self, event: Event) { - match event { - Event::Mouse(mouse::Event::CursorMoved { x, y }) => { - self.cursor_position = Point::new(x, y); - } - _ => {} - } - - self.events.push(event); - } - - pub fn compute<'a, Message, Renderer>( - &'a mut self, - root: Element<'a, Message, Renderer>, - renderer: &Renderer, - ) -> Interface<'a, Message, Renderer> { - let hasher = &mut crate::Hasher::default(); - root.hash(hasher); - - let hash = hasher.finish(); - - if hash != self.cache.hash { - self.cache = Cache { - hash, - layout: root.compute_layout(renderer), - }; - } - - Interface { - root, - layout: &self.cache.layout, - events: &mut self.events, - cursor_position: self.cursor_position, - } - } -} - -struct Cache { - hash: u64, - layout: result::Layout, -} - -pub struct Interface<'a, Message, Renderer> { - root: Element<'a, Message, Renderer>, - layout: &'a result::Layout, - events: &'a mut Vec<Event>, - cursor_position: Point, -} - -impl<'a, Message, Renderer> Interface<'a, Message, Renderer> { - pub fn update(&mut self) -> Vec<Message> { - let mut messages = Vec::new(); - - for event in self.events.drain(..) { - self.root.widget.on_event( - event, - Layout::new(&self.layout), - self.cursor_position, - &mut messages, - ); - } - - messages - } - - pub fn draw(&self, renderer: &mut Renderer) -> MouseCursor { - let cursor = self.root.widget.draw( - renderer, - Layout::new(self.layout), - self.cursor_position, - ); - - cursor - } -} diff --git a/src/user_interface.rs b/src/user_interface.rs new file mode 100644 index 00000000..5d02bf9a --- /dev/null +++ b/src/user_interface.rs @@ -0,0 +1,116 @@ +use crate::{input::mouse, Column, Element, Event, Layout, MouseCursor, Point}; + +use std::hash::Hasher; +use stretch::result; + +pub struct UserInterface<'a, Message, Renderer> { + hash: u64, + root: Element<'a, Message, Renderer>, + layout: result::Layout, + cursor_position: Point, +} + +impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { + pub fn build( + root: Element<'a, Message, Renderer>, + renderer: &Renderer, + cache: Cache, + ) -> Self { + let hasher = &mut crate::Hasher::default(); + root.hash(hasher); + + let hash = hasher.finish(); + + let layout = if hash == cache.hash { + cache.layout + } else { + root.compute_layout(renderer) + }; + + UserInterface { + hash, + root, + layout, + cursor_position: cache.cursor_position, + } + } + + pub fn update( + &mut self, + events: std::vec::Drain<'_, Event>, + ) -> Vec<Message> { + let mut messages = Vec::new(); + + for event in events { + match event { + Event::Mouse(mouse::Event::CursorMoved { x, y }) => { + self.cursor_position = Point::new(x, y); + } + _ => {} + } + + self.root.widget.on_event( + event, + Layout::new(&self.layout), + self.cursor_position, + &mut messages, + ); + } + + messages + } + + pub fn draw(&self, renderer: &mut Renderer) -> MouseCursor { + let cursor = self.root.widget.draw( + renderer, + Layout::new(&self.layout), + self.cursor_position, + ); + + cursor + } + + pub fn into_cache(self) -> Cache { + Cache { + hash: self.hash, + layout: self.layout, + cursor_position: self.cursor_position, + } + } +} + +#[derive(Debug, Clone)] +pub struct Cache { + hash: u64, + layout: result::Layout, + cursor_position: Point, +} + +impl Cache { + pub fn new() -> Cache { + let root: Element<'_, (), ()> = Column::new().into(); + + let hasher = &mut crate::Hasher::default(); + root.hash(hasher); + + Cache { + hash: hasher.finish(), + layout: root.compute_layout(&()), + cursor_position: Point::new(0.0, 0.0), + } + } +} + +impl Default for Cache { + fn default() -> Cache { + Cache::new() + } +} + +impl PartialEq for Cache { + fn eq(&self, other: &Cache) -> bool { + self.hash == other.hash && self.cursor_position == other.cursor_position + } +} + +impl Eq for Cache {} |