summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/Cargo.toml13
-rw-r--r--web/README.md4
-rw-r--r--web/src/bus.rs6
-rw-r--r--web/src/css.rs29
-rw-r--r--web/src/element.rs9
-rw-r--r--web/src/lib.rs52
-rw-r--r--web/src/subscription.rs3
-rw-r--r--web/src/widget.rs6
-rw-r--r--web/src/widget/button.rs38
-rw-r--r--web/src/widget/checkbox.rs33
-rw-r--r--web/src/widget/column.rs20
-rw-r--r--web/src/widget/container.rs18
-rw-r--r--web/src/widget/image.rs41
-rw-r--r--web/src/widget/progress_bar.rs8
-rw-r--r--web/src/widget/radio.rs46
-rw-r--r--web/src/widget/row.rs21
-rw-r--r--web/src/widget/scrollable.rs23
-rw-r--r--web/src/widget/slider.rs82
-rw-r--r--web/src/widget/space.rs6
-rw-r--r--web/src/widget/text.rs30
-rw-r--r--web/src/widget/text_input.rs80
21 files changed, 207 insertions, 361 deletions
diff --git a/web/Cargo.toml b/web/Cargo.toml
index 12d3865e..e063a021 100644
--- a/web/Cargo.toml
+++ b/web/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_web"
-version = "0.2.1"
+version = "0.3.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2018"
description = "A web backend for Iced"
@@ -15,21 +15,22 @@ categories = ["web-programming"]
maintenance = { status = "actively-developed" }
[dependencies]
-dodrio = "0.1.0"
-wasm-bindgen = "0.2.51"
+dodrio = "0.2"
+wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
url = "2.0"
+num-traits = "0.2"
[dependencies.iced_core]
-version = "0.2"
+version = "0.3"
path = "../core"
[dependencies.iced_futures]
-version = "0.1"
+version = "0.2"
path = "../futures"
[dependencies.iced_style]
-version = "0.1"
+version = "0.2"
path = "../style"
[dependencies.web-sys]
diff --git a/web/README.md b/web/README.md
index 810bd1ec..0e770589 100644
--- a/web/README.md
+++ b/web/README.md
@@ -8,8 +8,6 @@
The crate is currently a __very experimental__, simple abstraction layer over [`dodrio`].
-![iced_core](../docs/graphs/web.png)
-
[documentation]: https://docs.rs/iced_web
[`iced_core`]: ../core
[`dodrio`]: https://github.com/fitzgen/dodrio
@@ -18,7 +16,7 @@ The crate is currently a __very experimental__, simple abstraction layer over [`
Add `iced_web` as a dependency in your `Cargo.toml`:
```toml
-iced_web = "0.2"
+iced_web = "0.3"
```
__Iced moves fast and the `master` branch can contain breaking changes!__ If
diff --git a/web/src/bus.rs b/web/src/bus.rs
index c66e9659..5ce8e810 100644
--- a/web/src/bus.rs
+++ b/web/src/bus.rs
@@ -5,7 +5,7 @@ use std::rc::Rc;
///
/// It can be used to route messages back to the [`Application`].
///
-/// [`Application`]: trait.Application.html
+/// [`Application`]: crate::Application
#[allow(missing_debug_implementations)]
pub struct Bus<Message> {
publish: Rc<Box<dyn Fn(Message) -> ()>>,
@@ -33,15 +33,13 @@ where
/// Publishes a new message for the [`Application`].
///
- /// [`Application`]: trait.Application.html
+ /// [`Application`]: crate::Application
pub fn publish(&self, message: Message) {
(self.publish)(message)
}
/// 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/css.rs b/web/src/css.rs
index 6a307770..bdde23f3 100644
--- a/web/src/css.rs
+++ b/web/src/css.rs
@@ -20,9 +20,7 @@ pub enum Rule {
}
impl Rule {
- /// Returns the class name of the [`Style`].
- ///
- /// [`Style`]: enum.Style.html
+ /// Returns the class name of the [`Rule`].
pub fn class<'a>(&self) -> String {
match self {
Rule::Column => String::from("c"),
@@ -32,9 +30,7 @@ impl Rule {
}
}
- /// Returns the declaration of the [`Style`].
- ///
- /// [`Style`]: enum.Style.html
+ /// Returns the declaration of the [`Rule`].
pub fn declaration<'a>(&self, bump: &'a bumpalo::Bump) -> &'a str {
let class = self.class();
@@ -81,22 +77,17 @@ pub struct Css<'a> {
}
impl<'a> Css<'a> {
- /// Creates an empty style [`Sheet`].
- ///
- /// [`Sheet`]: struct.Sheet.html
+ /// Creates an empty [`Css`].
pub fn new() -> Self {
Css {
rules: BTreeMap::new(),
}
}
- /// Inserts the [`rule`] in the [`Sheet`], if it was not previously
+ /// Inserts the [`Rule`] in the [`Css`], if it was not previously
/// inserted.
///
/// It returns the class name of the provided [`Rule`].
- ///
- /// [`Sheet`]: struct.Sheet.html
- /// [`Rule`]: enum.Rule.html
pub fn insert(&mut self, bump: &'a bumpalo::Bump, rule: Rule) -> String {
let class = rule.class();
@@ -107,9 +98,7 @@ impl<'a> Css<'a> {
class
}
- /// Produces the VDOM node of the style [`Sheet`].
- ///
- /// [`Sheet`]: struct.Sheet.html
+ /// Produces the VDOM node of the [`Css`].
pub fn node(self, bump: &'a bumpalo::Bump) -> dodrio::Node<'a> {
use dodrio::builder::*;
@@ -133,8 +122,6 @@ impl<'a> Css<'a> {
}
/// Returns the style value for the given [`Length`].
-///
-/// [`Length`]: ../enum.Length.html
pub fn length(length: Length) -> String {
match length {
Length::Shrink => String::from("auto"),
@@ -164,15 +151,11 @@ pub fn min_length(units: u32) -> String {
}
/// Returns the style value for the given [`Color`].
-///
-/// [`Color`]: ../struct.Color.html
pub fn color(Color { r, g, b, a }: Color) -> String {
format!("rgba({}, {}, {}, {})", 255.0 * r, 255.0 * g, 255.0 * b, a)
}
/// Returns the style value for the given [`Background`].
-///
-/// [`Background`]: ../struct.Background.html
pub fn background(background: Background) -> String {
match background {
Background::Color(c) => color(c),
@@ -180,8 +163,6 @@ pub fn background(background: Background) -> String {
}
/// Returns the style value for the given [`Align`].
-///
-/// [`Align`]: ../enum.Align.html
pub fn align(align: Align) -> &'static str {
match align {
Align::Start => "flex-start",
diff --git a/web/src/element.rs b/web/src/element.rs
index 93e73713..6bb90177 100644
--- a/web/src/element.rs
+++ b/web/src/element.rs
@@ -11,9 +11,7 @@ use std::rc::Rc;
/// 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
+/// [built-in widget]: mod@crate::widget
#[allow(missing_debug_implementations)]
pub struct Element<'a, Message> {
pub(crate) widget: Box<dyn Widget<Message> + 'a>,
@@ -21,9 +19,6 @@ pub struct 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 {
Self {
widget: Box::new(widget),
@@ -34,8 +29,6 @@ impl<'a, Message> Element<'a, Message> {
///
/// 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,
diff --git a/web/src/lib.rs b/web/src/lib.rs
index 53b54b7e..58f6591d 100644
--- a/web/src/lib.rs
+++ b/web/src/lib.rs
@@ -1,7 +1,5 @@
//! 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.
@@ -51,7 +49,7 @@
//!
//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack
//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
-//! [`tour` example]: https://github.com/hecrj/iced/tree/0.1/examples/tour
+//! [`tour` example]: https://github.com/hecrj/iced/tree/0.2/examples/tour
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
@@ -96,33 +94,21 @@ pub use executor::Executor;
/// by returning a [`Command`](struct.Command.html) in some of its methods.
pub trait Application {
/// The [`Executor`] that will run commands and subscriptions.
- ///
- /// The [`executor::WasmBindgen`] can be a good choice for the Web.
- ///
- /// [`Executor`]: trait.Executor.html
- /// [`executor::Default`]: executor/struct.Default.html
type Executor: Executor;
/// The type of __messages__ your [`Application`] will produce.
- ///
- /// [`Application`]: trait.Application.html
type Message: Send;
/// The data needed to initialize your [`Application`].
- ///
- /// [`Application`]: trait.Application.html
type Flags;
/// Initializes the [`Application`].
///
/// Here is where you should return the initial state of your app.
///
- /// Additionally, you can return a [`Command`](struct.Command.html) if you
- /// need to perform some async action in the background on startup. This is
- /// useful if you want to load state from a file, perform an initial HTTP
- /// request, etc.
- ///
- /// [`Application`]: trait.Application.html
+ /// Additionally, you can return a [`Command`] if you need to perform some
+ /// async action in the background on startup. This is useful if you want to
+ /// load state from a file, perform an initial HTTP request, etc.
fn new(flags: Self::Flags) -> (Self, Command<Self::Message>)
where
Self: Sized;
@@ -131,8 +117,6 @@ pub trait Application {
///
/// This title can be dynamic! The runtime will automatically update the
/// title of your application when necessary.
- ///
- /// [`Application`]: trait.Application.html
fn title(&self) -> String;
/// Handles a __message__ and updates the state of the [`Application`].
@@ -142,16 +126,11 @@ pub trait Application {
/// 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) -> Command<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>;
/// Returns the event [`Subscription`] for the current state of the
@@ -162,15 +141,11 @@ pub trait Application {
/// [`update`](#tymethod.update).
///
/// By default, this method returns an empty [`Subscription`].
- ///
- /// [`Subscription`]: struct.Subscription.html
fn subscription(&self) -> Subscription<Self::Message> {
Subscription::none()
}
/// Runs the [`Application`].
- ///
- /// [`Application`]: trait.Application.html
fn run(flags: Self::Flags)
where
Self: 'static + Sized,
@@ -238,28 +213,25 @@ struct Instance<A: Application> {
bus: Bus<A::Message>,
}
-impl<A> dodrio::Render for Instance<A>
+impl<'a, A> dodrio::Render<'a> for Instance<A>
where
A: Application,
{
- fn render<'a, 'bump>(
- &'a self,
- bump: &'bump bumpalo::Bump,
- ) -> dodrio::Node<'bump>
- where
- 'a: 'bump,
- {
+ fn render(
+ &self,
+ context: &mut dodrio::RenderContext<'a>,
+ ) -> dodrio::Node<'a> {
use dodrio::builder::*;
let mut ui = self.application.borrow_mut();
let element = ui.view();
let mut css = Css::new();
- let node = element.widget.node(bump, &self.bus, &mut css);
+ let node = element.widget.node(context.bump, &self.bus, &mut css);
- div(bump)
+ div(context.bump)
.attr("style", "width: 100%; height: 100%")
- .children(vec![css.node(bump), node])
+ .children(vec![css.node(context.bump), node])
.finish()
}
}
diff --git a/web/src/subscription.rs b/web/src/subscription.rs
index 6b8415c0..fb54f7e3 100644
--- a/web/src/subscription.rs
+++ b/web/src/subscription.rs
@@ -12,8 +12,7 @@ use crate::Hasher;
/// For instance, you can use a [`Subscription`] to listen to a WebSocket
/// connection, keyboard presses, mouse events, time ticks, etc.
///
-/// [`Command`]: ../struct.Command.html
-/// [`Subscription`]: struct.Subscription.html
+/// [`Command`]: crate::Command
pub type Subscription<T> = iced_futures::Subscription<Hasher, (), T>;
pub use iced_futures::subscription::Recipe;
diff --git a/web/src/widget.rs b/web/src/widget.rs
index 025cf22f..023f5f13 100644
--- a/web/src/widget.rs
+++ b/web/src/widget.rs
@@ -12,8 +12,6 @@
//! ```
//! use iced_web::{button, Button, Widget};
//! ```
-//!
-//! [`Widget`]: trait.Widget.html
use crate::{Bus, Css};
use dodrio::bumpalo;
@@ -56,12 +54,8 @@ pub use space::Space;
///
/// 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 3a5afe60..e7cff6a0 100644
--- a/web/src/widget/button.rs
+++ b/web/src/widget/button.rs
@@ -1,9 +1,6 @@
//! 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::{css, Background, Bus, Css, Element, Length, Widget};
pub use iced_style::button::{Style, StyleSheet};
@@ -38,9 +35,6 @@ pub struct Button<'a, Message> {
impl<'a, Message> Button<'a, Message> {
/// Creates a new [`Button`] with some local [`State`] and the given
/// content.
- ///
- /// [`Button`]: struct.Button.html
- /// [`State`]: struct.State.html
pub fn new<E>(_state: &'a mut State, content: E) -> Self
where
E: Into<Element<'a, Message>>,
@@ -58,56 +52,42 @@ impl<'a, Message> Button<'a, Message> {
}
/// Sets the width of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the minimum width of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn min_width(mut self, min_width: u32) -> Self {
self.min_width = min_width;
self
}
/// Sets the minimum height of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn min_height(mut self, min_height: u32) -> Self {
self.min_height = min_height;
self
}
/// Sets the padding of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn padding(mut self, padding: u16) -> Self {
self.padding = padding;
self
}
/// Sets the style of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
}
/// Sets the message that will be produced when the [`Button`] is pressed.
- ///
- /// [`Button`]: struct.Button.html
pub fn on_press(mut self, msg: Message) -> Self {
self.on_press = Some(msg);
self
@@ -115,15 +95,11 @@ impl<'a, Message> Button<'a, Message> {
}
/// The local state of a [`Button`].
-///
-/// [`Button`]: struct.Button.html
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct State;
impl State {
/// Creates a new [`State`].
- ///
- /// [`State`]: struct.State.html
pub fn new() -> State {
State::default()
}
@@ -154,16 +130,20 @@ where
},
};
+ let class = {
+ use dodrio::bumpalo::collections::String;
+
+ String::from_str_in(&padding_class, bump).into_bump_str()
+ };
+
let mut node = button(bump)
- .attr(
- "class",
- bumpalo::format!(in bump, "{}", padding_class).into_bump_str(),
- )
+ .attr("class", class)
.attr(
"style",
bumpalo::format!(
in bump,
- "background: {}; border-radius: {}px; width:{}; min-width: {}; color: {}",
+ "background: {}; border-radius: {}px; width:{}; \
+ min-width: {}; color: {}",
background,
style.border_radius,
css::length(self.width),
diff --git a/web/src/widget/checkbox.rs b/web/src/widget/checkbox.rs
index 5ebc26c8..543af99a 100644
--- a/web/src/widget/checkbox.rs
+++ b/web/src/widget/checkbox.rs
@@ -28,6 +28,7 @@ pub struct Checkbox<Message> {
is_checked: bool,
on_toggle: Rc<dyn Fn(bool) -> Message>,
label: String,
+ id: Option<String>,
width: Length,
style: Box<dyn StyleSheet>,
}
@@ -41,8 +42,6 @@ impl<Message> Checkbox<Message> {
/// * a function that will be called when the [`Checkbox`] is toggled. It
/// will receive the new state of the [`Checkbox`] and must produce a
/// `Message`.
- ///
- /// [`Checkbox`]: struct.Checkbox.html
pub fn new<F>(is_checked: bool, label: impl Into<String>, f: F) -> Self
where
F: 'static + Fn(bool) -> Message,
@@ -51,26 +50,29 @@ impl<Message> Checkbox<Message> {
is_checked,
on_toggle: Rc::new(f),
label: label.into(),
+ id: None,
width: Length::Shrink,
style: Default::default(),
}
}
/// Sets the width of the [`Checkbox`].
- ///
- /// [`Checkbox`]: struct.Checkbox.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the style of the [`Checkbox`].
- ///
- /// [`Checkbox`]: struct.Checkbox.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
}
+
+ /// Sets the id of the [`Checkbox`].
+ pub fn id(mut self, id: impl Into<String>) -> Self {
+ self.id = Some(id.into());
+ self
+ }
}
impl<Message> Widget<Message> for Checkbox<Message>
@@ -84,8 +86,10 @@ where
style_sheet: &mut Css<'b>,
) -> dodrio::Node<'b> {
use dodrio::builder::*;
+ use dodrio::bumpalo::collections::String;
- let checkbox_label = bumpalo::format!(in bump, "{}", self.label);
+ let checkbox_label =
+ String::from_str_in(&self.label, bump).into_bump_str();
let event_bus = bus.clone();
let on_toggle = self.on_toggle.clone();
@@ -95,7 +99,15 @@ where
let spacing_class = style_sheet.insert(bump, css::Rule::Spacing(5));
- label(bump)
+ let (label, input) = if let Some(id) = &self.id {
+ let id = String::from_str_in(id, bump).into_bump_str();
+
+ (label(bump).attr("for", id), input(bump).attr("id", id))
+ } else {
+ (label(bump), input(bump))
+ };
+
+ label
.attr(
"class",
bumpalo::format!(in bump, "{} {}", row_class, spacing_class)
@@ -108,7 +120,7 @@ where
)
.children(vec![
// TODO: Checkbox styling
- input(bump)
+ input
.attr("type", "checkbox")
.bool_attr("checked", self.is_checked)
.on("click", move |_root, vdom, _event| {
@@ -118,8 +130,7 @@ where
vdom.schedule_render();
})
.finish(),
- span(bump).children(vec![
- text(checkbox_label.into_bump_str())]).finish(),
+ text(checkbox_label),
])
.finish()
}
diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs
index 25b88b0e..d832fdcb 100644
--- a/web/src/widget/column.rs
+++ b/web/src/widget/column.rs
@@ -6,8 +6,6 @@ use std::u32;
/// A container that distributes its contents vertically.
///
/// 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,
@@ -22,15 +20,11 @@ pub struct Column<'a, Message> {
impl<'a, Message> Column<'a, Message> {
/// Creates an empty [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn new() -> Self {
Self::with_children(Vec::new())
}
/// Creates a [`Column`] with the given elements.
- ///
- /// [`Column`]: struct.Column.html
pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
Column {
spacing: 0,
@@ -55,56 +49,42 @@ impl<'a, Message> Column<'a, Message> {
}
/// Sets the padding of the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn padding(mut self, units: u16) -> Self {
self.padding = units;
self
}
/// Sets the width of the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the maximum width of the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn max_width(mut self, max_width: u32) -> Self {
self.max_width = max_width;
self
}
/// Sets the maximum height of the [`Column`] in pixels.
- ///
- /// [`Column`]: struct.Column.html
pub fn max_height(mut self, max_height: u32) -> Self {
self.max_height = max_height;
self
}
/// Sets the horizontal alignment of the contents of the [`Column`] .
- ///
- /// [`Column`]: struct.Column.html
pub fn align_items(mut self, align: Align) -> Self {
self.align_items = align;
self
}
/// Adds an element to the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
pub fn push<E>(mut self, child: E) -> Self
where
E: Into<Element<'a, Message>>,
diff --git a/web/src/widget/container.rs b/web/src/widget/container.rs
index 78be3543..7187a4f0 100644
--- a/web/src/widget/container.rs
+++ b/web/src/widget/container.rs
@@ -21,8 +21,6 @@ pub struct Container<'a, Message> {
impl<'a, Message> Container<'a, Message> {
/// Creates an empty [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn new<T>(content: T) -> Self
where
T: Into<Element<'a, Message>>,
@@ -43,48 +41,36 @@ impl<'a, Message> Container<'a, Message> {
}
/// Sets the padding of the [`Container`].
- ///
- /// [`Container`]: struct.Column.html
pub fn padding(mut self, units: u16) -> Self {
self.padding = units;
self
}
/// Sets the width of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the maximum width of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn max_width(mut self, max_width: u32) -> Self {
self.max_width = max_width;
self
}
/// Sets the maximum height of the [`Container`] in pixels.
- ///
- /// [`Container`]: struct.Container.html
pub fn max_height(mut self, max_height: u32) -> Self {
self.max_height = max_height;
self
}
/// Centers the contents in the horizontal axis of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn center_x(mut self) -> Self {
self.horizontal_alignment = Align::Center;
@@ -92,8 +78,6 @@ impl<'a, Message> Container<'a, Message> {
}
/// Centers the contents in the vertical axis of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn center_y(mut self) -> Self {
self.vertical_alignment = Align::Center;
@@ -101,8 +85,6 @@ impl<'a, Message> Container<'a, Message> {
}
/// Sets the style of the [`Container`].
- ///
- /// [`Container`]: struct.Container.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style_sheet = style.into();
self
diff --git a/web/src/widget/image.rs b/web/src/widget/image.rs
index 029ab352..05c89ea5 100644
--- a/web/src/widget/image.rs
+++ b/web/src/widget/image.rs
@@ -22,6 +22,9 @@ pub struct Image {
/// The image path
pub handle: Handle,
+ /// The alt text of the image
+ pub alt: String,
+
/// The width of the image
pub width: Length,
@@ -31,31 +34,32 @@ pub struct Image {
impl Image {
/// Creates a new [`Image`] with the given path.
- ///
- /// [`Image`]: struct.Image.html
pub fn new<T: Into<Handle>>(handle: T) -> Self {
Image {
handle: handle.into(),
+ alt: Default::default(),
width: Length::Shrink,
height: Length::Shrink,
}
}
/// Sets the width of the [`Image`] boundaries.
- ///
- /// [`Image`]: struct.Image.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Image`] boundaries.
- ///
- /// [`Image`]: struct.Image.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
+
+ /// Sets the alt text of the [`Image`].
+ pub fn alt(mut self, alt: impl Into<String>) -> Self {
+ self.alt = alt.into();
+ self
+ }
}
impl<Message> Widget<Message> for Image {
@@ -66,12 +70,19 @@ impl<Message> Widget<Message> for Image {
_style_sheet: &mut Css<'b>,
) -> dodrio::Node<'b> {
use dodrio::builder::*;
+ use dodrio::bumpalo::collections::String;
- let src = bumpalo::format!(in bump, "{}", match self.handle.data.as_ref() {
- Data::Path(path) => path.to_str().unwrap_or("")
- });
+ let src = String::from_str_in(
+ match self.handle.data.as_ref() {
+ Data::Path(path) => path.to_str().unwrap_or(""),
+ },
+ bump,
+ )
+ .into_bump_str();
- let mut image = img(bump).attr("src", src.into_bump_str());
+ let alt = String::from_str_in(&self.alt, bump).into_bump_str();
+
+ let mut image = img(bump).attr("src", src).attr("alt", alt);
match self.width {
Length::Shrink => {}
@@ -99,8 +110,6 @@ impl<'a, Message> From<Image> for Element<'a, Message> {
}
/// An [`Image`] handle.
-///
-/// [`Image`]: struct.Image.html
#[derive(Debug, Clone)]
pub struct Handle {
id: u64,
@@ -109,8 +118,6 @@ pub struct Handle {
impl Handle {
/// Creates an image [`Handle`] pointing to the image of the given path.
- ///
- /// [`Handle`]: struct.Handle.html
pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle {
Self::from_data(Data::Path(path.into()))
}
@@ -126,15 +133,11 @@ impl Handle {
}
/// Returns the unique identifier of the [`Handle`].
- ///
- /// [`Handle`]: struct.Handle.html
pub fn id(&self) -> u64 {
self.id
}
/// Returns a reference to the image [`Data`].
- ///
- /// [`Data`]: enum.Data.html
pub fn data(&self) -> &Data {
&self.data
}
@@ -153,8 +156,6 @@ impl From<&str> for Handle {
}
/// The data of an [`Image`].
-///
-/// [`Image`]: struct.Image.html
#[derive(Clone, Hash)]
pub enum Data {
/// A remote image
diff --git a/web/src/widget/progress_bar.rs b/web/src/widget/progress_bar.rs
index 856203c0..7d77616e 100644
--- a/web/src/widget/progress_bar.rs
+++ b/web/src/widget/progress_bar.rs
@@ -32,8 +32,6 @@ impl ProgressBar {
/// It expects:
/// * an inclusive range of possible values
/// * the current value of the [`ProgressBar`]
- ///
- /// [`ProgressBar`]: struct.ProgressBar.html
pub fn new(range: RangeInclusive<f32>, value: f32) -> Self {
ProgressBar {
value: value.max(*range.start()).min(*range.end()),
@@ -45,24 +43,18 @@ impl ProgressBar {
}
/// Sets the width of the [`ProgressBar`].
- ///
- /// [`ProgressBar`]: struct.ProgressBar.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`ProgressBar`].
- ///
- /// [`ProgressBar`]: struct.ProgressBar.html
pub fn height(mut self, height: Length) -> Self {
self.height = Some(height);
self
}
/// Sets the style of the [`ProgressBar`].
- ///
- /// [`ProgressBar`]: struct.ProgressBar.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
diff --git a/web/src/widget/radio.rs b/web/src/widget/radio.rs
index 520b24cd..5a9bc379 100644
--- a/web/src/widget/radio.rs
+++ b/web/src/widget/radio.rs
@@ -35,6 +35,8 @@ pub struct Radio<Message> {
is_selected: bool,
on_click: Message,
label: String,
+ id: Option<String>,
+ name: Option<String>,
style: Box<dyn StyleSheet>,
}
@@ -47,8 +49,6 @@ impl<Message> Radio<Message> {
/// * the current selected value
/// * a function that will be called when the [`Radio`] is selected. It
/// receives the value of the radio and must produce a `Message`.
- ///
- /// [`Radio`]: struct.Radio.html
pub fn new<F, V>(
value: V,
label: impl Into<String>,
@@ -63,17 +63,29 @@ impl<Message> Radio<Message> {
is_selected: Some(value) == selected,
on_click: f(value),
label: label.into(),
+ id: None,
+ name: None,
style: Default::default(),
}
}
/// Sets the style of the [`Radio`] button.
- ///
- /// [`Radio`]: struct.Radio.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
}
+
+ /// Sets the name attribute of the [`Radio`] button.
+ pub fn name(mut self, name: impl Into<String>) -> Self {
+ self.name = Some(name.into());
+ self
+ }
+
+ /// Sets the id of the [`Radio`] button.
+ pub fn id(mut self, id: impl Into<String>) -> Self {
+ self.id = Some(id.into());
+ self
+ }
}
impl<Message> Widget<Message> for Radio<Message>
@@ -87,17 +99,35 @@ where
_style_sheet: &mut Css<'b>,
) -> dodrio::Node<'b> {
use dodrio::builder::*;
+ use dodrio::bumpalo::collections::String;
- let radio_label = bumpalo::format!(in bump, "{}", self.label);
+ let radio_label =
+ String::from_str_in(&self.label, bump).into_bump_str();
let event_bus = bus.clone();
let on_click = self.on_click.clone();
+ let (label, input) = if let Some(id) = &self.id {
+ let id = String::from_str_in(id, bump).into_bump_str();
+
+ (label(bump).attr("for", id), input(bump).attr("id", id))
+ } else {
+ (label(bump), input(bump))
+ };
+
+ let input = if let Some(name) = &self.name {
+ let name = String::from_str_in(name, bump).into_bump_str();
+
+ dodrio::builder::input(bump).attr("name", name)
+ } else {
+ input
+ };
+
// TODO: Complete styling
- label(bump)
+ label
.attr("style", "display: block; font-size: 20px")
.children(vec![
- input(bump)
+ input
.attr("type", "radio")
.attr("style", "margin-right: 10px")
.bool_attr("checked", self.is_selected)
@@ -105,7 +135,7 @@ where
event_bus.publish(on_click.clone());
})
.finish(),
- text(radio_label.into_bump_str()),
+ text(radio_label),
])
.finish()
}
diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs
index cfa10fdf..f00a544a 100644
--- a/web/src/widget/row.rs
+++ b/web/src/widget/row.rs
@@ -6,8 +6,6 @@ use std::u32;
/// A container that distributes its contents horizontally.
///
/// A [`Row`] will try to fill the horizontal space of its container.
-///
-/// [`Row`]: struct.Row.html
#[allow(missing_debug_implementations)]
pub struct Row<'a, Message> {
spacing: u16,
@@ -22,15 +20,11 @@ pub struct Row<'a, Message> {
impl<'a, Message> Row<'a, Message> {
/// Creates an empty [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn new() -> Self {
Self::with_children(Vec::new())
}
/// Creates a [`Row`] with the given elements.
- ///
- /// [`Row`]: struct.Row.html
pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
Row {
spacing: 0,
@@ -55,57 +49,42 @@ impl<'a, Message> Row<'a, Message> {
}
/// Sets the padding of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn padding(mut self, units: u16) -> Self {
self.padding = units;
self
}
/// Sets the width of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the maximum width of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn max_width(mut self, max_width: u32) -> Self {
self.max_width = max_width;
self
}
/// Sets the maximum height of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
pub fn max_height(mut self, max_height: u32) -> Self {
self.max_height = max_height;
self
}
/// Sets the vertical alignment of the contents of the [`Row`] .
- ///
- /// [`Row`]: struct.Row.html
pub fn align_items(mut self, align: Align) -> Self {
self.align_items = align;
self
}
/// Adds an [`Element`] to the [`Row`].
- ///
- /// [`Element`]: ../struct.Element.html
- /// [`Row`]: struct.Row.html
pub fn push<E>(mut self, child: E) -> Self
where
E: Into<Element<'a, Message>>,
diff --git a/web/src/widget/scrollable.rs b/web/src/widget/scrollable.rs
index 07b38aad..f9135dd6 100644
--- a/web/src/widget/scrollable.rs
+++ b/web/src/widget/scrollable.rs
@@ -16,9 +16,6 @@ pub struct Scrollable<'a, Message> {
impl<'a, Message> Scrollable<'a, Message> {
/// Creates a new [`Scrollable`] with the given [`State`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
- /// [`State`]: struct.State.html
pub fn new(_state: &'a mut State) -> Self {
use std::u32;
@@ -42,64 +39,48 @@ impl<'a, Message> Scrollable<'a, Message> {
}
/// Sets the padding of the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn padding(mut self, units: u16) -> Self {
self.content = self.content.padding(units);
self
}
/// Sets the width of the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the maximum width of the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn max_width(mut self, max_width: u32) -> Self {
self.content = self.content.max_width(max_width);
self
}
/// Sets the maximum height of the [`Scrollable`] in pixels.
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn max_height(mut self, max_height: u32) -> Self {
self.max_height = max_height;
self
}
/// Sets the horizontal alignment of the contents of the [`Scrollable`] .
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn align_items(mut self, align_items: Align) -> Self {
self.content = self.content.align_items(align_items);
self
}
/// Sets the style of the [`Scrollable`] .
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
}
/// Adds an element to the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
pub fn push<E>(mut self, child: E) -> Self
where
E: Into<Element<'a, Message>>,
@@ -154,15 +135,11 @@ where
}
/// The local state of a [`Scrollable`].
-///
-/// [`Scrollable`]: struct.Scrollable.html
#[derive(Debug, Clone, Copy, Default)]
pub struct State;
impl State {
/// Creates a new [`State`] with the scrollbar located at the top.
- ///
- /// [`State`]: struct.State.html
pub fn new() -> Self {
State::default()
}
diff --git a/web/src/widget/slider.rs b/web/src/widget/slider.rs
index 5aa6439e..91a4d2ec 100644
--- a/web/src/widget/slider.rs
+++ b/web/src/widget/slider.rs
@@ -1,9 +1,6 @@
//! 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, Css, Element, Length, Widget};
pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
@@ -16,7 +13,8 @@ use std::{ops::RangeInclusive, rc::Rc};
///
/// A [`Slider`] will try to fill the horizontal space of its container.
///
-/// [`Slider`]: struct.Slider.html
+/// The [`Slider`] range of numeric values is generic and its step size defaults
+/// to 1 unit.
///
/// # Example
/// ```
@@ -34,16 +32,20 @@ use std::{ops::RangeInclusive, rc::Rc};
///
/// ![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> {
+pub struct Slider<'a, T, Message> {
_state: &'a mut State,
- range: RangeInclusive<f32>,
- value: f32,
- on_change: Rc<Box<dyn Fn(f32) -> Message>>,
+ range: RangeInclusive<T>,
+ step: T,
+ value: T,
+ on_change: Rc<Box<dyn Fn(T) -> Message>>,
width: Length,
style: Box<dyn StyleSheet>,
}
-impl<'a, Message> Slider<'a, Message> {
+impl<'a, T, Message> Slider<'a, T, Message>
+where
+ T: Copy + From<u8> + std::cmp::PartialOrd,
+{
/// Creates a new [`Slider`].
///
/// It expects:
@@ -53,22 +55,32 @@ impl<'a, Message> Slider<'a, Message> {
/// * a function that will be called when the [`Slider`] is dragged.
/// It receives the new value of the [`Slider`] and must produce a
/// `Message`.
- ///
- /// [`Slider`]: struct.Slider.html
- /// [`State`]: struct.State.html
pub fn new<F>(
state: &'a mut State,
- range: RangeInclusive<f32>,
- value: f32,
+ range: RangeInclusive<T>,
+ value: T,
on_change: F,
) -> Self
where
- F: 'static + Fn(f32) -> Message,
+ F: 'static + Fn(T) -> Message,
{
+ let value = if value >= *range.start() {
+ value
+ } else {
+ *range.start()
+ };
+
+ let value = if value <= *range.end() {
+ value
+ } else {
+ *range.end()
+ };
+
Slider {
_state: state,
- value: value.max(*range.start()).min(*range.end()),
+ value,
range,
+ step: T::from(1),
on_change: Rc::new(Box::new(on_change)),
width: Length::Fill,
style: Default::default(),
@@ -76,24 +88,27 @@ impl<'a, Message> Slider<'a, Message> {
}
/// Sets the width of the [`Slider`].
- ///
- /// [`Slider`]: struct.Slider.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the style of the [`Slider`].
- ///
- /// [`Slider`]: struct.Slider.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style = style.into();
self
}
+
+ /// Sets the step size of the [`Slider`].
+ pub fn step(mut self, step: T) -> Self {
+ self.step = step;
+ self
+ }
}
-impl<'a, Message> Widget<Message> for Slider<'a, Message>
+impl<'a, T, Message> Widget<Message> for Slider<'a, T, Message>
where
+ T: 'static + Copy + Into<f64> + num_traits::FromPrimitive,
Message: 'static,
{
fn node<'b>(
@@ -107,18 +122,18 @@ where
let (start, end) = self.range.clone().into_inner();
- let min = bumpalo::format!(in bump, "{}", start);
- let max = bumpalo::format!(in bump, "{}", end);
- let value = bumpalo::format!(in bump, "{}", self.value);
+ let min = bumpalo::format!(in bump, "{}", start.into());
+ let max = bumpalo::format!(in bump, "{}", end.into());
+ let value = bumpalo::format!(in bump, "{}", self.value.into());
+ let step = bumpalo::format!(in bump, "{}", self.step.into());
let on_change = self.on_change.clone();
let event_bus = bus.clone();
- // TODO: Make `step` configurable
// TODO: Styling
input(bump)
.attr("type", "range")
- .attr("step", "0.01")
+ .attr("step", step.into_bump_str())
.attr("min", min.into_bump_str())
.attr("max", max.into_bump_str())
.attr("value", value.into_bump_str())
@@ -131,33 +146,32 @@ where
Some(slider) => slider,
};
- if let Ok(value) = slider.value().parse::<f32>() {
- event_bus.publish(on_change(value));
+ if let Ok(value) = slider.value().parse::<f64>() {
+ if let Some(value) = T::from_f64(value) {
+ event_bus.publish(on_change(value));
+ }
}
})
.finish()
}
}
-impl<'a, Message> From<Slider<'a, Message>> for Element<'a, Message>
+impl<'a, T, Message> From<Slider<'a, T, Message>> for Element<'a, Message>
where
+ T: 'static + Copy + Into<f64> + num_traits::FromPrimitive,
Message: 'static,
{
- fn from(slider: Slider<'a, Message>) -> Element<'a, Message> {
+ fn from(slider: Slider<'a, T, Message>) -> Element<'a, Message> {
Element::new(slider)
}
}
/// 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
}
diff --git a/web/src/widget/space.rs b/web/src/widget/space.rs
index 4ce52595..a8571fdb 100644
--- a/web/src/widget/space.rs
+++ b/web/src/widget/space.rs
@@ -12,15 +12,11 @@ pub struct Space {
impl Space {
/// Creates an amount of empty [`Space`] with the given width and height.
- ///
- /// [`Space`]: struct.Space.html
pub fn new(width: Length, height: Length) -> Self {
Space { width, height }
}
/// Creates an amount of horizontal [`Space`].
- ///
- /// [`Space`]: struct.Space.html
pub fn with_width(width: Length) -> Self {
Space {
width,
@@ -29,8 +25,6 @@ impl Space {
}
/// Creates an amount of vertical [`Space`].
- ///
- /// [`Space`]: struct.Space.html
pub fn with_height(height: Length) -> Self {
Space {
width: Length::Shrink,
diff --git a/web/src/widget/text.rs b/web/src/widget/text.rs
index 3ec565a8..72232dc0 100644
--- a/web/src/widget/text.rs
+++ b/web/src/widget/text.rs
@@ -28,8 +28,6 @@ pub struct Text {
impl Text {
/// Create a new fragment of [`Text`] with the given contents.
- ///
- /// [`Text`]: struct.Text.html
pub fn new<T: Into<String>>(label: T) -> Self {
Text {
content: label.into(),
@@ -44,51 +42,36 @@ impl Text {
}
/// Sets the size of the [`Text`].
- ///
- /// [`Text`]: struct.Text.html
pub fn size(mut self, size: u16) -> Self {
self.size = Some(size);
self
}
/// Sets the [`Color`] of the [`Text`].
- ///
- /// [`Text`]: struct.Text.html
- /// [`Color`]: ../../struct.Color.html
pub fn color<C: Into<Color>>(mut self, color: C) -> Self {
self.color = Some(color.into());
self
}
/// Sets the [`Font`] of the [`Text`].
- ///
- /// [`Text`]: struct.Text.html
- /// [`Font`]: ../../struct.Font.html
pub fn font(mut self, font: Font) -> Self {
self.font = font;
self
}
/// Sets the width of the [`Text`] boundaries.
- ///
- /// [`Text`]: struct.Text.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the height of the [`Text`] boundaries.
- ///
- /// [`Text`]: struct.Text.html
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
/// Sets the [`HorizontalAlignment`] of the [`Text`].
- ///
- /// [`Text`]: struct.Text.html
- /// [`HorizontalAlignment`]: enum.HorizontalAlignment.html
pub fn horizontal_alignment(
mut self,
alignment: HorizontalAlignment,
@@ -98,9 +81,6 @@ impl Text {
}
/// Sets the [`VerticalAlignment`] of the [`Text`].
- ///
- /// [`Text`]: struct.Text.html
- /// [`VerticalAlignment`]: enum.VerticalAlignment.html
pub fn vertical_alignment(mut self, alignment: VerticalAlignment) -> Self {
self.vertical_alignment = alignment;
self
@@ -116,7 +96,12 @@ impl<'a, Message> Widget<Message> for Text {
) -> dodrio::Node<'b> {
use dodrio::builder::*;
- let content = bumpalo::format!(in bump, "{}", self.content);
+ let content = {
+ use dodrio::bumpalo::collections::String;
+
+ String::from_str_in(&self.content, bump)
+ };
+
let color = self
.color
.map(css::color)
@@ -133,7 +118,8 @@ impl<'a, Message> Widget<Message> for Text {
let style = bumpalo::format!(
in bump,
- "width: {}; height: {}; font-size: {}px; color: {}; text-align: {}; font-family: {}",
+ "width: {}; height: {}; font-size: {}px; color: {}; \
+ text-align: {}; font-family: {}",
width,
height,
self.size.unwrap_or(20),
diff --git a/web/src/widget/text_input.rs b/web/src/widget/text_input.rs
index 3fa458bd..bc2048a8 100644
--- a/web/src/widget/text_input.rs
+++ b/web/src/widget/text_input.rs
@@ -1,9 +1,6 @@
//! Display fields that can be filled with text.
//!
//! A [`TextInput`] has some local [`State`].
-//!
-//! [`TextInput`]: struct.TextInput.html
-//! [`State`]: struct.State.html
use crate::{bumpalo, css, Bus, Css, Element, Length, Widget};
pub use iced_style::text_input::{Style, StyleSheet};
@@ -53,9 +50,6 @@ impl<'a, Message> TextInput<'a, Message> {
/// - a placeholder
/// - the current value
/// - a function that produces a message when the [`TextInput`] changes
- ///
- /// [`TextInput`]: struct.TextInput.html
- /// [`State`]: struct.State.html
pub fn new<F>(
state: &'a mut State,
placeholder: &str,
@@ -81,40 +75,30 @@ impl<'a, Message> TextInput<'a, Message> {
}
/// Converts the [`TextInput`] into a secure password input.
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn password(mut self) -> Self {
self.is_secure = true;
self
}
/// Sets the width of the [`TextInput`].
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
/// Sets the maximum width of the [`TextInput`].
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn max_width(mut self, max_width: u32) -> Self {
self.max_width = max_width;
self
}
/// Sets the padding of the [`TextInput`].
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn padding(mut self, units: u16) -> Self {
self.padding = units;
self
}
/// Sets the text size of the [`TextInput`].
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn size(mut self, size: u16) -> Self {
self.size = Some(size);
self
@@ -122,16 +106,12 @@ impl<'a, Message> TextInput<'a, Message> {
/// Sets the message that should be produced when the [`TextInput`] is
/// focused and the enter key is pressed.
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn on_submit(mut self, message: Message) -> Self {
self.on_submit = Some(message);
self
}
/// Sets the style of the [`TextInput`].
- ///
- /// [`TextInput`]: struct.TextInput.html
pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
self.style_sheet = style.into();
self
@@ -151,8 +131,26 @@ where
use dodrio::builder::*;
use wasm_bindgen::JsCast;
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
+ let class = {
+ use dodrio::bumpalo::collections::String;
+
+ let padding_class =
+ style_sheet.insert(bump, css::Rule::Padding(self.padding));
+
+ String::from_str_in(&padding_class, bump).into_bump_str()
+ };
+
+ let placeholder = {
+ use dodrio::bumpalo::collections::String;
+
+ String::from_str_in(&self.placeholder, bump).into_bump_str()
+ };
+
+ let value = {
+ use dodrio::bumpalo::collections::String;
+
+ String::from_str_in(&self.value, bump).into_bump_str()
+ };
let on_change = self.on_change.clone();
let on_submit = self.on_submit.clone();
@@ -161,15 +159,14 @@ where
let style = self.style_sheet.active();
input(bump)
- .attr(
- "class",
- bumpalo::format!(in bump, "{}", padding_class).into_bump_str(),
- )
+ .attr("class", class)
.attr(
"style",
bumpalo::format!(
in bump,
- "width: {}; max-width: {}; font-size: {}px; background: {}; border-width: {}px; border-color: {}; border-radius: {}px; color: {}",
+ "width: {}; max-width: {}; font-size: {}px; \
+ background: {}; border-width: {}px; border-color: {}; \
+ border-radius: {}px; color: {}",
css::length(self.width),
css::max_length(self.max_width),
self.size.unwrap_or(20),
@@ -181,19 +178,9 @@ where
)
.into_bump_str(),
)
- .attr(
- "placeholder",
- bumpalo::format!(in bump, "{}", self.placeholder)
- .into_bump_str(),
- )
- .attr(
- "value",
- bumpalo::format!(in bump, "{}", self.value).into_bump_str(),
- )
- .attr(
- "type",
- bumpalo::format!(in bump, "{}", if self.is_secure { "password" } else { "text" }).into_bump_str(),
- )
+ .attr("placeholder", placeholder)
+ .attr("value", value)
+ .attr("type", if self.is_secure { "password" } else { "text" })
.on("input", move |_root, _vdom, event| {
let text_input = match event.target().and_then(|t| {
t.dyn_into::<web_sys::HtmlInputElement>().ok()
@@ -206,10 +193,13 @@ where
})
.on("keypress", move |_root, _vdom, event| {
if let Some(on_submit) = on_submit.clone() {
- let event = event.unchecked_into::<web_sys::KeyboardEvent>();
+ let event =
+ event.unchecked_into::<web_sys::KeyboardEvent>();
match event.key_code() {
- 13 => { submit_event_bus.publish(on_submit); }
+ 13 => {
+ submit_event_bus.publish(on_submit);
+ }
_ => {}
}
}
@@ -228,22 +218,16 @@ where
}
/// The state of a [`TextInput`].
-///
-/// [`TextInput`]: struct.TextInput.html
#[derive(Debug, Clone, Copy, Default)]
pub struct State;
impl State {
/// Creates a new [`State`], representing an unfocused [`TextInput`].
- ///
- /// [`State`]: struct.State.html
pub fn new() -> Self {
Self::default()
}
/// Creates a new [`State`], representing a focused [`TextInput`].
- ///
- /// [`State`]: struct.State.html
pub fn focused() -> Self {
// TODO
Self::default()