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;
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct Bus<Message> {
|
pub struct Bus<Message> {
|
||||||
publish: Rc<Box<dyn Fn(Message, &mut dyn dodrio::RootRender)>>,
|
publish: Rc<Box<dyn Fn(Message, &mut dyn dodrio::RootRender)>>,
|
||||||
@ -11,7 +17,7 @@ impl<Message> Bus<Message>
|
|||||||
where
|
where
|
||||||
Message: 'static,
|
Message: 'static,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
publish: Rc::new(Box::new(|message, root| {
|
publish: Rc::new(Box::new(|message, root| {
|
||||||
let app = root.unwrap_mut::<Instance<Message>>();
|
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) {
|
pub fn publish(&self, message: Message, root: &mut dyn dodrio::RootRender) {
|
||||||
(self.publish)(message, root);
|
(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>
|
pub fn map<B>(&self, mapper: Rc<Box<dyn Fn(B) -> Message>>) -> Bus<B>
|
||||||
where
|
where
|
||||||
B: 'static,
|
B: 'static,
|
||||||
|
@ -3,29 +3,39 @@ use crate::{Bus, Color, Widget};
|
|||||||
use dodrio::bumpalo;
|
use dodrio::bumpalo;
|
||||||
use std::rc::Rc;
|
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 struct Element<'a, Message> {
|
||||||
pub(crate) widget: Box<dyn Widget<Message> + 'a>,
|
pub(crate) widget: Box<dyn Widget<Message> + 'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message> Element<'a, Message> {
|
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 {
|
pub fn new(widget: impl Widget<Message> + 'a) -> Self {
|
||||||
Self {
|
Self {
|
||||||
widget: Box::new(widget),
|
widget: Box::new(widget),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node<'b>(
|
/// Applies a transformation to the produced message of the [`Element`].
|
||||||
&self,
|
///
|
||||||
bump: &'b bumpalo::Bump,
|
/// This method is useful when you want to decouple different parts of your
|
||||||
bus: &Bus<Message>,
|
/// UI and make them __composable__.
|
||||||
) -> dodrio::Node<'b> {
|
///
|
||||||
self.widget.node(bump, bus)
|
/// [`Element`]: struct.Element.html
|
||||||
}
|
|
||||||
|
|
||||||
pub fn explain(self, _color: Color) -> Element<'a, Message> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map<F, B>(self, f: F) -> Element<'a, B>
|
pub fn map<F, B>(self, f: F) -> Element<'a, B>
|
||||||
where
|
where
|
||||||
Message: 'static,
|
Message: 'static,
|
||||||
@ -36,6 +46,20 @@ impl<'a, Message> Element<'a, Message> {
|
|||||||
widget: Box::new(Map::new(self.widget, f)),
|
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> {
|
struct Map<'a, A, B> {
|
||||||
|
@ -1,3 +1,61 @@
|
|||||||
|
//! A web runtime for Iced, targetting the DOM.
|
||||||
|
//!
|
||||||
|
//! 
|
||||||
|
//!
|
||||||
|
//! `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 dodrio::bumpalo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
@ -6,6 +64,7 @@ mod element;
|
|||||||
pub mod widget;
|
pub mod widget;
|
||||||
|
|
||||||
pub use bus::Bus;
|
pub use bus::Bus;
|
||||||
|
pub use dodrio;
|
||||||
pub use element::Element;
|
pub use element::Element;
|
||||||
pub use iced_core::{
|
pub use iced_core::{
|
||||||
Align, Background, Color, Font, HorizontalAlignment, Length,
|
Align, Background, Color, Font, HorizontalAlignment, Length,
|
||||||
@ -13,13 +72,42 @@ pub use iced_core::{
|
|||||||
};
|
};
|
||||||
pub use widget::*;
|
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 {
|
pub trait Application {
|
||||||
|
/// The type of __messages__ your [`Application`] will produce.
|
||||||
|
///
|
||||||
|
/// [`Application`]: trait.Application.html
|
||||||
type Message;
|
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 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)
|
fn run(self)
|
||||||
where
|
where
|
||||||
Self: 'static + Sized,
|
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 crate::Bus;
|
||||||
use dodrio::bumpalo;
|
use dodrio::bumpalo;
|
||||||
|
|
||||||
pub mod button;
|
pub mod button;
|
||||||
pub mod slider;
|
pub mod slider;
|
||||||
pub mod text;
|
|
||||||
|
|
||||||
mod checkbox;
|
mod checkbox;
|
||||||
mod column;
|
mod column;
|
||||||
mod image;
|
mod image;
|
||||||
mod radio;
|
mod radio;
|
||||||
mod row;
|
mod row;
|
||||||
|
mod text;
|
||||||
|
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use button::Button;
|
pub use button::Button;
|
||||||
@ -26,7 +42,16 @@ pub use image::Image;
|
|||||||
pub use radio::Radio;
|
pub use radio::Radio;
|
||||||
pub use row::Row;
|
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> {
|
pub trait Widget<Message> {
|
||||||
|
/// Produces a VDOM node for the [`Widget`].
|
||||||
|
///
|
||||||
|
/// [`Widget`]: trait.Widget.html
|
||||||
fn node<'b>(
|
fn node<'b>(
|
||||||
&self,
|
&self,
|
||||||
bump: &'b bumpalo::Bump,
|
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 crate::{Background, Bus, Element, Length, Widget};
|
||||||
|
|
||||||
use dodrio::bumpalo;
|
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> {
|
pub struct Button<'a, Message> {
|
||||||
content: Element<'a, Message>,
|
content: Element<'a, Message>,
|
||||||
on_press: Option<Message>,
|
on_press: Option<Message>,
|
||||||
|
@ -19,6 +19,7 @@ use dodrio::bumpalo;
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// 
|
/// 
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Checkbox<Message> {
|
pub struct Checkbox<Message> {
|
||||||
is_checked: bool,
|
is_checked: bool,
|
||||||
on_toggle: Box<dyn Fn(bool) -> Message>,
|
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.
|
/// A [`Column`] will try to fill the horizontal space of its container.
|
||||||
///
|
///
|
||||||
/// [`Column`]: struct.Column.html
|
/// [`Column`]: struct.Column.html
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Column<'a, Message> {
|
pub struct Column<'a, Message> {
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
padding: u16,
|
padding: u16,
|
||||||
|
@ -27,6 +27,7 @@ use dodrio::bumpalo;
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// 
|
/// 
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Radio<Message> {
|
pub struct Radio<Message> {
|
||||||
is_selected: bool,
|
is_selected: bool,
|
||||||
on_click: Message,
|
on_click: Message,
|
||||||
|
@ -8,7 +8,7 @@ use std::u32;
|
|||||||
/// A [`Row`] will try to fill the horizontal space of its container.
|
/// A [`Row`] will try to fill the horizontal space of its container.
|
||||||
///
|
///
|
||||||
/// [`Row`]: struct.Row.html
|
/// [`Row`]: struct.Row.html
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Row<'a, Message> {
|
pub struct Row<'a, Message> {
|
||||||
spacing: u16,
|
spacing: u16,
|
||||||
padding: 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 crate::{Bus, Element, Length, Widget};
|
||||||
|
|
||||||
use dodrio::bumpalo;
|
use dodrio::bumpalo;
|
||||||
use std::{ops::RangeInclusive, rc::Rc};
|
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);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Slider<'a, Message> {
|
pub struct Slider<'a, Message> {
|
||||||
_state: &'a mut State,
|
_state: &'a mut State,
|
||||||
range: RangeInclusive<f32>,
|
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;
|
pub struct State;
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
/// Creates a new [`State`].
|
||||||
|
///
|
||||||
|
/// [`State`]: struct.State.html
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self
|
Self
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user