diff options
author | 2019-09-14 20:54:50 +0200 | |
---|---|---|
committer | 2019-09-14 20:54:50 +0200 | |
commit | 27ac85a9d98474904c422a891e54888376dec00a (patch) | |
tree | e268525f5bdb3e9631ba1156aaa6b02561dd03d4 /web | |
parent | a97401aed2a173260a4abfdb65a77975ce6c0f01 (diff) | |
download | iced-27ac85a9d98474904c422a891e54888376dec00a.tar.gz iced-27ac85a9d98474904c422a891e54888376dec00a.tar.bz2 iced-27ac85a9d98474904c422a891e54888376dec00a.zip |
Draft web runtime and widgets
Diffstat (limited to 'web')
-rw-r--r-- | web/Cargo.toml | 1 | ||||
-rw-r--r-- | web/examples/tour/Cargo.toml | 1 | ||||
-rw-r--r-- | web/examples/tour/src/lib.rs | 27 | ||||
-rw-r--r-- | web/examples/tour/src/tour.rs | 43 | ||||
-rw-r--r-- | web/src/color.rs | 16 | ||||
-rw-r--r-- | web/src/element.rs | 47 | ||||
-rw-r--r-- | web/src/lib.rs | 27 | ||||
-rw-r--r-- | web/src/widget.rs | 20 | ||||
-rw-r--r-- | web/src/widget/button.rs | 16 | ||||
-rw-r--r-- | web/src/widget/checkbox.rs | 14 | ||||
-rw-r--r-- | web/src/widget/column.rs | 48 | ||||
-rw-r--r-- | web/src/widget/image.rs | 11 | ||||
-rw-r--r-- | web/src/widget/radio.rs | 14 | ||||
-rw-r--r-- | web/src/widget/row.rs | 36 | ||||
-rw-r--r-- | web/src/widget/slider.rs | 16 | ||||
-rw-r--r-- | web/src/widget/text.rs | 13 |
16 files changed, 321 insertions, 29 deletions
diff --git a/web/Cargo.toml b/web/Cargo.toml index acc5f18b..6d8c37b1 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -17,6 +17,7 @@ maintenance = { status = "actively-developed" } [dependencies] iced = { version = "0.1.0-alpha", path = ".." } dodrio = "0.1.0" +futures = "0.1" [dependencies.web-sys] version = "0.3.27" diff --git a/web/examples/tour/Cargo.toml b/web/examples/tour/Cargo.toml index 15f38fa7..c2db46ec 100644 --- a/web/examples/tour/Cargo.toml +++ b/web/examples/tour/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["cdylib"] [dependencies] iced_web = { path = "../.." } wasm-bindgen = "0.2.50" +futures = "0.1" log = "0.4" console_error_panic_hook = "0.1.6" console_log = "0.1.2" diff --git a/web/examples/tour/src/lib.rs b/web/examples/tour/src/lib.rs index e747a193..30855e8b 100644 --- a/web/examples/tour/src/lib.rs +++ b/web/examples/tour/src/lib.rs @@ -1,8 +1,35 @@ +use futures::{future, Future}; +use iced_web::UserInterface; use wasm_bindgen::prelude::*; +mod tour; + +use tour::Tour; + #[wasm_bindgen(start)] pub fn run() { console_error_panic_hook::set_once(); console_log::init_with_level(log::Level::Trace) .expect("Initialize logging"); + + let tour = Tour::new(); + + tour.run(); +} + +impl iced_web::UserInterface for Tour { + type Message = tour::Message; + + fn update( + &mut self, + message: tour::Message, + ) -> Box<dyn Future<Item = tour::Message, Error = ()>> { + self.update(message); + + Box::new(future::err(())) + } + + fn view(&mut self) -> iced_web::Element<tour::Message> { + self.view() + } } diff --git a/web/examples/tour/src/tour.rs b/web/examples/tour/src/tour.rs index d0be99b0..6c24622e 100644 --- a/web/examples/tour/src/tour.rs +++ b/web/examples/tour/src/tour.rs @@ -1,12 +1,8 @@ -use super::widget::{ - button, slider, Button, Checkbox, Column, Element, Image, Radio, Row, - Slider, Text, +use iced_web::{ + button, slider, text::HorizontalAlignment, Align, Button, Checkbox, Color, + Column, Element, Image, Radio, Row, Slider, Text, }; -use ggez::graphics::{self, Color, FilterMode, BLACK}; -use ggez::Context; -use iced::{text::HorizontalAlignment, Align}; - pub struct Tour { steps: Steps, back_button: button::State, @@ -15,9 +11,9 @@ pub struct Tour { } impl Tour { - pub fn new(context: &mut Context) -> Tour { + pub fn new() -> Tour { Tour { - steps: Steps::new(context), + steps: Steps::new(), back_button: button::State::new(), next_button: button::State::new(), debug: false, @@ -72,7 +68,7 @@ impl Tour { .into(); if self.debug { - element.explain(BLACK) + element.explain(Color::BLACK) } else { element } @@ -92,7 +88,7 @@ struct Steps { } impl Steps { - fn new(context: &mut Context) -> Steps { + fn new() -> Steps { Steps { steps: vec![ Step::Welcome, @@ -109,19 +105,10 @@ impl Steps { size_slider: slider::State::new(), size: 30, color_sliders: [slider::State::new(); 3], - color: BLACK, + color: Color::BLACK, }, Step::Radio { selection: None }, Step::Image { - ferris: { - let mut image = - graphics::Image::new(context, "/ferris.png") - .expect("Load ferris image"); - - image.set_filter(FilterMode::Linear); - - image - }, width: 300, slider: slider::State::new(), }, @@ -183,7 +170,6 @@ enum Step { selection: Option<Language>, }, Image { - ferris: graphics::Image, width: u16, slider: slider::State, }, @@ -273,11 +259,7 @@ impl<'a> Step { color_sliders, color, } => Self::text(size_slider, *size, color_sliders, *color).into(), - Step::Image { - ferris, - width, - slider, - } => Self::image(ferris.clone(), *width, slider).into(), + Step::Image { width, slider } => Self::image(*width, slider).into(), Step::RowsAndColumns { layout, spacing_slider, @@ -489,13 +471,16 @@ impl<'a> Step { } fn image( - ferris: graphics::Image, width: u16, slider: &'a mut slider::State, ) -> Column<'a, StepMessage> { Self::container("Image") .push(Text::new("An image that tries to keep its aspect ratio.")) - .push(Image::new(ferris).width(width).align_self(Align::Center)) + .push( + Image::new("resources/ferris.png") + .width(width) + .align_self(Align::Center), + ) .push(Slider::new( slider, 100.0..=500.0, diff --git a/web/src/color.rs b/web/src/color.rs new file mode 100644 index 00000000..2624c3c9 --- /dev/null +++ b/web/src/color.rs @@ -0,0 +1,16 @@ +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Color { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} + +impl Color { + pub const BLACK: Color = Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 1.0, + }; +} diff --git a/web/src/element.rs b/web/src/element.rs new file mode 100644 index 00000000..c0c9ce5d --- /dev/null +++ b/web/src/element.rs @@ -0,0 +1,47 @@ +use crate::{Color, Widget}; + +pub struct Element<'a, Message> { + pub(crate) widget: Box<dyn Widget<Message> + 'a>, +} + +impl<'a, Message> Element<'a, Message> { + pub fn new(widget: impl Widget<Message> + 'a) -> Self { + Self { + widget: Box::new(widget), + } + } + + pub fn explain(self, color: Color) -> Element<'a, Message> { + self + } + + pub fn map<F, B>(self, f: F) -> Element<'a, B> + where + Message: 'static, + B: 'static, + F: 'static + Fn(Message) -> B, + { + Element { + widget: Box::new(Map::new(self.widget, f)), + } + } +} + +struct Map<'a, A, B> { + widget: Box<dyn Widget<A> + 'a>, + mapper: Box<dyn Fn(A) -> B>, +} + +impl<'a, A, B> Map<'a, A, B> { + pub fn new<F>(widget: Box<dyn Widget<A> + 'a>, mapper: F) -> Map<'a, A, B> + where + F: 'static + Fn(A) -> B, + { + Map { + widget, + mapper: Box::new(mapper), + } + } +} + +impl<'a, A, B> Widget<B> for Map<'a, A, B> {} diff --git a/web/src/lib.rs b/web/src/lib.rs index 8b137891..187e8ad9 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -1 +1,28 @@ +use futures::Future; +mod color; +mod element; +mod widget; + +pub use color::Color; +pub use element::Element; +pub use iced::Align; +pub use widget::*; + +pub trait UserInterface { + type Message; + + fn update( + &mut self, + message: Self::Message, + ) -> Box<dyn Future<Item = Self::Message, Error = ()>>; + + fn view(&mut self) -> Element<Self::Message>; + + fn run(mut self) + where + Self: Sized, + { + let element = self.view(); + } +} diff --git a/web/src/widget.rs b/web/src/widget.rs new file mode 100644 index 00000000..5cb89a60 --- /dev/null +++ b/web/src/widget.rs @@ -0,0 +1,20 @@ +pub mod button; +pub mod slider; +pub mod text; + +mod checkbox; +mod column; +mod image; +mod radio; +mod row; + +pub use button::Button; +pub use checkbox::Checkbox; +pub use column::Column; +pub use image::Image; +pub use radio::Radio; +pub use row::Row; +pub use slider::Slider; +pub use text::Text; + +pub trait Widget<Message> {} diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs new file mode 100644 index 00000000..1f117d82 --- /dev/null +++ b/web/src/widget/button.rs @@ -0,0 +1,16 @@ +use crate::{Element, Widget}; + +pub use iced::button::{Class, State}; + +pub type Button<'a, Message> = iced::Button<'a, Message>; + +impl<'a, Message> Widget<Message> for Button<'a, Message> {} + +impl<'a, Message> From<Button<'a, Message>> for Element<'a, Message> +where + Message: 'static, +{ + 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 new file mode 100644 index 00000000..a231d801 --- /dev/null +++ b/web/src/widget/checkbox.rs @@ -0,0 +1,14 @@ +use crate::{Color, Element, Widget}; + +pub type Checkbox<Message> = iced::Checkbox<Color, Message>; + +impl<Message> Widget<Message> for Checkbox<Message> {} + +impl<'a, Message> From<Checkbox<Message>> for Element<'a, Message> +where + Message: 'static, +{ + fn from(checkbox: Checkbox<Message>) -> Element<'a, Message> { + Element::new(checkbox) + } +} diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs new file mode 100644 index 00000000..84068ce6 --- /dev/null +++ b/web/src/widget/column.rs @@ -0,0 +1,48 @@ +use crate::{Align, Element, Widget}; + +pub struct Column<'a, Message> { + children: Vec<Element<'a, Message>>, +} + +impl<'a, Message> Column<'a, Message> { + pub fn new() -> Self { + Self { + children: Vec::new(), + } + } + + pub fn spacing(self, _spacing: u16) -> Self { + self + } + + pub fn padding(self, _padding: u16) -> Self { + self + } + + pub fn max_width(self, _max_width: u16) -> Self { + self + } + + pub fn align_items(self, _align: Align) -> Self { + self + } + + pub fn push<E>(mut self, element: E) -> Self + where + E: Into<Element<'a, Message>>, + { + self.children.push(element.into()); + self + } +} + +impl<'a, Message> Widget<Message> for Column<'a, Message> {} + +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/image.rs b/web/src/widget/image.rs new file mode 100644 index 00000000..ac144fd8 --- /dev/null +++ b/web/src/widget/image.rs @@ -0,0 +1,11 @@ +use crate::{Element, Widget}; + +pub type Image<'a> = iced::Image<&'a str>; + +impl<'a, Message> Widget<Message> for Image<'a> {} + +impl<'a, Message> From<Image<'a>> for Element<'a, Message> { + fn from(image: Image<'a>) -> Element<'a, Message> { + Element::new(image) + } +} diff --git a/web/src/widget/radio.rs b/web/src/widget/radio.rs new file mode 100644 index 00000000..0c28b46f --- /dev/null +++ b/web/src/widget/radio.rs @@ -0,0 +1,14 @@ +use crate::{Color, Element, Widget}; + +pub type Radio<Message> = iced::Radio<Color, Message>; + +impl<Message> Widget<Message> for Radio<Message> {} + +impl<'a, Message> From<Radio<Message>> for Element<'a, Message> +where + Message: 'static, +{ + fn from(radio: Radio<Message>) -> Element<'a, Message> { + Element::new(radio) + } +} diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs new file mode 100644 index 00000000..fc474ec3 --- /dev/null +++ b/web/src/widget/row.rs @@ -0,0 +1,36 @@ +use crate::{Element, Widget}; + +pub struct Row<'a, Message> { + children: Vec<Element<'a, Message>>, +} + +impl<'a, Message> Row<'a, Message> { + pub fn new() -> Self { + Self { + children: Vec::new(), + } + } + + pub fn spacing(self, _spacing: u16) -> Self { + self + } + + pub fn push<E>(mut self, element: E) -> Self + where + E: Into<Element<'a, Message>>, + { + self.children.push(element.into()); + self + } +} + +impl<'a, Message> Widget<Message> for Row<'a, Message> {} + +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/slider.rs b/web/src/widget/slider.rs new file mode 100644 index 00000000..9c83befb --- /dev/null +++ b/web/src/widget/slider.rs @@ -0,0 +1,16 @@ +use crate::{Element, Widget}; + +pub use iced::slider::State; + +pub type Slider<'a, Message> = iced::Slider<'a, Message>; + +impl<'a, Message> Widget<Message> for Slider<'a, Message> {} + +impl<'a, Message> From<Slider<'a, Message>> for Element<'a, Message> +where + Message: 'static, +{ + fn from(slider: Slider<'a, Message>) -> Element<'a, Message> { + Element::new(slider) + } +} diff --git a/web/src/widget/text.rs b/web/src/widget/text.rs new file mode 100644 index 00000000..0c1f75b6 --- /dev/null +++ b/web/src/widget/text.rs @@ -0,0 +1,13 @@ +use crate::{Color, Element, Widget}; + +pub use iced::text::HorizontalAlignment; + +pub type Text = iced::Text<Color>; + +impl<'a, Message> Widget<Message> for Text {} + +impl<'a, Message> From<Text> for Element<'a, Message> { + fn from(text: Text) -> Element<'a, Message> { + Element::new(text) + } +} |