summaryrefslogtreecommitdiffstats
path: root/src/user_interface.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/user_interface.rs')
-rw-r--r--src/user_interface.rs323
1 files changed, 0 insertions, 323 deletions
diff --git a/src/user_interface.rs b/src/user_interface.rs
deleted file mode 100644
index 2c7cbf82..00000000
--- a/src/user_interface.rs
+++ /dev/null
@@ -1,323 +0,0 @@
-use crate::{input::mouse, Column, Element, Event, Layout, MouseCursor, Point};
-
-use std::hash::Hasher;
-use stretch::result;
-
-/// A set of interactive graphical elements with a specific [`Layout`].
-///
-/// It can be updated and drawn.
-///
-/// Iced tries to avoid dictating how to write your event loop. You are in
-/// charge of using this type in your system in any way you want.
-///
-/// [`Layout`]: struct.Layout.html
-#[derive(Debug)]
-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> {
- /// Builds a user interface for an [`Element`].
- ///
- /// It is able to avoid expensive computations when using a [`Cache`]
- /// obtained from a previous instance of a [`UserInterface`].
- ///
- /// [`Element`]: struct.Element.html
- /// [`Cache`]: struct.Cache.html
- /// [`UserInterface`]: struct.UserInterface.html
- ///
- /// # Example
- /// Imagine we want to build a [`UserInterface`] for
- /// [the counter example that we previously wrote](index.html#usage). Here
- /// is naive way to set up our application loop:
- ///
- /// ```no_run
- /// use iced::{UserInterface, Cache};
- /// use iced_wgpu::Renderer;
- ///
- /// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// # }
- /// #
- /// # use iced::Column;
- /// #
- /// # pub struct Counter;
- /// #
- /// # impl Counter {
- /// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
- /// # }
- /// // Initialization
- /// let mut counter = Counter::new();
- /// let mut cache = Cache::new();
- /// let mut renderer = Renderer::new();
- ///
- /// // Application loop
- /// loop {
- /// // Process system events here...
- ///
- /// // Build the user interface
- /// let user_interface = UserInterface::build(
- /// counter.view(),
- /// cache,
- /// &renderer,
- /// );
- ///
- /// // Update and draw the user interface here...
- /// // ...
- ///
- /// // Obtain the cache for the next iteration
- /// cache = user_interface.into_cache();
- /// }
- /// ```
- pub fn build<E: Into<Element<'a, Message, Renderer>>>(
- root: E,
- cache: Cache,
- renderer: &Renderer,
- ) -> Self {
- let root = root.into();
-
- let hasher = &mut crate::Hasher::default();
- root.hash_layout(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,
- }
- }
-
- /// Updates the [`UserInterface`] by processing each provided [`Event`].
- ///
- /// It returns __messages__ that may have been produced as a result of user
- /// interactions. You should feed these to your __update logic__.
- ///
- /// [`UserInterface`]: struct.UserInterface.html
- /// [`Event`]: enum.Event.html
- ///
- /// # Example
- /// Let's allow our [counter](index.html#usage) to change state by completing
- /// [the previous example](#example):
- ///
- /// ```no_run
- /// use iced::{UserInterface, Cache};
- /// use iced_wgpu::Renderer;
- ///
- /// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// # }
- /// #
- /// # use iced::Column;
- /// #
- /// # pub struct Counter;
- /// #
- /// # impl Counter {
- /// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
- /// # pub fn update(&mut self, message: ()) {}
- /// # }
- /// let mut counter = Counter::new();
- /// let mut cache = Cache::new();
- /// let mut renderer = Renderer::new();
- ///
- /// // Initialize our event storage
- /// let mut events = Vec::new();
- ///
- /// loop {
- /// // Process system events...
- ///
- /// let mut user_interface = UserInterface::build(
- /// counter.view(),
- /// cache,
- /// &renderer,
- /// );
- ///
- /// // Update the user interface
- /// let messages = user_interface.update(events.drain(..));
- ///
- /// cache = user_interface.into_cache();
- ///
- /// // Process the produced messages
- /// for message in messages {
- /// counter.update(message);
- /// }
- /// }
- /// ```
- pub fn update(
- &mut self,
- events: impl Iterator<Item = Event>,
- ) -> Vec<Message> {
- let mut messages = Vec::new();
-
- for event in events {
- if let Event::Mouse(mouse::Event::CursorMoved { x, y }) = event {
- self.cursor_position = Point::new(x, y);
- }
-
- self.root.widget.on_event(
- event,
- Layout::new(&self.layout),
- self.cursor_position,
- &mut messages,
- );
- }
-
- messages
- }
-
- /// Draws the [`UserInterface`] with the provided [`Renderer`].
- ///
- /// It returns the current state of the [`MouseCursor`]. You should update
- /// the icon of the mouse cursor accordingly in your system.
- ///
- /// [`UserInterface`]: struct.UserInterface.html
- /// [`Renderer`]: trait.Renderer.html
- /// [`MouseCursor`]: enum.MouseCursor.html
- ///
- /// # Example
- /// We can finally draw our [counter](index.html#usage) by
- /// [completing the last example](#example-1):
- ///
- /// ```no_run
- /// use iced::{UserInterface, Cache};
- /// use iced_wgpu::Renderer;
- ///
- /// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// # }
- /// #
- /// # use iced::Column;
- /// #
- /// # pub struct Counter;
- /// #
- /// # impl Counter {
- /// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
- /// # pub fn update(&mut self, message: ()) {}
- /// # }
- /// let mut counter = Counter::new();
- /// let mut cache = Cache::new();
- /// let mut renderer = Renderer::new();
- /// let mut events = Vec::new();
- ///
- /// loop {
- /// // Process system events...
- ///
- /// let mut user_interface = UserInterface::build(
- /// counter.view(),
- /// cache,
- /// &renderer,
- /// );
- ///
- /// let messages = user_interface.update(events.drain(..));
- ///
- /// // Draw the user interface
- /// let mouse_cursor = user_interface.draw(&mut renderer);
- ///
- /// cache = user_interface.into_cache();
- ///
- /// for message in messages {
- /// counter.update(message);
- /// }
- ///
- /// // Update mouse cursor icon...
- /// // Flush rendering operations...
- /// }
- /// ```
- pub fn draw(&self, renderer: &mut Renderer) -> MouseCursor {
- self.root.widget.draw(
- renderer,
- Layout::new(&self.layout),
- self.cursor_position,
- )
- }
-
- /// Extract the [`Cache`] of the [`UserInterface`], consuming it in the
- /// process.
- ///
- /// [`Cache`]: struct.Cache.html
- /// [`UserInterface`]: struct.UserInterface.html
- pub fn into_cache(self) -> Cache {
- Cache {
- hash: self.hash,
- layout: self.layout,
- cursor_position: self.cursor_position,
- }
- }
-}
-
-/// Reusable data of a specific [`UserInterface`].
-///
-/// [`UserInterface`]: struct.UserInterface.html
-#[derive(Debug, Clone)]
-pub struct Cache {
- hash: u64,
- layout: result::Layout,
- cursor_position: Point,
-}
-
-impl Cache {
- /// Creates an empty [`Cache`].
- ///
- /// You should use this to initialize a [`Cache`] before building your first
- /// [`UserInterface`].
- ///
- /// [`Cache`]: struct.Cache.html
- /// [`UserInterface`]: struct.UserInterface.html
- pub fn new() -> Cache {
- let root: Element<'_, (), ()> = Column::new().into();
-
- let hasher = &mut crate::Hasher::default();
- root.hash_layout(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 {}