summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-22 22:14:04 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-22 22:14:04 +0100
commitfa227255b02adbbfa99801a7baaa4d6d387f7302 (patch)
tree1b9b4c97a6b6a054ff73cd69ac9b1493f50392c3
parent048909b45dfecef73bfacf3b5aa67462470ccca2 (diff)
downloadiced-fa227255b02adbbfa99801a7baaa4d6d387f7302.tar.gz
iced-fa227255b02adbbfa99801a7baaa4d6d387f7302.tar.bz2
iced-fa227255b02adbbfa99801a7baaa4d6d387f7302.zip
Write docs for `iced_web`
-rw-r--r--web/src/bus.rs15
-rw-r--r--web/src/element.rs48
-rw-r--r--web/src/lib.rs90
-rw-r--r--web/src/widget.rs27
-rw-r--r--web/src/widget/button.rs21
-rw-r--r--web/src/widget/checkbox.rs1
-rw-r--r--web/src/widget/column.rs1
-rw-r--r--web/src/widget/radio.rs1
-rw-r--r--web/src/widget/row.rs2
-rw-r--r--web/src/widget/slider.rs36
10 files changed, 225 insertions, 17 deletions
diff --git a/web/src/bus.rs b/web/src/bus.rs
index b4fd67c7..09908679 100644
--- a/web/src/bus.rs
+++ b/web/src/bus.rs
@@ -2,6 +2,12 @@ use crate::Instance;
use std::rc::Rc;
+/// A publisher of messages.
+///
+/// It can be used to route messages back to the [`Application`].
+///
+/// [`Application`]: trait.Application.html
+#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct Bus<Message> {
publish: Rc<Box<dyn Fn(Message, &mut dyn dodrio::RootRender)>>,
@@ -11,7 +17,7 @@ impl<Message> Bus<Message>
where
Message: 'static,
{
- pub fn new() -> Self {
+ pub(crate) fn new() -> Self {
Self {
publish: Rc::new(Box::new(|message, root| {
let app = root.unwrap_mut::<Instance<Message>>();
@@ -21,10 +27,17 @@ where
}
}
+ /// Publishes a new message for the [`Application`].
+ ///
+ /// [`Application`]: trait.Application.html
pub fn publish(&self, message: Message, root: &mut dyn dodrio::RootRender) {
(self.publish)(message, root);
}
+ /// Creates a new [`Bus`] that applies the given function to the messages
+ /// before publishing.
+ ///
+ /// [`Bus`]: struct.Bus.html
pub fn map<B>(&self, mapper: Rc<Box<dyn Fn(B) -> Message>>) -> Bus<B>
where
B: 'static,
diff --git a/web/src/element.rs b/web/src/element.rs
index a2b78c69..fcf0a4b6 100644
--- a/web/src/element.rs
+++ b/web/src/element.rs
@@ -3,29 +3,39 @@ use crate::{Bus, Color, Widget};
use dodrio::bumpalo;
use std::rc::Rc;
+/// A generic [`Widget`].
+///
+/// It is useful to build composable user interfaces that do not leak
+/// implementation details in their __view logic__.
+///
+/// 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
+/// [`Widget`]: widget/trait.Widget.html
+/// [`Element`]: struct.Element.html
+#[allow(missing_debug_implementations)]
pub struct Element<'a, Message> {
pub(crate) widget: Box<dyn Widget<Message> + 'a>,
}
impl<'a, Message> Element<'a, Message> {
+ /// Create a new [`Element`] containing the given [`Widget`].
+ ///
+ /// [`Element`]: struct.Element.html
+ /// [`Widget`]: widget/trait.Widget.html
pub fn new(widget: impl Widget<Message> + 'a) -> Self {
Self {
widget: Box::new(widget),
}
}
- pub fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- bus: &Bus<Message>,
- ) -> dodrio::Node<'b> {
- self.widget.node(bump, bus)
- }
-
- pub fn explain(self, _color: Color) -> Element<'a, Message> {
- self
- }
-
+ /// Applies a transformation to the produced message of the [`Element`].
+ ///
+ /// This method is useful when you want to decouple different parts of your
+ /// UI and make them __composable__.
+ ///
+ /// [`Element`]: struct.Element.html
pub fn map<F, B>(self, f: F) -> Element<'a, B>
where
Message: 'static,
@@ -36,6 +46,20 @@ impl<'a, Message> Element<'a, Message> {
widget: Box::new(Map::new(self.widget, f)),
}
}
+
+ /// Marks the [`Element`] as _to-be-explained_.
+ pub fn explain(self, _color: Color) -> Element<'a, Message> {
+ self
+ }
+
+ /// Produces a VDOM node for the [`Element`].
+ pub fn node<'b>(
+ &self,
+ bump: &'b bumpalo::Bump,
+ bus: &Bus<Message>,
+ ) -> dodrio::Node<'b> {
+ self.widget.node(bump, bus)
+ }
}
struct Map<'a, A, B> {
diff --git a/web/src/lib.rs b/web/src/lib.rs
index 00a85cf5..77a963ba 100644
--- a/web/src/lib.rs
+++ b/web/src/lib.rs
@@ -1,3 +1,61 @@
+//! A web runtime for Iced, targetting the DOM.
+//!
+//! ![`iced_web` crate graph](https://github.com/hecrj/iced/blob/cae26cb7bc627f4a5b3bcf1cd023a0c552e8c65e/docs/graphs/web.png?raw=true)
+//!
+//! `iced_web` takes [`iced_core`] and builds a WebAssembly runtime on top. It
+//! achieves this by introducing a `Widget` trait that can be used to produce
+//! VDOM nodes.
+//!
+//! The crate is currently a __very experimental__, simple abstraction layer
+//! over [`dodrio`].
+//!
+//! [`iced_core`]: https://github.com/hecrj/iced/tree/master/core
+//! [`dodrio`]: https://github.com/fitzgen/dodrio
+//!
+//! # Usage
+//! The current build process is a bit involved, as [`wasm-pack`] does not
+//! currently [support building binary crates](https://github.com/rustwasm/wasm-pack/issues/734).
+//!
+//! Therefore, we instead build using the `wasm32-unknown-unknown` target and
+//! use the [`wasm-bindgen`] CLI to generate appropriate bindings.
+//!
+//! For instance, let's say we want to build the [`tour` example]:
+//!
+//! ```bash
+//! cd examples
+//! cargo build --example tour --target wasm32-unknown-unknown
+//! wasm-bindgen ../target/wasm32-unknown-unknown/debug/examples/tour.wasm --out-dir tour --web
+//! ```
+//!
+//! Then, we need to create an `.html` file to load our application:
+//!
+//! ```html
+//! <!DOCTYPE html>
+//! <html>
+//! <head>
+//! <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
+//! <title>Tour - Iced</title>
+//! </head>
+//! <body>
+//! <script type="module">
+//! import init from "./tour/tour.js";
+//!
+//! init('./tour/tour_bg.wasm');
+//! </script>
+//! </body>
+//! </html>
+//! ```
+//!
+//! Finally, we serve it using an HTTP server and access it with our browser.
+//!
+//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack
+//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
+//! [`tour` example]: https://github.com/hecrj/iced/blob/master/examples/tour.rs
+#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
+#![deny(unused_results)]
+#![deny(unsafe_code)]
+#![deny(rust_2018_idioms)]
use dodrio::bumpalo;
use std::cell::RefCell;
@@ -6,6 +64,7 @@ mod element;
pub mod widget;
pub use bus::Bus;
+pub use dodrio;
pub use element::Element;
pub use iced_core::{
Align, Background, Color, Font, HorizontalAlignment, Length,
@@ -13,13 +72,42 @@ pub use iced_core::{
};
pub use widget::*;
+/// An interactive web application.
+///
+/// This trait is the main entrypoint of Iced. Once implemented, you can run
+/// your GUI application by simply calling [`run`](#method.run). It will take
+/// control of the `<title>` and the `<body>` of the document.
+///
+/// An [`Application`](trait.Application.html) can execute asynchronous actions
+/// by returning a [`Command`](struct.Command.html) in some of its methods.
pub trait Application {
+ /// The type of __messages__ your [`Application`] will produce.
+ ///
+ /// [`Application`]: trait.Application.html
type Message;
+ /// Handles a __message__ and updates the state of the [`Application`].
+ ///
+ /// This is where you define your __update logic__. All the __messages__,
+ /// produced by either user interactions or commands, will be handled by
+ /// this method.
+ ///
+ /// Any [`Command`] returned will be executed immediately in the background.
+ ///
+ /// [`Application`]: trait.Application.html
+ /// [`Command`]: struct.Command.html
fn update(&mut self, message: Self::Message);
- fn view(&mut self) -> Element<Self::Message>;
+ /// Returns the widgets to display in the [`Application`].
+ ///
+ /// These widgets can produce __messages__ based on user interaction.
+ ///
+ /// [`Application`]: trait.Application.html
+ fn view(&mut self) -> Element<'_, Self::Message>;
+ /// Runs the [`Application`].
+ ///
+ /// [`Application`]: trait.Application.html
fn run(self)
where
Self: 'static + Sized,
diff --git a/web/src/widget.rs b/web/src/widget.rs
index 88b2efc9..30ac8eeb 100644
--- a/web/src/widget.rs
+++ b/web/src/widget.rs
@@ -1,15 +1,31 @@
+//! Use the built-in widgets or create your own.
+//!
+//! # Custom widgets
+//! If you want to implement a custom widget, you simply need to implement the
+//! [`Widget`] trait. You can use the API of the built-in widgets as a guide or
+//! source of inspiration.
+//!
+//! # Re-exports
+//! For convenience, the contents of this module are available at the root
+//! module. Therefore, you can directly type:
+//!
+//! ```
+//! use iced_web::{button, Button, Widget};
+//! ```
+//!
+//! [`Widget`]: trait.Widget.html
use crate::Bus;
use dodrio::bumpalo;
pub mod button;
pub mod slider;
-pub mod text;
mod checkbox;
mod column;
mod image;
mod radio;
mod row;
+mod text;
#[doc(no_inline)]
pub use button::Button;
@@ -26,7 +42,16 @@ pub use image::Image;
pub use radio::Radio;
pub use row::Row;
+/// A component that displays information and allows interaction.
+///
+/// If you want to build your own widgets, you will need to implement this
+/// trait.
+///
+/// [`Widget`]: trait.Widget.html
pub trait Widget<Message> {
+ /// Produces a VDOM node for the [`Widget`].
+ ///
+ /// [`Widget`]: trait.Widget.html
fn node<'b>(
&self,
bump: &'b bumpalo::Bump,
diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs
index ddf67743..1c13f34d 100644
--- a/web/src/widget/button.rs
+++ b/web/src/widget/button.rs
@@ -1,8 +1,27 @@
+//! Allow your users to perform actions by pressing a button.
+//!
+//! A [`Button`] has some local [`State`].
+//!
+//! [`Button`]: struct.Button.html
+//! [`State`]: struct.State.html
use crate::{Background, Bus, Element, Length, Widget};
use dodrio::bumpalo;
-/// A generic widget that produces a message when clicked.
+/// A generic widget that produces a message when pressed.
+///
+/// ```
+/// # use iced_web::{button, Button, Text};
+/// #
+/// enum Message {
+/// ButtonPressed,
+/// }
+///
+/// let mut state = button::State::new();
+/// let button = Button::new(&mut state, Text::new("Press me!"))
+/// .on_press(Message::ButtonPressed);
+/// ```
+#[allow(missing_debug_implementations)]
pub struct Button<'a, Message> {
content: Element<'a, Message>,
on_press: Option<Message>,
diff --git a/web/src/widget/checkbox.rs b/web/src/widget/checkbox.rs
index 8bcef816..94b42554 100644
--- a/web/src/widget/checkbox.rs
+++ b/web/src/widget/checkbox.rs
@@ -19,6 +19,7 @@ use dodrio::bumpalo;
/// ```
///
/// ![Checkbox drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/checkbox.png?raw=true)
+#[allow(missing_debug_implementations)]
pub struct Checkbox<Message> {
is_checked: bool,
on_toggle: Box<dyn Fn(bool) -> Message>,
diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs
index cea50f6d..ee8c14fa 100644
--- a/web/src/widget/column.rs
+++ b/web/src/widget/column.rs
@@ -8,6 +8,7 @@ use std::u32;
/// A [`Column`] will try to fill the horizontal space of its container.
///
/// [`Column`]: struct.Column.html
+#[allow(missing_debug_implementations)]
pub struct Column<'a, Message> {
spacing: u16,
padding: u16,
diff --git a/web/src/widget/radio.rs b/web/src/widget/radio.rs
index a0b8fc43..32532ebe 100644
--- a/web/src/widget/radio.rs
+++ b/web/src/widget/radio.rs
@@ -27,6 +27,7 @@ use dodrio::bumpalo;
/// ```
///
/// ![Radio buttons drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/radio.png?raw=true)
+#[allow(missing_debug_implementations)]
pub struct Radio<Message> {
is_selected: bool,
on_click: Message,
diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs
index 44cacd50..b980d9b4 100644
--- a/web/src/widget/row.rs
+++ b/web/src/widget/row.rs
@@ -8,7 +8,7 @@ use std::u32;
/// A [`Row`] will try to fill the horizontal space of its container.
///
/// [`Row`]: struct.Row.html
-#[allow(missing_docs)]
+#[allow(missing_debug_implementations)]
pub struct Row<'a, Message> {
spacing: u16,
padding: u16,
diff --git a/web/src/widget/slider.rs b/web/src/widget/slider.rs
index acdef0a1..16e20b82 100644
--- a/web/src/widget/slider.rs
+++ b/web/src/widget/slider.rs
@@ -1,8 +1,37 @@
+//! Display an interactive selector of a single value from a range of values.
+//!
+//! A [`Slider`] has some local [`State`].
+//!
+//! [`Slider`]: struct.Slider.html
+//! [`State`]: struct.State.html
use crate::{Bus, Element, Length, Widget};
use dodrio::bumpalo;
use std::{ops::RangeInclusive, rc::Rc};
+/// An horizontal bar and a handle that selects a single value from a range of
+/// values.
+///
+/// A [`Slider`] will try to fill the horizontal space of its container.
+///
+/// [`Slider`]: struct.Slider.html
+///
+/// # Example
+/// ```
+/// # use iced_web::{slider, Slider};
+/// #
+/// pub enum Message {
+/// SliderChanged(f32),
+/// }
+///
+/// let state = &mut slider::State::new();
+/// let value = 50.0;
+///
+/// Slider::new(state, 0.0..=100.0, value, Message::SliderChanged);
+/// ```
+///
+/// ![Slider drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/slider.png?raw=true)
+#[allow(missing_debug_implementations)]
pub struct Slider<'a, Message> {
_state: &'a mut State,
range: RangeInclusive<f32>,
@@ -108,9 +137,16 @@ where
}
}
+/// The local state of a [`Slider`].
+///
+/// [`Slider`]: struct.Slider.html
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct State;
impl State {
+ /// Creates a new [`State`].
+ ///
+ /// [`State`]: struct.State.html
pub fn new() -> Self {
Self
}