Write docs for iced_web
This commit is contained in:
parent
048909b45d
commit
fa227255b0
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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>,
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user