summaryrefslogtreecommitdiffstats
path: root/web/src/widget
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-01-28 16:47:50 +0700
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-01-28 21:37:16 +0700
commit825c7749ff364cf1f7ae5cab0c25f27ed85c7d82 (patch)
treefdd7e499c343a7e3cf690d4b5aa40ba568674a3c /web/src/widget
parent1e3feee3a36f25d7e2eda231c3e6b895858952c5 (diff)
downloadiced-825c7749ff364cf1f7ae5cab0c25f27ed85c7d82.tar.gz
iced-825c7749ff364cf1f7ae5cab0c25f27ed85c7d82.tar.bz2
iced-825c7749ff364cf1f7ae5cab0c25f27ed85c7d82.zip
Replace `iced_web` with WebGL support in `wgpu` :tada:
Diffstat (limited to 'web/src/widget')
-rw-r--r--web/src/widget/button.rs192
-rw-r--r--web/src/widget/checkbox.rs150
-rw-r--r--web/src/widget/column.rs148
-rw-r--r--web/src/widget/container.rs153
-rw-r--r--web/src/widget/image.rs186
-rw-r--r--web/src/widget/progress_bar.rs116
-rw-r--r--web/src/widget/radio.rs155
-rw-r--r--web/src/widget/row.rs148
-rw-r--r--web/src/widget/scrollable.rs152
-rw-r--r--web/src/widget/slider.rs183
-rw-r--r--web/src/widget/space.rs63
-rw-r--r--web/src/widget/text.rs148
-rw-r--r--web/src/widget/text_input.rs234
-rw-r--r--web/src/widget/toggler.rs171
14 files changed, 0 insertions, 2199 deletions
diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs
deleted file mode 100644
index 88137607..00000000
--- a/web/src/widget/button.rs
+++ /dev/null
@@ -1,192 +0,0 @@
-//! Allow your users to perform actions by pressing a button.
-//!
-//! A [`Button`] has some local [`State`].
-use crate::{css, Background, Bus, Css, Element, Length, Padding, Widget};
-
-pub use iced_style::button::{Style, StyleSheet};
-
-use dodrio::bumpalo;
-
-/// A generic widget that produces a message when pressed.
-///
-/// ```
-/// # use iced_web::{button, Button, Text};
-/// #
-/// enum Message {
-/// ButtonPressed,
-/// }
-///
-/// let mut state = button::State::new();
-/// let button = Button::new(&mut state, Text::new("Press me!"))
-/// .on_press(Message::ButtonPressed);
-/// ```
-///
-/// 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: Padding,
- style: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, Message> Button<'a, Message> {
- /// Creates a new [`Button`] with some local [`State`] and the given
- /// content.
- pub fn new<E>(_state: &'a mut State, content: E) -> Self
- where
- E: Into<Element<'a, Message>>,
- {
- Button {
- content: content.into(),
- on_press: None,
- width: Length::Shrink,
- height: Length::Shrink,
- min_width: 0,
- min_height: 0,
- padding: Padding::new(5),
- style: Default::default(),
- }
- }
-
- /// Sets the width of the [`Button`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Button`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the minimum width of the [`Button`].
- pub fn min_width(mut self, min_width: u32) -> Self {
- self.min_width = min_width;
- self
- }
-
- /// Sets the minimum height of the [`Button`].
- pub fn min_height(mut self, min_height: u32) -> Self {
- self.min_height = min_height;
- self
- }
-
- /// 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`].
- pub fn style(mut self, style: impl Into<Box<dyn StyleSheet + 'a>>) -> Self {
- self.style = style.into();
- self
- }
-
- /// Sets the message that will be produced when the [`Button`] is pressed.
- /// 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
- }
-}
-
-/// The local state of a [`Button`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
-pub struct State;
-
-impl State {
- /// Creates a new [`State`].
- pub fn new() -> State {
- State::default()
- }
-}
-
-impl<'a, Message> Widget<Message> for Button<'a, Message>
-where
- Message: 'static + Clone,
-{
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- bus: &Bus<Message>,
- style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- // TODO: State-based styling
- let style = self.style.active();
-
- let background = match style.background {
- None => String::from("none"),
- Some(background) => match background {
- Background::Color(color) => css::color(color),
- },
- };
-
- let mut node = button(bump)
- .attr(
- "style",
- bumpalo::format!(
- in bump,
- "background: {}; border-radius: {}px; width:{}; \
- min-width: {}; color: {}; padding: {}",
- background,
- style.border_radius,
- css::length(self.width),
- css::min_length(self.min_width),
- css::color(style.text_color),
- css::padding(self.padding)
- )
- .into_bump_str(),
- )
- .children(vec![self.content.node(bump, bus, style_sheet)]);
-
- if let Some(on_press) = self.on_press.clone() {
- let event_bus = bus.clone();
-
- node = node.on("click", move |_root, _vdom, _event| {
- event_bus.publish(on_press.clone());
- });
- } else {
- node = node.attr("disabled", "");
- }
-
- node.finish()
- }
-}
-
-impl<'a, Message> From<Button<'a, Message>> for Element<'a, Message>
-where
- Message: 'static + Clone,
-{
- fn from(button: Button<'a, Message>) -> Element<'a, Message> {
- Element::new(button)
- }
-}
diff --git a/web/src/widget/checkbox.rs b/web/src/widget/checkbox.rs
deleted file mode 100644
index 844bf862..00000000
--- a/web/src/widget/checkbox.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-//! Show toggle controls using checkboxes.
-use crate::{css, Bus, Css, Element, Length, Widget};
-
-pub use iced_style::checkbox::{Style, StyleSheet};
-
-use dodrio::bumpalo;
-use std::rc::Rc;
-
-/// A box that can be checked.
-///
-/// # Example
-///
-/// ```
-/// # use iced_web::Checkbox;
-///
-/// pub enum Message {
-/// CheckboxToggled(bool),
-/// }
-///
-/// let is_checked = true;
-///
-/// Checkbox::new(is_checked, "Toggle me!", Message::CheckboxToggled);
-/// ```
-///
-/// ![Checkbox drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/checkbox.png?raw=true)
-#[allow(missing_debug_implementations)]
-pub struct Checkbox<'a, Message> {
- is_checked: bool,
- on_toggle: Rc<dyn Fn(bool) -> Message>,
- label: String,
- id: Option<String>,
- width: Length,
- #[allow(dead_code)]
- style_sheet: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, Message> Checkbox<'a, Message> {
- /// Creates a new [`Checkbox`].
- ///
- /// It expects:
- /// * a boolean describing whether the [`Checkbox`] is checked or not
- /// * the label of the [`Checkbox`]
- /// * 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`.
- pub fn new<F>(is_checked: bool, label: impl Into<String>, f: F) -> Self
- where
- F: 'static + Fn(bool) -> Message,
- {
- Checkbox {
- is_checked,
- on_toggle: Rc::new(f),
- label: label.into(),
- id: None,
- width: Length::Shrink,
- style_sheet: Default::default(),
- }
- }
-
- /// Sets the width of the [`Checkbox`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the style of the [`Checkbox`].
- pub fn style(
- mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
- ) -> Self {
- self.style_sheet = style_sheet.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<'a, Message> Widget<Message> for Checkbox<'a, 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 checkbox_label =
- String::from_str_in(&self.label, bump).into_bump_str();
-
- let event_bus = bus.clone();
- let on_toggle = self.on_toggle.clone();
- let is_checked = self.is_checked;
-
- let row_class = style_sheet.insert(bump, css::Rule::Row);
-
- let spacing_class = style_sheet.insert(bump, css::Rule::Spacing(5));
-
- 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)
- .into_bump_str(),
- )
- .attr(
- "style",
- bumpalo::format!(in bump, "width: {}; align-items: center", css::length(self.width))
- .into_bump_str(),
- )
- .children(vec![
- // TODO: Checkbox styling
- input
- .attr("type", "checkbox")
- .bool_attr("checked", self.is_checked)
- .on("click", move |_root, vdom, _event| {
- let msg = on_toggle(!is_checked);
- event_bus.publish(msg);
-
- vdom.schedule_render();
- })
- .finish(),
- text(checkbox_label),
- ])
- .finish()
- }
-}
-
-impl<'a, Message> From<Checkbox<'a, Message>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(checkbox: Checkbox<'a, Message>) -> Element<'a, Message> {
- Element::new(checkbox)
- }
-}
diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs
deleted file mode 100644
index 30a57c41..00000000
--- a/web/src/widget/column.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-use crate::css;
-use crate::{Alignment, Bus, Css, Element, Length, Padding, Widget};
-
-use dodrio::bumpalo;
-use std::u32;
-
-/// A container that distributes its contents vertically.
-///
-/// A [`Column`] will try to fill the horizontal space of its container.
-#[allow(missing_debug_implementations)]
-pub struct Column<'a, Message> {
- spacing: u16,
- padding: Padding,
- width: Length,
- height: Length,
- max_width: u32,
- max_height: u32,
- align_items: Alignment,
- children: Vec<Element<'a, Message>>,
-}
-
-impl<'a, Message> Column<'a, Message> {
- /// Creates an empty [`Column`].
- pub fn new() -> Self {
- Self::with_children(Vec::new())
- }
-
- /// Creates a [`Column`] with the given elements.
- pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
- Column {
- spacing: 0,
- padding: Padding::ZERO,
- width: Length::Fill,
- height: Length::Shrink,
- max_width: u32::MAX,
- max_height: u32::MAX,
- align_items: Alignment::Start,
- children,
- }
- }
-
- /// Sets the vertical spacing _between_ elements.
- ///
- /// Custom margins per element do not exist in Iced. You should use this
- /// method instead! While less flexible, it helps you keep spacing between
- /// elements consistent.
- pub fn spacing(mut self, units: u16) -> Self {
- self.spacing = units;
- self
- }
-
- /// 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`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Column`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the maximum width of the [`Column`].
- 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.
- 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`] .
- pub fn align_items(mut self, align: Alignment) -> Self {
- self.align_items = align;
- self
- }
-
- /// Adds an element to the [`Column`].
- pub fn push<E>(mut self, child: E) -> Self
- where
- E: Into<Element<'a, Message>>,
- {
- self.children.push(child.into());
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for Column<'a, Message> {
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- publish: &Bus<Message>,
- style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- let children: Vec<_> = self
- .children
- .iter()
- .map(|element| element.widget.node(bump, publish, style_sheet))
- .collect();
-
- let column_class = style_sheet.insert(bump, css::Rule::Column);
-
- let spacing_class =
- style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
-
- // TODO: Complete styling
- div(bump)
- .attr(
- "class",
- bumpalo::format!(in bump, "{} {}", column_class, spacing_class)
- .into_bump_str(),
- )
- .attr("style", bumpalo::format!(
- in bump,
- "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::alignment(self.align_items)
- ).into_bump_str()
- )
- .children(children)
- .finish()
- }
-}
-
-impl<'a, Message> From<Column<'a, Message>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(column: Column<'a, Message>) -> Element<'a, Message> {
- Element::new(column)
- }
-}
diff --git a/web/src/widget/container.rs b/web/src/widget/container.rs
deleted file mode 100644
index 8e345b9a..00000000
--- a/web/src/widget/container.rs
+++ /dev/null
@@ -1,153 +0,0 @@
-//! Decorate content and apply alignment.
-use crate::alignment::{self, Alignment};
-use crate::bumpalo;
-use crate::css;
-use crate::{Bus, Css, Element, Length, Padding, Widget};
-
-pub use iced_style::container::{Style, StyleSheet};
-
-/// An element decorating some content.
-///
-/// It is normally used for alignment purposes.
-#[allow(missing_debug_implementations)]
-pub struct Container<'a, Message> {
- padding: Padding,
- width: Length,
- height: Length,
- max_width: u32,
- #[allow(dead_code)]
- max_height: u32,
- horizontal_alignment: alignment::Horizontal,
- vertical_alignment: alignment::Vertical,
- style_sheet: Box<dyn StyleSheet + 'a>,
- content: Element<'a, Message>,
-}
-
-impl<'a, Message> Container<'a, Message> {
- /// Creates an empty [`Container`].
- pub fn new<T>(content: T) -> Self
- where
- T: Into<Element<'a, Message>>,
- {
- use std::u32;
-
- Container {
- padding: Padding::ZERO,
- width: Length::Shrink,
- height: Length::Shrink,
- max_width: u32::MAX,
- max_height: u32::MAX,
- horizontal_alignment: alignment::Horizontal::Left,
- vertical_alignment: alignment::Vertical::Top,
- style_sheet: Default::default(),
- content: content.into(),
- }
- }
-
- /// 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`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Container`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the maximum width of the [`Container`].
- 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.
- 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`].
- pub fn center_x(mut self) -> Self {
- self.horizontal_alignment = alignment::Horizontal::Center;
-
- self
- }
-
- /// Centers the contents in the vertical axis of the [`Container`].
- pub fn center_y(mut self) -> Self {
- self.vertical_alignment = alignment::Vertical::Center;
-
- self
- }
-
- /// Sets the style of the [`Container`].
- pub fn style(mut self, style: impl Into<Box<dyn StyleSheet + 'a>>) -> Self {
- self.style_sheet = style.into();
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for Container<'a, 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::*;
-
- let column_class = style_sheet.insert(bump, css::Rule::Column);
-
- let style = self.style_sheet.style();
-
- let node = div(bump)
- .attr(
- "class",
- bumpalo::format!(in bump, "{}", column_class).into_bump_str(),
- )
- .attr(
- "style",
- bumpalo::format!(
- in bump,
- "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::alignment(Alignment::from(self.horizontal_alignment)),
- css::alignment(Alignment::from(self.vertical_alignment)),
- style.background.map(css::background).unwrap_or(String::from("initial")),
- style.text_color.map(css::color).unwrap_or(String::from("inherit")),
- style.border_width,
- css::color(style.border_color),
- style.border_radius
- )
- .into_bump_str(),
- )
- .children(vec![self.content.node(bump, bus, style_sheet)]);
-
- // TODO: Complete styling
-
- node.finish()
- }
-}
-
-impl<'a, Message> From<Container<'a, Message>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(container: Container<'a, Message>) -> Element<'a, Message> {
- Element::new(container)
- }
-}
diff --git a/web/src/widget/image.rs b/web/src/widget/image.rs
deleted file mode 100644
index 28435f4f..00000000
--- a/web/src/widget/image.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-//! Display images in your user interface.
-use crate::{Bus, Css, Element, Hasher, Length, Widget};
-
-use dodrio::bumpalo;
-use std::{
- hash::{Hash, Hasher as _},
- path::PathBuf,
- sync::Arc,
-};
-
-/// A frame that displays an image while keeping aspect ratio.
-///
-/// # Example
-///
-/// ```
-/// # use iced_web::Image;
-///
-/// let image = Image::new("resources/ferris.png");
-/// ```
-#[derive(Debug)]
-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,
-
- /// The height of the image
- pub height: Length,
-}
-
-impl Image {
- /// Creates a new [`Image`] with the given path.
- 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.
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Image`] boundaries.
- 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 {
- 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 src = match self.handle.data.as_ref() {
- Data::Path(path) => {
- String::from_str_in(path.to_str().unwrap_or(""), bump)
- }
- Data::Bytes(bytes) => {
- // The web is able to infer the kind of image, so we don't have to add a dependency on image-rs to guess the mime type.
- bumpalo::format!(in bump, "data:;base64,{}", base64::encode(bytes))
- },
- }
- .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 => {}
- Length::Fill | Length::FillPortion(_) => {
- image = image.attr("width", "100%");
- }
- Length::Units(px) => {
- image = image.attr(
- "width",
- bumpalo::format!(in bump, "{}px", px).into_bump_str(),
- );
- }
- }
-
- // TODO: Complete styling
-
- image.finish()
- }
-}
-
-impl<'a, Message> From<Image> for Element<'a, Message> {
- fn from(image: Image) -> Element<'a, Message> {
- Element::new(image)
- }
-}
-
-/// An [`Image`] handle.
-#[derive(Debug, Clone)]
-pub struct Handle {
- id: u64,
- data: Arc<Data>,
-}
-
-impl Handle {
- /// Creates an image [`Handle`] pointing to the image of the given path.
- pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle {
- Self::from_data(Data::Path(path.into()))
- }
-
- /// Creates an image [`Handle`] containing the image data directly.
- ///
- /// This is useful if you already have your image loaded in-memory, maybe
- /// because you downloaded or generated it procedurally.
- pub fn from_memory(bytes: Vec<u8>) -> Handle {
- Self::from_data(Data::Bytes(bytes))
- }
-
- fn from_data(data: Data) -> Handle {
- let mut hasher = Hasher::default();
- data.hash(&mut hasher);
-
- Handle {
- id: hasher.finish(),
- data: Arc::new(data),
- }
- }
-
- /// Returns the unique identifier of the [`Handle`].
- pub fn id(&self) -> u64 {
- self.id
- }
-
- /// Returns a reference to the image [`Data`].
- pub fn data(&self) -> &Data {
- &self.data
- }
-}
-
-impl From<String> for Handle {
- fn from(path: String) -> Handle {
- Handle::from_path(path)
- }
-}
-
-impl From<&str> for Handle {
- fn from(path: &str) -> Handle {
- Handle::from_path(path)
- }
-}
-
-/// The data of an [`Image`].
-#[derive(Clone, Hash)]
-pub enum Data {
- /// A remote image
- Path(PathBuf),
-
- /// In-memory data
- Bytes(Vec<u8>),
-}
-
-impl std::fmt::Debug for Data {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Data::Path(path) => write!(f, "Path({:?})", path),
- Data::Bytes(_) => write!(f, "Bytes(...)"),
- }
- }
-}
diff --git a/web/src/widget/progress_bar.rs b/web/src/widget/progress_bar.rs
deleted file mode 100644
index 01f412f8..00000000
--- a/web/src/widget/progress_bar.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-//! Provide progress feedback to your users.
-use crate::{bumpalo, css, Bus, Css, Element, Length, Widget};
-
-pub use iced_style::progress_bar::{Style, StyleSheet};
-
-use std::ops::RangeInclusive;
-
-/// A bar that displays progress.
-///
-/// # Example
-/// ```
-/// use iced_web::ProgressBar;
-///
-/// let value = 50.0;
-///
-/// ProgressBar::new(0.0..=100.0, value);
-/// ```
-///
-/// ![Progress bar](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png)
-#[allow(missing_debug_implementations)]
-pub struct ProgressBar<'a> {
- range: RangeInclusive<f32>,
- value: f32,
- width: Length,
- height: Option<Length>,
- style: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a> ProgressBar<'a> {
- /// Creates a new [`ProgressBar`].
- ///
- /// It expects:
- /// * an inclusive range of possible values
- /// * the current value of the [`ProgressBar`]
- pub fn new(range: RangeInclusive<f32>, value: f32) -> Self {
- ProgressBar {
- value: value.max(*range.start()).min(*range.end()),
- range,
- width: Length::Fill,
- height: None,
- style: Default::default(),
- }
- }
-
- /// Sets the width of the [`ProgressBar`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`ProgressBar`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = Some(height);
- self
- }
-
- /// Sets the style of the [`ProgressBar`].
- pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self {
- self.style = style.into();
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for ProgressBar<'a> {
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- _bus: &Bus<Message>,
- _style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- let (range_start, range_end) = self.range.clone().into_inner();
- let amount_filled =
- (self.value - range_start) / (range_end - range_start).max(1.0);
-
- let style = self.style.style();
-
- let bar = div(bump)
- .attr(
- "style",
- bumpalo::format!(
- in bump,
- "width: {}%; height: 100%; background: {}",
- amount_filled * 100.0,
- css::background(style.bar)
- )
- .into_bump_str(),
- )
- .finish();
-
- let node = div(bump).attr(
- "style",
- bumpalo::format!(
- in bump,
- "width: {}; height: {}; background: {}; border-radius: {}px; overflow: hidden;",
- css::length(self.width),
- css::length(self.height.unwrap_or(Length::Units(30))),
- css::background(style.background),
- style.border_radius
- )
- .into_bump_str(),
- ).children(vec![bar]);
-
- node.finish()
- }
-}
-
-impl<'a, Message> From<ProgressBar<'a>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(container: ProgressBar<'a>) -> Element<'a, Message> {
- Element::new(container)
- }
-}
diff --git a/web/src/widget/radio.rs b/web/src/widget/radio.rs
deleted file mode 100644
index 03b2922b..00000000
--- a/web/src/widget/radio.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-//! Create choices using radio buttons.
-use crate::{Bus, Css, Element, Widget};
-
-pub use iced_style::radio::{Style, StyleSheet};
-
-use dodrio::bumpalo;
-
-/// A circular button representing a choice.
-///
-/// # Example
-/// ```
-/// # use iced_web::Radio;
-///
-/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
-/// pub enum Choice {
-/// A,
-/// B,
-/// }
-///
-/// #[derive(Debug, Clone, Copy)]
-/// pub enum Message {
-/// RadioSelected(Choice),
-/// }
-///
-/// let selected_choice = Some(Choice::A);
-///
-/// Radio::new(Choice::A, "This is A", selected_choice, Message::RadioSelected);
-///
-/// Radio::new(Choice::B, "This is B", selected_choice, Message::RadioSelected);
-/// ```
-///
-/// ![Radio buttons drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/radio.png?raw=true)
-#[allow(missing_debug_implementations)]
-pub struct Radio<'a, Message> {
- is_selected: bool,
- on_click: Message,
- label: String,
- id: Option<String>,
- name: Option<String>,
- #[allow(dead_code)]
- style_sheet: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, Message> Radio<'a, Message> {
- /// Creates a new [`Radio`] button.
- ///
- /// It expects:
- /// * the value related to the [`Radio`] button
- /// * the label of the [`Radio`] button
- /// * 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`.
- pub fn new<F, V>(
- value: V,
- label: impl Into<String>,
- selected: Option<V>,
- f: F,
- ) -> Self
- where
- V: Eq + Copy,
- F: 'static + Fn(V) -> Message,
- {
- Radio {
- is_selected: Some(value) == selected,
- on_click: f(value),
- label: label.into(),
- id: None,
- name: None,
- style_sheet: Default::default(),
- }
- }
-
- /// Sets the style of the [`Radio`] button.
- pub fn style(
- mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
- ) -> Self {
- self.style_sheet = style_sheet.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<'a, Message> Widget<Message> for Radio<'a, Message>
-where
- Message: 'static + Clone,
-{
- 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 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
- .attr("style", "display: block; font-size: 20px")
- .children(vec![
- input
- .attr("type", "radio")
- .attr("style", "margin-right: 10px")
- .bool_attr("checked", self.is_selected)
- .on("click", move |_root, _vdom, _event| {
- event_bus.publish(on_click.clone());
- })
- .finish(),
- text(radio_label),
- ])
- .finish()
- }
-}
-
-impl<'a, Message> From<Radio<'a, Message>> for Element<'a, Message>
-where
- Message: 'static + Clone,
-{
- fn from(radio: Radio<'a, Message>) -> Element<'a, Message> {
- Element::new(radio)
- }
-}
diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs
deleted file mode 100644
index 13eab27d..00000000
--- a/web/src/widget/row.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-use crate::css;
-use crate::{Alignment, Bus, Css, Element, Length, Padding, Widget};
-
-use dodrio::bumpalo;
-use std::u32;
-
-/// A container that distributes its contents horizontally.
-///
-/// A [`Row`] will try to fill the horizontal space of its container.
-#[allow(missing_debug_implementations)]
-pub struct Row<'a, Message> {
- spacing: u16,
- padding: Padding,
- width: Length,
- height: Length,
- max_width: u32,
- max_height: u32,
- align_items: Alignment,
- children: Vec<Element<'a, Message>>,
-}
-
-impl<'a, Message> Row<'a, Message> {
- /// Creates an empty [`Row`].
- pub fn new() -> Self {
- Self::with_children(Vec::new())
- }
-
- /// Creates a [`Row`] with the given elements.
- pub fn with_children(children: Vec<Element<'a, Message>>) -> Self {
- Row {
- spacing: 0,
- padding: Padding::ZERO,
- width: Length::Fill,
- height: Length::Shrink,
- max_width: u32::MAX,
- max_height: u32::MAX,
- align_items: Alignment::Start,
- children,
- }
- }
-
- /// Sets the horizontal spacing _between_ elements.
- ///
- /// Custom margins per element do not exist in Iced. You should use this
- /// method instead! While less flexible, it helps you keep spacing between
- /// elements consistent.
- pub fn spacing(mut self, units: u16) -> Self {
- self.spacing = units;
- self
- }
-
- /// 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`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Row`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the maximum width of the [`Row`].
- pub fn max_width(mut self, max_width: u32) -> Self {
- self.max_width = max_width;
- self
- }
-
- /// Sets the maximum height of the [`Row`].
- 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`] .
- pub fn align_items(mut self, align: Alignment) -> Self {
- self.align_items = align;
- self
- }
-
- /// Adds an [`Element`] to the [`Row`].
- pub fn push<E>(mut self, child: E) -> Self
- where
- E: Into<Element<'a, Message>>,
- {
- self.children.push(child.into());
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for Row<'a, Message> {
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- publish: &Bus<Message>,
- style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- let children: Vec<_> = self
- .children
- .iter()
- .map(|element| element.widget.node(bump, publish, style_sheet))
- .collect();
-
- let row_class = style_sheet.insert(bump, css::Rule::Row);
-
- let spacing_class =
- style_sheet.insert(bump, css::Rule::Spacing(self.spacing));
-
- // TODO: Complete styling
- div(bump)
- .attr(
- "class",
- bumpalo::format!(in bump, "{} {}", row_class, spacing_class)
- .into_bump_str(),
- )
- .attr("style", bumpalo::format!(
- in bump,
- "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::alignment(self.align_items)
- ).into_bump_str()
- )
- .children(children)
- .finish()
- }
-}
-
-impl<'a, Message> From<Row<'a, Message>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(column: Row<'a, Message>) -> Element<'a, Message> {
- Element::new(column)
- }
-}
diff --git a/web/src/widget/scrollable.rs b/web/src/widget/scrollable.rs
deleted file mode 100644
index 22cb61be..00000000
--- a/web/src/widget/scrollable.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-//! Navigate an endless amount of content with a scrollbar.
-use crate::bumpalo;
-use crate::css;
-use crate::{Alignment, Bus, Column, Css, Element, Length, Padding, Widget};
-
-pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
-
-/// A widget that can vertically display an infinite amount of content with a
-/// scrollbar.
-#[allow(missing_debug_implementations)]
-pub struct Scrollable<'a, Message> {
- width: Length,
- height: Length,
- max_height: u32,
- content: Column<'a, Message>,
- #[allow(dead_code)]
- style_sheet: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, Message> Scrollable<'a, Message> {
- /// Creates a new [`Scrollable`] with the given [`State`].
- pub fn new(_state: &'a mut State) -> Self {
- use std::u32;
-
- Scrollable {
- width: Length::Fill,
- height: Length::Shrink,
- max_height: u32::MAX,
- content: Column::new(),
- style_sheet: Default::default(),
- }
- }
-
- /// Sets the vertical spacing _between_ elements.
- ///
- /// Custom margins per element do not exist in Iced. You should use this
- /// method instead! While less flexible, it helps you keep spacing between
- /// elements consistent.
- pub fn spacing(mut self, units: u16) -> Self {
- self.content = self.content.spacing(units);
- self
- }
-
- /// 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`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Scrollable`].
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the maximum width of the [`Scrollable`].
- 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.
- 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`] .
- pub fn align_items(mut self, align_items: Alignment) -> Self {
- self.content = self.content.align_items(align_items);
- self
- }
-
- /// Sets the style of the [`Scrollable`] .
- pub fn style(
- mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
- ) -> Self {
- self.style_sheet = style_sheet.into();
- self
- }
-
- /// Adds an element to the [`Scrollable`].
- pub fn push<E>(mut self, child: E) -> Self
- where
- E: Into<Element<'a, Message>>,
- {
- self.content = self.content.push(child);
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for Scrollable<'a, 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::*;
-
- let width = css::length(self.width);
- let height = css::length(self.height);
-
- // TODO: Scrollbar styling
-
- let node = div(bump)
- .attr(
- "style",
- bumpalo::format!(
- in bump,
- "width: {}; height: {}; max-height: {}px; overflow: auto",
- width,
- height,
- self.max_height
- )
- .into_bump_str(),
- )
- .children(vec![self.content.node(bump, bus, style_sheet)]);
-
- node.finish()
- }
-}
-
-impl<'a, Message> From<Scrollable<'a, Message>> for Element<'a, Message>
-where
- Message: 'static,
-{
- fn from(scrollable: Scrollable<'a, Message>) -> Element<'a, Message> {
- Element::new(scrollable)
- }
-}
-
-/// The local state of a [`Scrollable`].
-#[derive(Debug, Clone, Copy, Default)]
-pub struct State;
-
-impl State {
- /// Creates a new [`State`] with the scrollbar located at the top.
- pub fn new() -> Self {
- State::default()
- }
-}
diff --git a/web/src/widget/slider.rs b/web/src/widget/slider.rs
deleted file mode 100644
index 8cbf5bd0..00000000
--- a/web/src/widget/slider.rs
+++ /dev/null
@@ -1,183 +0,0 @@
-//! Display an interactive selector of a single value from a range of values.
-//!
-//! A [`Slider`] has some local [`State`].
-use crate::{Bus, Css, Element, Length, Widget};
-
-pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
-
-use dodrio::bumpalo;
-use std::{ops::RangeInclusive, rc::Rc};
-
-/// An horizontal bar and a handle that selects a single value from a range of
-/// values.
-///
-/// A [`Slider`] will try to fill the horizontal space of its container.
-///
-/// The [`Slider`] range of numeric values is generic and its step size defaults
-/// to 1 unit.
-///
-/// # Example
-/// ```
-/// # use iced_web::{slider, Slider};
-/// #
-/// pub enum Message {
-/// SliderChanged(f32),
-/// }
-///
-/// let state = &mut slider::State::new();
-/// let value = 50.0;
-///
-/// Slider::new(state, 0.0..=100.0, value, Message::SliderChanged);
-/// ```
-///
-/// ![Slider drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/slider.png?raw=true)
-#[allow(missing_debug_implementations)]
-pub struct Slider<'a, T, Message> {
- _state: &'a mut State,
- range: RangeInclusive<T>,
- step: T,
- value: T,
- on_change: Rc<Box<dyn Fn(T) -> Message>>,
- #[allow(dead_code)]
- width: Length,
- #[allow(dead_code)]
- style_sheet: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, T, Message> Slider<'a, T, Message>
-where
- T: Copy + From<u8> + std::cmp::PartialOrd,
-{
- /// Creates a new [`Slider`].
- ///
- /// It expects:
- /// * the local [`State`] of the [`Slider`]
- /// * an inclusive range of possible values
- /// * the current value of the [`Slider`]
- /// * a function that will be called when the [`Slider`] is dragged.
- /// It receives the new value of the [`Slider`] and must produce a
- /// `Message`.
- pub fn new<F>(
- state: &'a mut State,
- range: RangeInclusive<T>,
- value: T,
- on_change: F,
- ) -> Self
- where
- 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,
- range,
- step: T::from(1),
- on_change: Rc::new(Box::new(on_change)),
- width: Length::Fill,
- style_sheet: Default::default(),
- }
- }
-
- /// Sets the width of the [`Slider`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the style of the [`Slider`].
- pub fn style(
- mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
- ) -> Self {
- self.style_sheet = style_sheet.into();
- self
- }
-
- /// Sets the step size of the [`Slider`].
- pub fn step(mut self, step: T) -> Self {
- self.step = step;
- self
- }
-}
-
-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>(
- &self,
- bump: &'b bumpalo::Bump,
- bus: &Bus<Message>,
- _style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
- use wasm_bindgen::JsCast;
-
- let (start, end) = self.range.clone().into_inner();
-
- 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: Styling
- input(bump)
- .attr("type", "range")
- .attr("step", step.into_bump_str())
- .attr("min", min.into_bump_str())
- .attr("max", max.into_bump_str())
- .attr("value", value.into_bump_str())
- .attr("style", "width: 100%")
- .on("input", move |_root, _vdom, event| {
- let slider = match event.target().and_then(|t| {
- t.dyn_into::<web_sys::HtmlInputElement>().ok()
- }) {
- None => return,
- Some(slider) => slider,
- };
-
- 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, 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, T, Message>) -> Element<'a, Message> {
- Element::new(slider)
- }
-}
-
-/// The local state of a [`Slider`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
-pub struct State;
-
-impl State {
- /// Creates a new [`State`].
- pub fn new() -> Self {
- Self
- }
-}
diff --git a/web/src/widget/space.rs b/web/src/widget/space.rs
deleted file mode 100644
index a8571fdb..00000000
--- a/web/src/widget/space.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use crate::{css, Bus, Css, Element, Length, Widget};
-use dodrio::bumpalo;
-
-/// An amount of empty space.
-///
-/// It can be useful if you want to fill some space with nothing.
-#[derive(Debug)]
-pub struct Space {
- width: Length,
- height: Length,
-}
-
-impl Space {
- /// Creates an amount of empty [`Space`] with the given width and height.
- pub fn new(width: Length, height: Length) -> Self {
- Space { width, height }
- }
-
- /// Creates an amount of horizontal [`Space`].
- pub fn with_width(width: Length) -> Self {
- Space {
- width,
- height: Length::Shrink,
- }
- }
-
- /// Creates an amount of vertical [`Space`].
- pub fn with_height(height: Length) -> Self {
- Space {
- width: Length::Shrink,
- height,
- }
- }
-}
-
-impl<'a, Message> Widget<Message> for Space {
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- _publish: &Bus<Message>,
- _css: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- let width = css::length(self.width);
- let height = css::length(self.height);
-
- let style = bumpalo::format!(
- in bump,
- "width: {}; height: {};",
- width,
- height
- );
-
- div(bump).attr("style", style.into_bump_str()).finish()
- }
-}
-
-impl<'a, Message> From<Space> for Element<'a, Message> {
- fn from(space: Space) -> Element<'a, Message> {
- Element::new(space)
- }
-}
diff --git a/web/src/widget/text.rs b/web/src/widget/text.rs
deleted file mode 100644
index 53d57bfd..00000000
--- a/web/src/widget/text.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-use crate::alignment;
-use crate::css;
-use crate::{Bus, Color, Css, Element, Font, Length, Widget};
-use dodrio::bumpalo;
-
-/// A paragraph of text.
-///
-/// # Example
-///
-/// ```
-/// # use iced_web::Text;
-///
-/// Text::new("I <3 iced!")
-/// .size(40);
-/// ```
-#[derive(Debug, Clone)]
-pub struct Text {
- content: String,
- size: Option<u16>,
- color: Option<Color>,
- font: Font,
- width: Length,
- height: Length,
- horizontal_alignment: alignment::Horizontal,
- vertical_alignment: alignment::Vertical,
-}
-
-impl Text {
- /// Create a new fragment of [`Text`] with the given contents.
- pub fn new<T: Into<String>>(label: T) -> Self {
- Text {
- content: label.into(),
- size: None,
- color: None,
- font: Font::Default,
- width: Length::Shrink,
- height: Length::Shrink,
- horizontal_alignment: alignment::Horizontal::Left,
- vertical_alignment: alignment::Vertical::Top,
- }
- }
-
- /// Sets the size of the [`Text`].
- pub fn size(mut self, size: u16) -> Self {
- self.size = Some(size);
- self
- }
-
- /// Sets the [`Color`] of the [`Text`].
- pub fn color<C: Into<Color>>(mut self, color: C) -> Self {
- self.color = Some(color.into());
- self
- }
-
- /// Sets the [`Font`] of the [`Text`].
- pub fn font(mut self, font: Font) -> Self {
- self.font = font;
- self
- }
-
- /// Sets the width of the [`Text`] boundaries.
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Text`] boundaries.
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Sets the [`HorizontalAlignment`] of the [`Text`].
- pub fn horizontal_alignment(
- mut self,
- alignment: alignment::Horizontal,
- ) -> Self {
- self.horizontal_alignment = alignment;
- self
- }
-
- /// Sets the [`VerticalAlignment`] of the [`Text`].
- pub fn vertical_alignment(
- mut self,
- alignment: alignment::Vertical,
- ) -> Self {
- self.vertical_alignment = alignment;
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for Text {
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- _publish: &Bus<Message>,
- _style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
-
- let content = {
- use dodrio::bumpalo::collections::String;
-
- String::from_str_in(&self.content, bump)
- };
-
- let color = self
- .color
- .map(css::color)
- .unwrap_or(String::from("inherit"));
-
- let width = css::length(self.width);
- let height = css::length(self.height);
-
- let text_align = match self.horizontal_alignment {
- alignment::Horizontal::Left => "left",
- alignment::Horizontal::Center => "center",
- alignment::Horizontal::Right => "right",
- };
-
- let style = bumpalo::format!(
- in bump,
- "width: {}; height: {}; font-size: {}px; color: {}; \
- text-align: {}; font-family: {}",
- width,
- height,
- self.size.unwrap_or(20),
- color,
- text_align,
- match self.font {
- Font::Default => "inherit",
- Font::External { name, .. } => name,
- }
- );
-
- // TODO: Complete styling
- p(bump)
- .attr("style", style.into_bump_str())
- .children(vec![text(content.into_bump_str())])
- .finish()
- }
-}
-
-impl<'a, Message> From<Text> for Element<'a, Message> {
- fn from(text: Text) -> Element<'a, Message> {
- Element::new(text)
- }
-}
diff --git a/web/src/widget/text_input.rs b/web/src/widget/text_input.rs
deleted file mode 100644
index c5874485..00000000
--- a/web/src/widget/text_input.rs
+++ /dev/null
@@ -1,234 +0,0 @@
-//! Display fields that can be filled with text.
-//!
-//! A [`TextInput`] has some local [`State`].
-use crate::{bumpalo, css, Bus, Css, Element, Length, Padding, Widget};
-
-pub use iced_style::text_input::{Style, StyleSheet};
-
-use std::{rc::Rc, u32};
-
-/// A field that can be filled with text.
-///
-/// # Example
-/// ```
-/// # use iced_web::{text_input, TextInput};
-/// #
-/// enum Message {
-/// TextInputChanged(String),
-/// }
-///
-/// let mut state = text_input::State::new();
-/// let value = "Some text";
-///
-/// let input = TextInput::new(
-/// &mut state,
-/// "This is the placeholder...",
-/// value,
-/// Message::TextInputChanged,
-/// );
-/// ```
-#[allow(missing_debug_implementations)]
-pub struct TextInput<'a, Message> {
- _state: &'a mut State,
- placeholder: String,
- value: String,
- is_secure: bool,
- width: Length,
- max_width: u32,
- padding: Padding,
- size: Option<u16>,
- on_change: Rc<Box<dyn Fn(String) -> Message>>,
- on_submit: Option<Message>,
- style_sheet: Box<dyn StyleSheet + 'a>,
-}
-
-impl<'a, Message> TextInput<'a, Message> {
- /// Creates a new [`TextInput`].
- ///
- /// It expects:
- /// - some [`State`]
- /// - a placeholder
- /// - the current value
- /// - a function that produces a message when the [`TextInput`] changes
- pub fn new<F>(
- state: &'a mut State,
- placeholder: &str,
- value: &str,
- on_change: F,
- ) -> Self
- where
- F: 'static + Fn(String) -> Message,
- {
- Self {
- _state: state,
- placeholder: String::from(placeholder),
- value: String::from(value),
- is_secure: false,
- width: Length::Fill,
- max_width: u32::MAX,
- padding: Padding::ZERO,
- size: None,
- on_change: Rc::new(Box::new(on_change)),
- on_submit: None,
- style_sheet: Default::default(),
- }
- }
-
- /// Converts the [`TextInput`] into a secure password input.
- pub fn password(mut self) -> Self {
- self.is_secure = true;
- self
- }
-
- /// Sets the width of the [`TextInput`].
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the maximum width of the [`TextInput`].
- pub fn max_width(mut self, max_width: u32) -> Self {
- self.max_width = max_width;
- self
- }
-
- /// 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`].
- pub fn size(mut self, size: u16) -> Self {
- self.size = Some(size);
- self
- }
-
- /// Sets the message that should be produced when the [`TextInput`] is
- /// focused and the enter key is pressed.
- pub fn on_submit(mut self, message: Message) -> Self {
- self.on_submit = Some(message);
- self
- }
-
- /// Sets the style of the [`TextInput`].
- pub fn style(
- mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
- ) -> Self {
- self.style_sheet = style_sheet.into();
- self
- }
-}
-
-impl<'a, Message> Widget<Message> for TextInput<'a, Message>
-where
- Message: 'static + Clone,
-{
- fn node<'b>(
- &self,
- bump: &'b bumpalo::Bump,
- bus: &Bus<Message>,
- _style_sheet: &mut Css<'b>,
- ) -> dodrio::Node<'b> {
- use dodrio::builder::*;
- use wasm_bindgen::JsCast;
-
- 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();
- let input_event_bus = bus.clone();
- let submit_event_bus = bus.clone();
- let style = self.style_sheet.active();
-
- input(bump)
- .attr(
- "style",
- bumpalo::format!(
- in bump,
- "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,
- css::color(style.border_color),
- style.border_radius,
- css::color(self.style_sheet.value_color())
- )
- .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()
- }) {
- None => return,
- Some(text_input) => text_input,
- };
-
- input_event_bus.publish(on_change(text_input.value()));
- })
- .on("keypress", move |_root, _vdom, event| {
- if let Some(on_submit) = on_submit.clone() {
- let event =
- event.unchecked_into::<web_sys::KeyboardEvent>();
-
- match event.key_code() {
- 13 => {
- submit_event_bus.publish(on_submit);
- }
- _ => {}
- }
- }
- })
- .finish()
- }
-}
-
-impl<'a, Message> From<TextInput<'a, Message>> for Element<'a, Message>
-where
- Message: 'static + Clone,
-{
- fn from(text_input: TextInput<'a, Message>) -> Element<'a, Message> {
- Element::new(text_input)
- }
-}
-
-/// The state of a [`TextInput`].
-#[derive(Debug, Clone, Copy, Default)]
-pub struct State;
-
-impl State {
- /// Creates a new [`State`], representing an unfocused [`TextInput`].
- pub fn new() -> Self {
- Self::default()
- }
-
- /// Creates a new [`State`], representing a focused [`TextInput`].
- 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
deleted file mode 100644
index 0a198079..00000000
--- a/web/src/widget/toggler.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-//! 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)
- }
-}