diff options
author | 2019-08-29 00:58:42 +0200 | |
---|---|---|
committer | 2019-08-29 00:58:42 +0200 | |
commit | 268a5f00171820ff1d3da7de03b5efab5e45c01d (patch) | |
tree | dec80ca85cd0edad458ab7bd24913f6a408a60e5 /src | |
parent | 51050fc45ce0e84e40ab801deefe35baf4ee3c2c (diff) | |
download | iced-268a5f00171820ff1d3da7de03b5efab5e45c01d.tar.gz iced-268a5f00171820ff1d3da7de03b5efab5e45c01d.tar.bz2 iced-268a5f00171820ff1d3da7de03b5efab5e45c01d.zip |
Write documentation for `UserInterface`
Diffstat (limited to 'src')
-rw-r--r-- | src/element.rs | 10 | ||||
-rw-r--r-- | src/layout.rs | 2 | ||||
-rw-r--r-- | src/user_interface.rs | 208 | ||||
-rw-r--r-- | src/widget.rs | 4 |
4 files changed, 212 insertions, 12 deletions
diff --git a/src/element.rs b/src/element.rs index 6bc0ad74..ca9d420b 100644 --- a/src/element.rs +++ b/src/element.rs @@ -4,10 +4,14 @@ use crate::{Event, Hasher, Layout, MouseCursor, Node, Point, Widget}; /// A generic [`Widget`]. /// -/// If you have a widget, you should be able to use `widget.into()` to turn it -/// into an [`Element`]. +/// It is useful to build composable user interfaces that do not leak +/// implementation details in their __view logic__. /// -/// [`Widget`]: trait.Widget.html +/// If you have a [built-in widget], you should be able to use `Into<Element>` +/// to turn it into an [`Element`]. +/// +/// [built-in widget]: widget/index.html#built-in-widgets +/// [`Widget`]: widget/trait.Widget.html /// [`Element`]: struct.Element.html pub struct Element<'a, Message, Renderer> { pub(crate) widget: Box<dyn Widget<Message, Renderer> + 'a>, diff --git a/src/layout.rs b/src/layout.rs index 481b4166..78c7f947 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -5,7 +5,7 @@ use crate::{Point, Rectangle, Vector}; /// The computed bounds of a [`Node`] and its children. /// /// This type is provided by the GUI runtime to [`Widget::on_event`] and -/// [`Widget::draw`], describing the layout of the produced [`Node`] by +/// [`Widget::draw`], describing the layout of the [`Node`] produced by /// [`Widget::node`]. /// /// [`Node`]: struct.Node.html diff --git a/src/user_interface.rs b/src/user_interface.rs index cb8d05ae..f64fe74b 100644 --- a/src/user_interface.rs +++ b/src/user_interface.rs @@ -3,7 +3,14 @@ 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. +/// A set of interactive graphical elements with a specific [`Layout`]. +/// +/// Use this to build, update, and draw your GUI! +/// +/// Iced tries to avoid dictating how to write your event loop. You are in +/// charge of integrating Iced in your system in any way you want. +/// +/// [`Layout`]: struct.Layout.html pub struct UserInterface<'a, Message, Renderer> { hash: u64, root: Element<'a, Message, Renderer>, @@ -12,11 +19,72 @@ pub struct UserInterface<'a, Message, Renderer> { } impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { - pub fn build( - root: Element<'a, Message, Renderer>, - renderer: &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 how we could build our GUI application indefinitely: + /// + /// ```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(hasher); @@ -36,6 +104,68 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { } } + /// 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>, @@ -61,6 +191,71 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { 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 { let cursor = self.root.widget.draw( renderer, @@ -71,6 +266,11 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { cursor } + /// 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, diff --git a/src/widget.rs b/src/widget.rs index cd3ff7a2..ef5bd7b5 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -44,10 +44,6 @@ use crate::{Event, Hasher, Layout, MouseCursor, Node, Point}; /// If you want to build your own widgets, you will need to implement this /// trait. /// -/// Additionally, remember to also provide [`Into<Element>`] so your users can -/// easily turn your [`Widget`] into a generic [`Element`]. -/// -/// [`Into<Element>`]: ../struct.Element.html /// [`Widget`]: trait.Widget.html /// [`Element`]: ../struct.Element.html pub trait Widget<Message, Renderer>: std::fmt::Debug { |