diff options
Diffstat (limited to 'web/src/widget')
-rw-r--r-- | web/src/widget/button.rs | 76 | ||||
-rw-r--r-- | web/src/widget/checkbox.rs | 9 | ||||
-rw-r--r-- | web/src/widget/column.rs | 40 | ||||
-rw-r--r-- | web/src/widget/container.rs | 39 | ||||
-rw-r--r-- | web/src/widget/image.rs | 18 | ||||
-rw-r--r-- | web/src/widget/progress_bar.rs | 8 | ||||
-rw-r--r-- | web/src/widget/radio.rs | 9 | ||||
-rw-r--r-- | web/src/widget/row.rs | 41 | ||||
-rw-r--r-- | web/src/widget/scrollable.rs | 34 | ||||
-rw-r--r-- | web/src/widget/slider.rs | 20 | ||||
-rw-r--r-- | web/src/widget/space.rs | 6 | ||||
-rw-r--r-- | web/src/widget/text.rs | 20 | ||||
-rw-r--r-- | web/src/widget/text_input.rs | 58 | ||||
-rw-r--r-- | web/src/widget/toggler.rs | 171 |
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) + } +} |