diff options
author | 2019-09-15 17:43:15 +0200 | |
---|---|---|
committer | 2019-09-15 17:43:15 +0200 | |
commit | 8834772fa70850559f7bd82cc8432394e3fd9db7 (patch) | |
tree | 84522dca905c8a3803dc728726975c7095c06557 /web | |
parent | 27ac85a9d98474904c422a891e54888376dec00a (diff) | |
download | iced-8834772fa70850559f7bd82cc8432394e3fd9db7.tar.gz iced-8834772fa70850559f7bd82cc8432394e3fd9db7.tar.bz2 iced-8834772fa70850559f7bd82cc8432394e3fd9db7.zip |
Draft widget nodes and wire interaction
Diffstat (limited to 'web')
-rw-r--r-- | web/src/bus.rs | 40 | ||||
-rw-r--r-- | web/src/element.rs | 25 | ||||
-rw-r--r-- | web/src/lib.rs | 54 | ||||
-rw-r--r-- | web/src/widget.rs | 15 | ||||
-rw-r--r-- | web/src/widget/button.rs | 34 | ||||
-rw-r--r-- | web/src/widget/column.rs | 22 | ||||
-rw-r--r-- | web/src/widget/row.rs | 22 | ||||
-rw-r--r-- | web/src/widget/text.rs | 21 |
8 files changed, 215 insertions, 18 deletions
diff --git a/web/src/bus.rs b/web/src/bus.rs new file mode 100644 index 00000000..d76466f5 --- /dev/null +++ b/web/src/bus.rs @@ -0,0 +1,40 @@ +use crate::Application; + +use std::rc::Rc; + +#[derive(Clone)] +pub struct Bus<Message> { + publish: Rc<Box<dyn Fn(Message, &mut dyn dodrio::RootRender)>>, +} + +impl<Message> Bus<Message> +where + Message: 'static, +{ + pub fn new() -> Self { + Self { + publish: Rc::new(Box::new(|message, root| { + let app = root.unwrap_mut::<Application<Message>>(); + + app.update(message) + })), + } + } + + pub fn publish(&self, message: Message, root: &mut dyn dodrio::RootRender) { + (self.publish)(message, root); + } + + pub fn map<B>(&self, mapper: Rc<Box<dyn Fn(B) -> Message>>) -> Bus<B> + where + B: 'static, + { + let publish = self.publish.clone(); + + Bus { + publish: Rc::new(Box::new(move |message, root| { + publish(mapper(message), root) + })), + } + } +} diff --git a/web/src/element.rs b/web/src/element.rs index c0c9ce5d..8270d8db 100644 --- a/web/src/element.rs +++ b/web/src/element.rs @@ -1,4 +1,7 @@ -use crate::{Color, Widget}; +use crate::{Bus, Color, Widget}; + +use dodrio::bumpalo; +use std::rc::Rc; pub struct Element<'a, Message> { pub(crate) widget: Box<dyn Widget<Message> + 'a>, @@ -11,7 +14,7 @@ impl<'a, Message> Element<'a, Message> { } } - pub fn explain(self, color: Color) -> Element<'a, Message> { + pub fn explain(self, _color: Color) -> Element<'a, Message> { self } @@ -29,7 +32,7 @@ impl<'a, Message> Element<'a, Message> { struct Map<'a, A, B> { widget: Box<dyn Widget<A> + 'a>, - mapper: Box<dyn Fn(A) -> B>, + mapper: Rc<Box<dyn Fn(A) -> B>>, } impl<'a, A, B> Map<'a, A, B> { @@ -39,9 +42,21 @@ impl<'a, A, B> Map<'a, A, B> { { Map { widget, - mapper: Box::new(mapper), + mapper: Rc::new(Box::new(mapper)), } } } -impl<'a, A, B> Widget<B> for Map<'a, A, B> {} +impl<'a, A, B> Widget<B> for Map<'a, A, B> +where + A: 'static, + B: 'static, +{ + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + bus: &Bus<B>, + ) -> dodrio::Node<'b> { + self.widget.node(bump, &bus.map(self.mapper.clone())) + } +} diff --git a/web/src/lib.rs b/web/src/lib.rs index 187e8ad9..3173e736 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -1,9 +1,13 @@ +use dodrio::bumpalo; use futures::Future; +use std::cell::RefCell; +mod bus; mod color; mod element; mod widget; +pub use bus::Bus; pub use color::Color; pub use element::Element; pub use iced::Align; @@ -19,10 +23,54 @@ pub trait UserInterface { fn view(&mut self) -> Element<Self::Message>; - fn run(mut self) + fn run(self) where - Self: Sized, + Self: 'static + Sized, { - let element = self.view(); + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + let body = document.body().unwrap(); + + let app = Application::new(self); + + let vdom = dodrio::Vdom::new(&body, app); + vdom.forget(); + } +} + +struct Application<Message> { + ui: RefCell<Box<dyn UserInterface<Message = Message>>>, +} + +impl<Message> Application<Message> { + fn new(ui: impl UserInterface<Message = Message> + 'static) -> Self { + Self { + ui: RefCell::new(Box::new(ui)), + } + } + + fn update(&mut self, message: Message) { + let mut ui = self.ui.borrow_mut(); + + // TODO: Resolve futures and publish resulting messages + let _ = ui.update(message); + } +} + +impl<Message> dodrio::Render for Application<Message> +where + Message: 'static, +{ + fn render<'a, 'bump>( + &'a self, + bump: &'bump bumpalo::Bump, + ) -> dodrio::Node<'bump> + where + 'a: 'bump, + { + let mut ui = self.ui.borrow_mut(); + let element = ui.view(); + + element.widget.node(bump, &Bus::new()) } } diff --git a/web/src/widget.rs b/web/src/widget.rs index 5cb89a60..7af592e1 100644 --- a/web/src/widget.rs +++ b/web/src/widget.rs @@ -1,3 +1,6 @@ +use crate::Bus; +use dodrio::bumpalo; + pub mod button; pub mod slider; pub mod text; @@ -17,4 +20,14 @@ pub use row::Row; pub use slider::Slider; pub use text::Text; -pub trait Widget<Message> {} +pub trait Widget<Message> { + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + _bus: &Bus<Message>, + ) -> dodrio::Node<'b> { + use dodrio::builder::*; + + div(bump).children(vec![text("WIP")]).finish() + } +} diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs index 1f117d82..8ccda107 100644 --- a/web/src/widget/button.rs +++ b/web/src/widget/button.rs @@ -1,14 +1,42 @@ -use crate::{Element, Widget}; +use crate::{Bus, Element, Widget}; +use dodrio::bumpalo; 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> Widget<Message> for Button<'a, Message> +where + Message: 'static + Copy, +{ + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + bus: &Bus<Message>, + ) -> dodrio::Node<'b> { + use dodrio::builder::*; + + let label = bumpalo::format!(in bump, "{}", self.label); + + let mut node = button(bump).children(vec![text(label.into_bump_str())]); + + if let Some(on_press) = self.on_press { + let event_bus = bus.clone(); + + node = node.on("click", move |root, vdom, _event| { + event_bus.publish(on_press, root); + + vdom.schedule_render(); + }); + } + + node.finish() + } +} impl<'a, Message> From<Button<'a, Message>> for Element<'a, Message> where - Message: 'static, + Message: 'static + Copy, { fn from(button: Button<'a, Message>) -> Element<'a, Message> { Element::new(button) diff --git a/web/src/widget/column.rs b/web/src/widget/column.rs index 84068ce6..b3131f5e 100644 --- a/web/src/widget/column.rs +++ b/web/src/widget/column.rs @@ -1,4 +1,6 @@ -use crate::{Align, Element, Widget}; +use crate::{Align, Bus, Element, Widget}; + +use dodrio::bumpalo; pub struct Column<'a, Message> { children: Vec<Element<'a, Message>>, @@ -36,7 +38,23 @@ impl<'a, Message> Column<'a, Message> { } } -impl<'a, Message> Widget<Message> for Column<'a, Message> {} +impl<'a, Message> Widget<Message> for Column<'a, Message> { + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + publish: &Bus<Message>, + ) -> dodrio::Node<'b> { + use dodrio::builder::*; + + let children: Vec<_> = self + .children + .iter() + .map(|element| element.widget.node(bump, publish)) + .collect(); + + div(bump).children(children).finish() + } +} impl<'a, Message> From<Column<'a, Message>> for Element<'a, Message> where diff --git a/web/src/widget/row.rs b/web/src/widget/row.rs index fc474ec3..40fc68e3 100644 --- a/web/src/widget/row.rs +++ b/web/src/widget/row.rs @@ -1,4 +1,6 @@ -use crate::{Element, Widget}; +use crate::{Bus, Element, Widget}; + +use dodrio::bumpalo; pub struct Row<'a, Message> { children: Vec<Element<'a, Message>>, @@ -24,7 +26,23 @@ impl<'a, Message> Row<'a, Message> { } } -impl<'a, Message> Widget<Message> for Row<'a, Message> {} +impl<'a, Message> Widget<Message> for Row<'a, Message> { + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + publish: &Bus<Message>, + ) -> dodrio::Node<'b> { + use dodrio::builder::*; + + let children: Vec<_> = self + .children + .iter() + .map(|element| element.widget.node(bump, publish)) + .collect(); + + div(bump).children(children).finish() + } +} impl<'a, Message> From<Row<'a, Message>> for Element<'a, Message> where diff --git a/web/src/widget/text.rs b/web/src/widget/text.rs index 0c1f75b6..b8fe9565 100644 --- a/web/src/widget/text.rs +++ b/web/src/widget/text.rs @@ -1,10 +1,27 @@ -use crate::{Color, Element, Widget}; +use crate::{Bus, Color, Element, Widget}; +use dodrio::bumpalo; pub use iced::text::HorizontalAlignment; pub type Text = iced::Text<Color>; -impl<'a, Message> Widget<Message> for Text {} +impl<'a, Message> Widget<Message> for Text { + fn node<'b>( + &self, + bump: &'b bumpalo::Bump, + _publish: &Bus<Message>, + ) -> dodrio::Node<'b> { + use dodrio::builder::*; + + let content = bumpalo::format!(in bump, "{}", self.content); + let size = bumpalo::format!(in bump, "font-size: {}px", self.size.unwrap_or(20)); + + p(bump) + .attr("style", size.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> { |