summaryrefslogtreecommitdiffstats
path: root/web/src/widget
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/widget')
-rw-r--r--web/src/widget/button.rs76
-rw-r--r--web/src/widget/checkbox.rs9
-rw-r--r--web/src/widget/column.rs40
-rw-r--r--web/src/widget/container.rs39
-rw-r--r--web/src/widget/image.rs18
-rw-r--r--web/src/widget/progress_bar.rs8
-rw-r--r--web/src/widget/radio.rs9
-rw-r--r--web/src/widget/row.rs41
-rw-r--r--web/src/widget/scrollable.rs34
-rw-r--r--web/src/widget/slider.rs20
-rw-r--r--web/src/widget/space.rs6
-rw-r--r--web/src/widget/text.rs20
-rw-r--r--web/src/widget/text_input.rs58
-rw-r--r--web/src/widget/toggler.rs171
14 files changed, 258 insertions, 291 deletions
diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs
index a4bcc33d..cd450b55 100644
--- a/web/src/widget/button.rs
+++ b/web/src/widget/button.rs
@@ -1,10 +1,7 @@
//! 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};
+use crate::{css, Background, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::button::{Style, StyleSheet};
@@ -23,24 +20,43 @@ use dodrio::bumpalo;
/// let button = Button::new(&mut state, Text::new("Press me!"))
/// .on_press(Message::ButtonPressed);
/// ```
+///
+/// If a [`Button::on_press`] handler is not set, the resulting [`Button`] will
+/// be disabled:
+///
+/// ```
+/// # use iced_web::{button, Button, Text};
+/// #
+/// #[derive(Clone)]
+/// enum Message {
+/// ButtonPressed,
+/// }
+///
+/// fn disabled_button(state: &mut button::State) -> Button<'_, Message> {
+/// Button::new(state, Text::new("I'm disabled!"))
+/// }
+///
+/// fn enabled_button(state: &mut button::State) -> Button<'_, Message> {
+/// disabled_button(state).on_press(Message::ButtonPressed)
+/// }
+/// ```
#[allow(missing_debug_implementations)]
pub struct Button<'a, Message> {
content: Element<'a, Message>,
on_press: Option<Message>,
width: Length,
+ #[allow(dead_code)]
height: Length,
min_width: u32,
+ #[allow(dead_code)]
min_height: u32,
- padding: u16,
+ padding: Padding,
style: Box<dyn StyleSheet>,
}
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>>,
@@ -52,62 +68,49 @@ impl<'a, Message> Button<'a, Message> {
height: Length::Shrink,
min_width: 0,
min_height: 0,
- padding: 5,
+ padding: Padding::new(5),
style: Default::default(),
}
}
/// 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;
+ /// Sets the [`Padding`] of the [`Button`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
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
+ /// If on_press isn't set, button will be disabled.
pub fn on_press(mut self, msg: Message) -> Self {
self.on_press = Some(msg);
self
@@ -115,15 +118,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()
}
@@ -144,9 +143,6 @@ where
// TODO: State-based styling
let style = self.style.active();
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
let background = match style.background {
None => String::from("none"),
Some(background) => match background {
@@ -154,25 +150,19 @@ 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", class)
.attr(
"style",
bumpalo::format!(
in bump,
"background: {}; border-radius: {}px; width:{}; \
- min-width: {}; color: {}",
+ min-width: {}; color: {}; padding: {}",
background,
style.border_radius,
css::length(self.width),
css::min_length(self.min_width),
- css::color(style.text_color)
+ css::color(style.text_color),
+ css::padding(self.padding)
)
.into_bump_str(),
)
@@ -184,6 +174,8 @@ where
node = node.on("click", move |_root, _vdom, _event| {
event_bus.publish(on_press.clone());
});
+ } else {
+ node = node.attr("disabled", "");
}
node.finish()
diff --git a/web/src/widget/checkbox.rs b/web/src/widget/checkbox.rs
index 21801e39..43110aa7 100644
--- a/web/src/widget/checkbox.rs
+++ b/web/src/widget/checkbox.rs
@@ -30,6 +30,7 @@ pub struct Checkbox<Message> {
label: String,
id: Option<String>,
width: Length,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
@@ -42,8 +43,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,
@@ -59,24 +58,18 @@ impl<Message> Checkbox<Message> {
}
/// 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`].
- ///
- /// [`Checkbox`]: struct.Checkbox.html
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs
index 25b88b0e..8738c2af 100644
--- a/web/src/widget/column.rs
+++ b/web/src/widget/column.rs
@@ -1,4 +1,4 @@
-use crate::{css, Align, Bus, Css, Element, Length, Widget};
+use crate::{css, Align, Bus, Css, Element, Length, Padding, Widget};
use dodrio::bumpalo;
use std::u32;
@@ -6,12 +6,10 @@ 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,
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
@@ -22,19 +20,15 @@ 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,
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Fill,
height: Length::Shrink,
max_width: u32::MAX,
@@ -54,57 +48,43 @@ impl<'a, Message> Column<'a, Message> {
self
}
- /// Sets the padding of the [`Column`].
- ///
- /// [`Column`]: struct.Column.html
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`Column`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
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>>,
@@ -134,23 +114,21 @@ impl<'a, Message> Widget<Message> for Column<'a, Message> {
let spacing_class =
style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
// TODO: Complete styling
div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {} {}", column_class, spacing_class, padding_class)
+ bumpalo::format!(in bump, "{} {}", column_class, spacing_class)
.into_bump_str(),
)
.attr("style", bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; max-height: {}; align-items: {}",
+ "width: {}; height: {}; max-width: {}; max-height: {}; padding: {}; align-items: {}",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
css::max_length(self.max_height),
+ css::padding(self.padding),
css::align(self.align_items)
).into_bump_str()
)
diff --git a/web/src/widget/container.rs b/web/src/widget/container.rs
index 78be3543..c006e011 100644
--- a/web/src/widget/container.rs
+++ b/web/src/widget/container.rs
@@ -1,5 +1,5 @@
//! Decorate content and apply alignment.
-use crate::{bumpalo, css, Align, Bus, Css, Element, Length, Widget};
+use crate::{bumpalo, css, Align, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::container::{Style, StyleSheet};
@@ -8,10 +8,11 @@ pub use iced_style::container::{Style, StyleSheet};
/// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)]
pub struct Container<'a, Message> {
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
+ #[allow(dead_code)]
max_height: u32,
horizontal_alignment: Align,
vertical_alignment: Align,
@@ -21,8 +22,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>>,
@@ -30,7 +29,7 @@ impl<'a, Message> Container<'a, Message> {
use std::u32;
Container {
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Shrink,
height: Length::Shrink,
max_width: u32::MAX,
@@ -42,49 +41,37 @@ 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;
+ /// Sets the [`Padding`] of the [`Container`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
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 +79,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 +86,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
@@ -123,24 +106,22 @@ where
let column_class = style_sheet.insert(bump, css::Rule::Column);
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
let style = self.style_sheet.style();
let node = div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {}", column_class, padding_class).into_bump_str(),
+ bumpalo::format!(in bump, "{}", column_class).into_bump_str(),
)
.attr(
"style",
bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; align-items: {}; justify-content: {}; background: {}; color: {}; border-width: {}px; border-color: {}; border-radius: {}px",
+ "width: {}; height: {}; max-width: {}; padding: {}; align-items: {}; justify-content: {}; background: {}; color: {}; border-width: {}px; border-color: {}; border-radius: {}px",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
+ css::padding(self.padding),
css::align(self.horizontal_alignment),
css::align(self.vertical_alignment),
style.background.map(css::background).unwrap_or(String::from("initial")),
diff --git a/web/src/widget/image.rs b/web/src/widget/image.rs
index a595c29a..05c89ea5 100644
--- a/web/src/widget/image.rs
+++ b/web/src/widget/image.rs
@@ -34,8 +34,6 @@ 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(),
@@ -46,24 +44,18 @@ impl Image {
}
/// 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`].
- ///
- /// [`Image`]: struct.Image.html
pub fn alt(mut self, alt: impl Into<String>) -> Self {
self.alt = alt.into();
self
@@ -118,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,
@@ -128,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()))
}
@@ -145,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
}
@@ -172,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 c9d0a00e..fbc88d29 100644
--- a/web/src/widget/radio.rs
+++ b/web/src/widget/radio.rs
@@ -37,6 +37,7 @@ pub struct Radio<Message> {
label: String,
id: Option<String>,
name: Option<String>,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
@@ -49,8 +50,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>,
@@ -72,24 +71,18 @@ impl<Message> Radio<Message> {
}
/// 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.
- ///
- /// [`Radio`]: struct.Radio.html
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
/// Sets the id of the [`Radio`] button.
- ///
- /// [`Radio`]: struct.Radio.html
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs
index cfa10fdf..ffb515cf 100644
--- a/web/src/widget/row.rs
+++ b/web/src/widget/row.rs
@@ -1,4 +1,4 @@
-use crate::{css, Align, Bus, Css, Element, Length, Widget};
+use crate::{css, Align, Bus, Css, Element, Length, Padding, Widget};
use dodrio::bumpalo;
use std::u32;
@@ -6,12 +6,10 @@ 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,
- padding: u16,
+ padding: Padding,
width: Length,
height: Length,
max_width: u32,
@@ -22,19 +20,15 @@ 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,
- padding: 0,
+ padding: Padding::ZERO,
width: Length::Fill,
height: Length::Shrink,
max_width: u32::MAX,
@@ -54,58 +48,43 @@ impl<'a, Message> Row<'a, Message> {
self
}
- /// Sets the padding of the [`Row`].
- ///
- /// [`Row`]: struct.Row.html
- pub fn padding(mut self, units: u16) -> Self {
- self.padding = units;
+ /// Sets the [`Padding`] of the [`Row`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
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>>,
@@ -135,23 +114,21 @@ impl<'a, Message> Widget<Message> for Row<'a, Message> {
let spacing_class =
style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
- let padding_class =
- style_sheet.insert(bump, css::Rule::Padding(self.padding));
-
// TODO: Complete styling
div(bump)
.attr(
"class",
- bumpalo::format!(in bump, "{} {} {}", row_class, spacing_class, padding_class)
+ bumpalo::format!(in bump, "{} {}", row_class, spacing_class)
.into_bump_str(),
)
.attr("style", bumpalo::format!(
in bump,
- "width: {}; height: {}; max-width: {}; max-height: {}; align-items: {}",
+ "width: {}; height: {}; max-width: {}; max-height: {}; padding: {}; align-items: {}",
css::length(self.width),
css::length(self.height),
css::max_length(self.max_width),
css::max_length(self.max_height),
+ css::padding(self.padding),
css::align(self.align_items)
).into_bump_str()
)
diff --git a/web/src/widget/scrollable.rs b/web/src/widget/scrollable.rs
index 07b38aad..ce0a10d4 100644
--- a/web/src/widget/scrollable.rs
+++ b/web/src/widget/scrollable.rs
@@ -1,5 +1,7 @@
//! Navigate an endless amount of content with a scrollbar.
-use crate::{bumpalo, css, Align, Bus, Column, Css, Element, Length, Widget};
+use crate::{
+ bumpalo, css, Align, Bus, Column, Css, Element, Length, Padding, Widget,
+};
pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
@@ -11,14 +13,12 @@ pub struct Scrollable<'a, Message> {
height: Length,
max_height: u32,
content: Column<'a, Message>,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
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;
@@ -41,65 +41,49 @@ impl<'a, Message> Scrollable<'a, Message> {
self
}
- /// Sets the padding of the [`Scrollable`].
- ///
- /// [`Scrollable`]: struct.Scrollable.html
- pub fn padding(mut self, units: u16) -> Self {
- self.content = self.content.padding(units);
+ /// Sets the [`Padding`] of the [`Scrollable`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.content = self.content.padding(padding);
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 +138,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 a0d9df00..f457aa4c 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};
@@ -19,8 +16,6 @@ use std::{ops::RangeInclusive, rc::Rc};
/// The [`Slider`] range of numeric values is generic and its step size defaults
/// to 1 unit.
///
-/// [`Slider`]: struct.Slider.html
-///
/// # Example
/// ```
/// # use iced_web::{slider, Slider};
@@ -43,7 +38,9 @@ pub struct Slider<'a, T, Message> {
step: T,
value: T,
on_change: Rc<Box<dyn Fn(T) -> Message>>,
+ #[allow(dead_code)]
width: Length,
+ #[allow(dead_code)]
style: Box<dyn StyleSheet>,
}
@@ -60,9 +57,6 @@ where
/// * 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<T>,
@@ -96,24 +90,18 @@ where
}
/// 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`].
- ///
- /// [`Slider`]: struct.Slider.html
pub fn step(mut self, step: T) -> Self {
self.step = step;
self
@@ -181,15 +169,11 @@ 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
}
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 2f7308ee..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
diff --git a/web/src/widget/text_input.rs b/web/src/widget/text_input.rs
index 0049a553..e4877f2a 100644
--- a/web/src/widget/text_input.rs
+++ b/web/src/widget/text_input.rs
@@ -1,10 +1,7 @@
//! 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};
+use crate::{bumpalo, css, Bus, Css, Element, Length, Padding, Widget};
pub use iced_style::text_input::{Style, StyleSheet};
@@ -38,7 +35,7 @@ pub struct TextInput<'a, Message> {
is_secure: bool,
width: Length,
max_width: u32,
- padding: u16,
+ padding: Padding,
size: Option<u16>,
on_change: Rc<Box<dyn Fn(String) -> Message>>,
on_submit: Option<Message>,
@@ -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,
@@ -72,7 +66,7 @@ impl<'a, Message> TextInput<'a, Message> {
is_secure: false,
width: Length::Fill,
max_width: u32::MAX,
- padding: 0,
+ padding: Padding::ZERO,
size: None,
on_change: Rc::new(Box::new(on_change)),
on_submit: None,
@@ -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;
+ /// Sets the [`Padding`] of the [`TextInput`].
+ pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
+ self.padding = padding.into();
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
@@ -146,20 +126,11 @@ where
&self,
bump: &'b bumpalo::Bump,
bus: &Bus<Message>,
- style_sheet: &mut Css<'b>,
+ _style_sheet: &mut Css<'b>,
) -> dodrio::Node<'b> {
use dodrio::builder::*;
use wasm_bindgen::JsCast;
- 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;
@@ -179,16 +150,16 @@ where
let style = self.style_sheet.active();
input(bump)
- .attr("class", class)
.attr(
"style",
bumpalo::format!(
in bump,
- "width: {}; max-width: {}; font-size: {}px; \
+ "width: {}; max-width: {}; padding: {}; font-size: {}px; \
background: {}; border-width: {}px; border-color: {}; \
border-radius: {}px; color: {}",
css::length(self.width),
css::max_length(self.max_width),
+ css::padding(self.padding),
self.size.unwrap_or(20),
css::background(style.background),
style.border_width,
@@ -238,24 +209,23 @@ 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()
}
+
+ /// Selects all the content of the [`TextInput`].
+ pub fn select_all(&mut self) {
+ // TODO
+ }
}
diff --git a/web/src/widget/toggler.rs b/web/src/widget/toggler.rs
new file mode 100644
index 00000000..0a198079
--- /dev/null
+++ b/web/src/widget/toggler.rs
@@ -0,0 +1,171 @@
+//! Show toggle controls using togglers.
+use crate::{css, Bus, Css, Element, Length, Widget};
+
+pub use iced_style::toggler::{Style, StyleSheet};
+
+use dodrio::bumpalo;
+use std::rc::Rc;
+
+/// A toggler that can be toggled.
+///
+/// # Example
+///
+/// ```
+/// # use iced_web::Toggler;
+///
+/// pub enum Message {
+/// TogglerToggled(bool),
+/// }
+///
+/// let is_active = true;
+///
+/// Toggler::new(is_active, String::from("Toggle me!"), Message::TogglerToggled);
+/// ```
+///
+#[allow(missing_debug_implementations)]
+pub struct Toggler<Message> {
+ is_active: bool,
+ on_toggle: Rc<dyn Fn(bool) -> Message>,
+ label: Option<String>,
+ id: Option<String>,
+ width: Length,
+ style: Box<dyn StyleSheet>,
+}
+
+impl<Message> Toggler<Message> {
+ /// Creates a new [`Toggler`].
+ ///
+ /// It expects:
+ /// * a boolean describing whether the [`Toggler`] is active or not
+ /// * An optional label for the [`Toggler`]
+ /// * a function that will be called when the [`Toggler`] is toggled. It
+ /// will receive the new state of the [`Toggler`] and must produce a
+ /// `Message`.
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn new<F>(
+ is_active: bool,
+ label: impl Into<Option<String>>,
+ f: F,
+ ) -> Self
+ where
+ F: 'static + Fn(bool) -> Message,
+ {
+ Toggler {
+ is_active,
+ on_toggle: Rc::new(f),
+ label: label.into(),
+ id: None,
+ width: Length::Shrink,
+ style: Default::default(),
+ }
+ }
+
+ /// Sets the width of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn width(mut self, width: Length) -> Self {
+ self.width = width;
+ self
+ }
+
+ /// Sets the style of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
+ self.style = style.into();
+ self
+ }
+
+ /// Sets the id of the [`Toggler`].
+ ///
+ /// [`Toggler`]: struct.Toggler.html
+ pub fn id(mut self, id: impl Into<String>) -> Self {
+ self.id = Some(id.into());
+ self
+ }
+}
+
+impl<Message> Widget<Message> for Toggler<Message>
+where
+ Message: 'static,
+{
+ fn node<'b>(
+ &self,
+ bump: &'b bumpalo::Bump,
+ bus: &Bus<Message>,
+ style_sheet: &mut Css<'b>,
+ ) -> dodrio::Node<'b> {
+ use dodrio::builder::*;
+ use dodrio::bumpalo::collections::String;
+
+ let toggler_label = &self
+ .label
+ .as_ref()
+ .map(|label| String::from_str_in(&label, bump).into_bump_str());
+
+ let event_bus = bus.clone();
+ let on_toggle = self.on_toggle.clone();
+ let is_active = self.is_active;
+
+ let row_class = style_sheet.insert(bump, css::Rule::Row);
+ let toggler_class = style_sheet.insert(bump, css::Rule::Toggler(16));
+
+ 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 checkbox = input
+ .attr("type", "checkbox")
+ .bool_attr("checked", self.is_active)
+ .on("click", move |_root, vdom, _event| {
+ let msg = on_toggle(!is_active);
+ event_bus.publish(msg);
+
+ vdom.schedule_render();
+ })
+ .finish();
+
+ let toggler = span(bump).children(vec![span(bump).finish()]).finish();
+
+ label
+ .attr(
+ "class",
+ bumpalo::format!(in bump, "{} {}", row_class, toggler_class)
+ .into_bump_str(),
+ )
+ .attr(
+ "style",
+ bumpalo::format!(in bump, "width: {}; align-items: center", css::length(self.width))
+ .into_bump_str()
+ )
+ .children(
+ if let Some(label) = toggler_label {
+ vec![
+ text(label),
+ checkbox,
+ toggler,
+ ]
+ } else {
+ vec![
+ checkbox,
+ toggler,
+ ]
+ }
+ )
+ .finish()
+ }
+}
+
+impl<'a, Message> From<Toggler<Message>> for Element<'a, Message>
+where
+ Message: 'static,
+{
+ fn from(toggler: Toggler<Message>) -> Element<'a, Message> {
+ Element::new(toggler)
+ }
+}