diff options
author | 2019-09-19 15:01:12 +0200 | |
---|---|---|
committer | 2019-09-19 15:01:12 +0200 | |
commit | f9de39ddaa3020a9585b1648afb0ead45dfd7aa9 (patch) | |
tree | 04289787e353b4b059354d22ce53f2b79464431c | |
parent | dd093c79d7da84675be648c7df2ebfc85b5039f2 (diff) | |
download | iced-f9de39ddaa3020a9585b1648afb0ead45dfd7aa9.tar.gz iced-f9de39ddaa3020a9585b1648afb0ead45dfd7aa9.tar.bz2 iced-f9de39ddaa3020a9585b1648afb0ead45dfd7aa9.zip |
Unify `web` and `ggez` tour examples :tada:
-rw-r--r-- | .github/workflows/integration.yml | 2 | ||||
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | examples/tour/Cargo.toml | 29 | ||||
-rw-r--r-- | examples/tour/index.html (renamed from web/examples/tour/index.html) | 6 | ||||
-rw-r--r-- | examples/tour/resources/Roboto-LICENSE (renamed from examples/resources/Roboto-LICENSE) | 0 | ||||
-rw-r--r-- | examples/tour/resources/Roboto-Regular.ttf (renamed from examples/resources/Roboto-Regular.ttf) | bin | 171272 -> 171272 bytes | |||
-rw-r--r-- | examples/tour/resources/ferris.png (renamed from examples/resources/ferris.png) | bin | 33061 -> 33061 bytes | |||
-rw-r--r-- | examples/tour/resources/ui.png (renamed from examples/resources/ui.png) | bin | 16691 -> 16691 bytes | |||
-rw-r--r-- | examples/tour/src/iced_ggez.rs | 6 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/main.rs (renamed from examples/tour/main.rs) | 28 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer.rs (renamed from examples/tour/renderer.rs) | 20 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/button.rs (renamed from examples/tour/renderer/button.rs) | 0 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/checkbox.rs (renamed from examples/tour/renderer/checkbox.rs) | 0 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/debugger.rs (renamed from examples/tour/renderer/debugger.rs) | 10 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/image.rs (renamed from examples/tour/renderer/image.rs) | 45 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/radio.rs (renamed from examples/tour/renderer/radio.rs) | 0 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/slider.rs (renamed from examples/tour/renderer/slider.rs) | 0 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/renderer/text.rs (renamed from examples/tour/renderer/text.rs) | 10 | ||||
-rw-r--r-- | examples/tour/src/iced_ggez/widget.rs (renamed from examples/tour/widget.rs) | 6 | ||||
-rw-r--r-- | examples/tour/src/lib.rs | 11 | ||||
-rw-r--r-- | examples/tour/src/tour.rs (renamed from web/examples/tour/src/tour.rs) | 2 | ||||
-rw-r--r-- | examples/tour/src/web.rs (renamed from web/examples/tour/src/lib.rs) | 4 | ||||
-rw-r--r-- | examples/tour/src/widget.rs | 5 | ||||
-rw-r--r-- | examples/tour/tour.rs | 578 | ||||
-rw-r--r-- | src/color.rs (renamed from web/src/color.rs) | 3 | ||||
-rw-r--r-- | src/element.rs | 9 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/user_interface.rs | 10 | ||||
-rw-r--r-- | src/widget.rs | 2 | ||||
-rw-r--r-- | src/widget/button.rs | 2 | ||||
-rw-r--r-- | src/widget/checkbox.rs | 2 | ||||
-rw-r--r-- | src/widget/column.rs | 2 | ||||
-rw-r--r-- | src/widget/image.rs | 4 | ||||
-rw-r--r-- | src/widget/radio.rs | 2 | ||||
-rw-r--r-- | src/widget/row.rs | 2 | ||||
-rw-r--r-- | src/widget/slider.rs | 2 | ||||
-rw-r--r-- | src/widget/text.rs | 2 | ||||
-rw-r--r-- | web/examples/tour/Cargo.toml | 17 | ||||
l--------- | web/examples/tour/resources/ferris.png | 1 | ||||
-rw-r--r-- | web/src/lib.rs | 4 |
40 files changed, 166 insertions, 669 deletions
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f574e930..884a4e9e 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -18,4 +18,4 @@ jobs: sudo apt-get install -y libasound2-dev libudev-dev - uses: actions/checkout@master - name: Run tests - run: cargo test --verbose --all-features + run: cargo test --verbose --all --all-features @@ -24,13 +24,8 @@ twox-hash = "1.5" # Enable to obtain conversion traits winit = { version = "0.20.0-alpha3", optional = true } -[dev-dependencies] -# A personal `ggez` fork that introduces a `FontCache` type to measure text -# efficiently and fixes HiDPI issues. -ggez = { version = "0.5", git = "https://github.com/hecrj/ggez.git" } - [workspace] members = [ "web", - "web/examples/tour", + "examples/tour", ] diff --git a/examples/tour/Cargo.toml b/examples/tour/Cargo.toml new file mode 100644 index 00000000..08d108d9 --- /dev/null +++ b/examples/tour/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "iced_tour" +version = "0.0.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +description = "Tour example for Iced" +license = "MIT" +repository = "https://github.com/hecrj/iced" +edition = "2018" +publish = false + +[[bin]] +name = "ggez" +path = "src/iced_ggez/main.rs" + +[dependencies] +futures-preview = "=0.3.0-alpha.18" + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +iced = { path = "../.." } +# A personal `ggez` fork that introduces a `FontCache` type to measure text +# efficiently and fixes HiDPI issues. +ggez = { version = "0.5", git = "https://github.com/hecrj/ggez.git" } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +iced_web = { path = "../../web" } +wasm-bindgen = "0.2.50" +log = "0.4" +console_error_panic_hook = "0.1.6" +console_log = "0.1.2" diff --git a/web/examples/tour/index.html b/examples/tour/index.html index 527cc54c..b17ac4a2 100644 --- a/web/examples/tour/index.html +++ b/examples/tour/index.html @@ -2,12 +2,12 @@ <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> - <title>Web Tour - Iced</title> + <title>Tour - Iced</title> </head> <body> <script type="module"> - import init from "./pkg/iced_web_tour.js"; - init("./pkg/iced_web_tour_bg.wasm"); + import init from "./pkg/iced_tour.js"; + init("./pkg/iced_tour_bg.wasm"); </script> </body> </html> diff --git a/examples/resources/Roboto-LICENSE b/examples/tour/resources/Roboto-LICENSE index 75b52484..75b52484 100644 --- a/examples/resources/Roboto-LICENSE +++ b/examples/tour/resources/Roboto-LICENSE diff --git a/examples/resources/Roboto-Regular.ttf b/examples/tour/resources/Roboto-Regular.ttf Binary files differindex 2b6392ff..2b6392ff 100644 --- a/examples/resources/Roboto-Regular.ttf +++ b/examples/tour/resources/Roboto-Regular.ttf diff --git a/examples/resources/ferris.png b/examples/tour/resources/ferris.png Binary files differindex ebce1a14..ebce1a14 100644 --- a/examples/resources/ferris.png +++ b/examples/tour/resources/ferris.png diff --git a/examples/resources/ui.png b/examples/tour/resources/ui.png Binary files differindex 4fd3beb3..4fd3beb3 100644 --- a/examples/resources/ui.png +++ b/examples/tour/resources/ui.png diff --git a/examples/tour/src/iced_ggez.rs b/examples/tour/src/iced_ggez.rs new file mode 100644 index 00000000..4a9c0ef4 --- /dev/null +++ b/examples/tour/src/iced_ggez.rs @@ -0,0 +1,6 @@ +mod renderer; +mod widget; + +pub use renderer::Cache as ImageCache; +pub use renderer::Renderer; +pub use widget::*; diff --git a/examples/tour/main.rs b/examples/tour/src/iced_ggez/main.rs index 571bc2e2..a8cf09e5 100644 --- a/examples/tour/main.rs +++ b/examples/tour/src/iced_ggez/main.rs @@ -1,10 +1,4 @@ -mod renderer; -mod tour; -mod widget; - -use renderer::Renderer; -use tour::Tour; -use widget::Column; +use iced_tour::{iced_ggez, Tour}; use ggez; use ggez::event; @@ -26,10 +20,7 @@ pub fn main() -> ggez::GameResult { filesystem::mount( context, - std::path::Path::new(&format!( - "{}/examples/resources", - env!("CARGO_MANIFEST_DIR") - )), + std::path::Path::new(env!("CARGO_MANIFEST_DIR")), true, ); @@ -41,6 +32,7 @@ pub fn main() -> ggez::GameResult { struct Game { spritesheet: graphics::Image, font: graphics::Font, + images: iced_ggez::ImageCache, tour: Tour, events: Vec<iced::Event>, @@ -52,9 +44,12 @@ impl Game { graphics::set_default_filter(context, graphics::FilterMode::Nearest); Ok(Game { - spritesheet: graphics::Image::new(context, "/ui.png").unwrap(), - font: graphics::Font::new(context, "/Roboto-Regular.ttf").unwrap(), - tour: Tour::new(context), + spritesheet: graphics::Image::new(context, "/resources/ui.png") + .unwrap(), + font: graphics::Font::new(context, "/resources/Roboto-Regular.ttf") + .unwrap(), + images: iced_ggez::ImageCache::new(), + tour: Tour::new(), events: Vec::new(), cache: Some(iced::Cache::default()), @@ -136,7 +131,7 @@ impl event::EventHandler for Game { let (messages, cursor) = { let view = self.tour.view(); - let content = Column::new() + let content = iced_ggez::Column::new() .width(screen.w as u16) .height(screen.h as u16) .padding(20) @@ -144,8 +139,9 @@ impl event::EventHandler for Game { .justify_content(iced::Justify::Center) .push(view); - let renderer = &mut Renderer::new( + let renderer = &mut iced_ggez::Renderer::new( context, + &mut self.images, self.spritesheet.clone(), self.font, ); diff --git a/examples/tour/renderer.rs b/examples/tour/src/iced_ggez/renderer.rs index 8746dd96..e3181eaa 100644 --- a/examples/tour/renderer.rs +++ b/examples/tour/src/iced_ggez/renderer.rs @@ -11,8 +11,11 @@ use ggez::graphics::{ }; use ggez::Context; +pub use image::Cache; + pub struct Renderer<'a> { pub context: &'a mut Context, + pub images: &'a mut image::Cache, pub sprites: SpriteBatch, pub spritesheet: Image, pub font: Font, @@ -20,14 +23,16 @@ pub struct Renderer<'a> { debug_mesh: Option<MeshBuilder>, } -impl Renderer<'_> { +impl<'a> Renderer<'a> { pub fn new( - context: &mut Context, + context: &'a mut Context, + images: &'a mut image::Cache, spritesheet: Image, font: Font, - ) -> Renderer { + ) -> Renderer<'a> { Renderer { context, + images, sprites: SpriteBatch::new(spritesheet.clone()), spritesheet, font, @@ -61,3 +66,12 @@ impl Renderer<'_> { } } } + +pub fn into_color(color: iced::Color) -> graphics::Color { + graphics::Color { + r: color.r, + g: color.g, + b: color.b, + a: color.a, + } +} diff --git a/examples/tour/renderer/button.rs b/examples/tour/src/iced_ggez/renderer/button.rs index 486e07ed..486e07ed 100644 --- a/examples/tour/renderer/button.rs +++ b/examples/tour/src/iced_ggez/renderer/button.rs diff --git a/examples/tour/renderer/checkbox.rs b/examples/tour/src/iced_ggez/renderer/checkbox.rs index 20a91be5..20a91be5 100644 --- a/examples/tour/renderer/checkbox.rs +++ b/examples/tour/src/iced_ggez/renderer/checkbox.rs diff --git a/examples/tour/renderer/debugger.rs b/examples/tour/src/iced_ggez/renderer/debugger.rs index 98124795..c6727881 100644 --- a/examples/tour/renderer/debugger.rs +++ b/examples/tour/src/iced_ggez/renderer/debugger.rs @@ -1,10 +1,10 @@ -use super::Renderer; -use ggez::graphics::{Color, DrawMode, MeshBuilder, Rect}; +use super::{into_color, Renderer}; +use ggez::graphics::{DrawMode, MeshBuilder, Rect}; impl iced::renderer::Debugger for Renderer<'_> { - type Color = Color; + type Color = iced::Color; - fn explain(&mut self, layout: &iced::Layout<'_>, color: Color) { + fn explain(&mut self, layout: &iced::Layout<'_>, color: iced::Color) { let bounds = layout.bounds(); let mut debug_mesh = @@ -18,7 +18,7 @@ impl iced::renderer::Debugger for Renderer<'_> { w: bounds.width, h: bounds.height, }, - color, + into_color(color), ); self.debug_mesh = Some(debug_mesh); diff --git a/examples/tour/renderer/image.rs b/examples/tour/src/iced_ggez/renderer/image.rs index c3ead5c9..17c6a56e 100644 --- a/examples/tour/renderer/image.rs +++ b/examples/tour/src/iced_ggez/renderer/image.rs @@ -3,15 +3,48 @@ use super::Renderer; use ggez::{graphics, nalgebra}; use iced::image; -impl image::Renderer<graphics::Image> for Renderer<'_> { +pub struct Cache { + images: std::collections::HashMap<String, graphics::Image>, +} + +impl Cache { + pub fn new() -> Self { + Self { + images: std::collections::HashMap::new(), + } + } + + fn get<'a>( + &mut self, + name: &'a str, + context: &mut ggez::Context, + ) -> graphics::Image { + if let Some(image) = self.images.get(name) { + return image.clone(); + } + + let mut image = graphics::Image::new(context, &format!("/{}", name)) + .expect("Load ferris image"); + + image.set_filter(graphics::FilterMode::Linear); + + self.images.insert(name.to_string(), image.clone()); + + image + } +} + +impl<'a> image::Renderer<&'a str> for Renderer<'_> { fn node( - &self, + &mut self, style: iced::Style, - image: &graphics::Image, + name: &&'a str, width: Option<u16>, height: Option<u16>, _source: Option<iced::Rectangle<u16>>, ) -> iced::Node { + let image = self.images.get(name, self.context); + let aspect_ratio = image.width() as f32 / image.height() as f32; let style = match (width, height) { @@ -30,15 +63,17 @@ impl image::Renderer<graphics::Image> for Renderer<'_> { fn draw( &mut self, - image: &graphics::Image, + name: &&'a str, bounds: iced::Rectangle, _source: Option<iced::Rectangle<u16>>, ) { + let image = self.images.get(name, self.context); + // We should probably use batches to draw images efficiently and keep // draw side-effect free, but this is good enough for the example. graphics::draw( self.context, - image, + &image, graphics::DrawParam::new() .dest(nalgebra::Point2::new(bounds.x, bounds.y)) .scale(nalgebra::Vector2::new( diff --git a/examples/tour/renderer/radio.rs b/examples/tour/src/iced_ggez/renderer/radio.rs index 0f7815d6..0f7815d6 100644 --- a/examples/tour/renderer/radio.rs +++ b/examples/tour/src/iced_ggez/renderer/radio.rs diff --git a/examples/tour/renderer/slider.rs b/examples/tour/src/iced_ggez/renderer/slider.rs index 146cee18..146cee18 100644 --- a/examples/tour/renderer/slider.rs +++ b/examples/tour/src/iced_ggez/renderer/slider.rs diff --git a/examples/tour/renderer/text.rs b/examples/tour/src/iced_ggez/renderer/text.rs index ecf1481e..b5010639 100644 --- a/examples/tour/renderer/text.rs +++ b/examples/tour/src/iced_ggez/renderer/text.rs @@ -1,11 +1,11 @@ -use super::Renderer; -use ggez::graphics::{self, mint, Align, Color, Scale, Text, TextFragment}; +use super::{into_color, Renderer}; +use ggez::graphics::{self, mint, Align, Scale, Text, TextFragment}; use iced::text; use std::cell::RefCell; use std::f32; -impl text::Renderer<Color> for Renderer<'_> { +impl text::Renderer<iced::Color> for Renderer<'_> { fn node( &self, style: iced::Style, @@ -80,7 +80,7 @@ impl text::Renderer<Color> for Renderer<'_> { bounds: iced::Rectangle, content: &str, size: Option<u16>, - color: Option<Color>, + color: Option<iced::Color>, horizontal_alignment: text::HorizontalAlignment, _vertical_alignment: text::VerticalAlignment, ) { @@ -112,7 +112,7 @@ impl text::Renderer<Color> for Renderer<'_> { x: bounds.x, y: bounds.y, }, - color.or(Some(graphics::BLACK)), + color.or(Some(iced::Color::BLACK)).map(into_color), ); } } diff --git a/examples/tour/widget.rs b/examples/tour/src/iced_ggez/widget.rs index 9a141c83..a365daca 100644 --- a/examples/tour/widget.rs +++ b/examples/tour/src/iced_ggez/widget.rs @@ -1,13 +1,11 @@ use super::Renderer; -use ggez::graphics::{self, Color}; - -pub use iced::{button, slider, Button, Slider}; +pub use iced::{button, slider, text, Align, Button, Color, Slider}; pub type Text = iced::Text<Color>; pub type Checkbox<Message> = iced::Checkbox<Color, Message>; pub type Radio<Message> = iced::Radio<Color, Message>; -pub type Image = iced::Image<graphics::Image>; +pub type Image<'a> = iced::Image<&'a str>; pub type Column<'a, Message> = iced::Column<'a, Message, Renderer<'a>>; pub type Row<'a, Message> = iced::Row<'a, Message, Renderer<'a>>; diff --git a/examples/tour/src/lib.rs b/examples/tour/src/lib.rs new file mode 100644 index 00000000..eb41fcd9 --- /dev/null +++ b/examples/tour/src/lib.rs @@ -0,0 +1,11 @@ +pub mod tour; + +pub use tour::{Message, Tour}; + +mod widget; + +#[cfg(target_arch = "wasm32")] +mod web; + +#[cfg(not(target_arch = "wasm32"))] +pub mod iced_ggez; diff --git a/web/examples/tour/src/tour.rs b/examples/tour/src/tour.rs index 9a60e092..4bd7c8a3 100644 --- a/web/examples/tour/src/tour.rs +++ b/examples/tour/src/tour.rs @@ -1,4 +1,4 @@ -use iced_web::{ +use crate::widget::{ button, slider, text::HorizontalAlignment, Align, Button, Checkbox, Color, Column, Element, Image, Radio, Row, Slider, Text, }; diff --git a/web/examples/tour/src/lib.rs b/examples/tour/src/web.rs index dbf04df8..a0a3060f 100644 --- a/web/examples/tour/src/lib.rs +++ b/examples/tour/src/web.rs @@ -2,9 +2,7 @@ use futures::Future; use iced_web::UserInterface; use wasm_bindgen::prelude::*; -mod tour; - -use tour::Tour; +use crate::tour::{self, Tour}; #[wasm_bindgen(start)] pub fn run() { diff --git a/examples/tour/src/widget.rs b/examples/tour/src/widget.rs new file mode 100644 index 00000000..9c2c4d5b --- /dev/null +++ b/examples/tour/src/widget.rs @@ -0,0 +1,5 @@ +#[cfg(target_arch = "wasm32")] +pub use iced_web::*; + +#[cfg(not(target_arch = "wasm32"))] +pub use crate::iced_ggez::*; diff --git a/examples/tour/tour.rs b/examples/tour/tour.rs deleted file mode 100644 index d0be99b0..00000000 --- a/examples/tour/tour.rs +++ /dev/null @@ -1,578 +0,0 @@ -use super::widget::{ - button, slider, Button, Checkbox, 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, - next_button: button::State, - debug: bool, -} - -impl Tour { - pub fn new(context: &mut Context) -> Tour { - Tour { - steps: Steps::new(context), - back_button: button::State::new(), - next_button: button::State::new(), - debug: false, - } - } - - pub fn update(&mut self, event: Message) { - match event { - Message::BackPressed => { - self.steps.go_back(); - } - Message::NextPressed => { - self.steps.advance(); - } - Message::StepMessage(step_msg) => { - self.steps.update(step_msg, &mut self.debug); - } - } - } - - pub fn view(&mut self) -> Element<Message> { - let Tour { - steps, - back_button, - next_button, - .. - } = self; - - let mut controls = Row::new(); - - if steps.has_previous() { - controls = controls.push( - Button::new(back_button, "Back") - .on_press(Message::BackPressed) - .class(button::Class::Secondary), - ); - } - - controls = controls.push(Column::new()); - - if steps.can_continue() { - controls = controls.push( - Button::new(next_button, "Next").on_press(Message::NextPressed), - ); - } - - let element: Element<_> = Column::new() - .max_width(500) - .spacing(20) - .push(steps.view(self.debug).map(Message::StepMessage)) - .push(controls) - .into(); - - if self.debug { - element.explain(BLACK) - } else { - element - } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum Message { - BackPressed, - NextPressed, - StepMessage(StepMessage), -} - -struct Steps { - steps: Vec<Step>, - current: usize, -} - -impl Steps { - fn new(context: &mut Context) -> Steps { - Steps { - steps: vec![ - Step::Welcome, - Step::Slider { - state: slider::State::new(), - value: 50, - }, - Step::RowsAndColumns { - layout: Layout::Row, - spacing_slider: slider::State::new(), - spacing: 20, - }, - Step::Text { - size_slider: slider::State::new(), - size: 30, - color_sliders: [slider::State::new(); 3], - 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(), - }, - Step::Debugger, - Step::End, - ], - current: 0, - } - } - - fn update(&mut self, msg: StepMessage, debug: &mut bool) { - self.steps[self.current].update(msg, debug); - } - - fn view(&mut self, debug: bool) -> Element<StepMessage> { - self.steps[self.current].view(debug) - } - - fn advance(&mut self) { - if self.can_continue() { - self.current += 1; - } - } - - fn go_back(&mut self) { - if self.has_previous() { - self.current -= 1; - } - } - - fn has_previous(&self) -> bool { - self.current > 0 - } - - fn can_continue(&self) -> bool { - self.current + 1 < self.steps.len() - && self.steps[self.current].can_continue() - } -} - -enum Step { - Welcome, - Slider { - state: slider::State, - value: u16, - }, - RowsAndColumns { - layout: Layout, - spacing_slider: slider::State, - spacing: u16, - }, - Text { - size_slider: slider::State, - size: u16, - color_sliders: [slider::State; 3], - color: Color, - }, - Radio { - selection: Option<Language>, - }, - Image { - ferris: graphics::Image, - width: u16, - slider: slider::State, - }, - Debugger, - End, -} - -#[derive(Debug, Clone, Copy)] -pub enum StepMessage { - SliderChanged(f32), - LayoutChanged(Layout), - SpacingChanged(f32), - TextSizeChanged(f32), - TextColorChanged(Color), - LanguageSelected(Language), - ImageWidthChanged(f32), - DebugToggled(bool), -} - -impl<'a> Step { - fn update(&mut self, msg: StepMessage, debug: &mut bool) { - match msg { - StepMessage::DebugToggled(value) => { - if let Step::Debugger = self { - *debug = value; - } - } - StepMessage::LanguageSelected(language) => { - if let Step::Radio { selection } = self { - *selection = Some(language); - } - } - StepMessage::SliderChanged(new_value) => { - if let Step::Slider { value, .. } = self { - *value = new_value.round() as u16; - } - } - StepMessage::TextSizeChanged(new_size) => { - if let Step::Text { size, .. } = self { - *size = new_size.round() as u16; - } - } - StepMessage::TextColorChanged(new_color) => { - if let Step::Text { color, .. } = self { - *color = new_color; - } - } - StepMessage::LayoutChanged(new_layout) => { - if let Step::RowsAndColumns { layout, .. } = self { - *layout = new_layout; - } - } - StepMessage::SpacingChanged(new_spacing) => { - if let Step::RowsAndColumns { spacing, .. } = self { - *spacing = new_spacing.round() as u16; - } - } - StepMessage::ImageWidthChanged(new_width) => { - if let Step::Image { width, .. } = self { - *width = new_width.round() as u16; - } - } - }; - } - - fn can_continue(&self) -> bool { - match self { - Step::Welcome => true, - Step::Radio { selection } => *selection == Some(Language::Rust), - Step::Slider { .. } => true, - Step::Text { .. } => true, - Step::Image { .. } => true, - Step::RowsAndColumns { .. } => true, - Step::Debugger => true, - Step::End => false, - } - } - - fn view(&mut self, debug: bool) -> Element<StepMessage> { - match self { - Step::Welcome => Self::welcome().into(), - Step::Radio { selection } => Self::radio(*selection).into(), - Step::Slider { state, value } => Self::slider(state, *value).into(), - Step::Text { - size_slider, - size, - 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::RowsAndColumns { - layout, - spacing_slider, - spacing, - } => { - Self::rows_and_columns(*layout, spacing_slider, *spacing).into() - } - Step::Debugger => Self::debugger(debug).into(), - Step::End => Self::end().into(), - } - } - - fn container(title: &str) -> Column<'a, StepMessage> { - Column::new() - .spacing(20) - .align_items(Align::Stretch) - .push(Text::new(title).size(50)) - } - - fn welcome() -> Column<'a, StepMessage> { - Self::container("Welcome!") - .push(Text::new( - "This a simple tour meant to showcase a bunch of widgets that \ - can be easily implemented on top of Iced.", - )) - .push(Text::new( - "Iced is a renderer-agnostic GUI library for Rust focused on \ - simplicity and type-safety. It is heavily inspired by Elm.", - )) - .push(Text::new( - "It was originally born as part of Coffee, an opinionated \ - 2D game engine for Rust.", - )) - .push(Text::new( - "Iced does not provide a built-in renderer. This example runs \ - on a fairly simple renderer built on top of ggez, another \ - game library.", - )) - .push(Text::new( - "You will need to interact with the UI in order to reach the \ - end!", - )) - } - - fn slider( - state: &'a mut slider::State, - value: u16, - ) -> Column<'a, StepMessage> { - Self::container("Slider") - .push(Text::new( - "A slider allows you to smoothly select a value from a range \ - of values.", - )) - .push(Text::new( - "The following slider lets you choose an integer from \ - 0 to 100:", - )) - .push(Slider::new( - state, - 0.0..=100.0, - value as f32, - StepMessage::SliderChanged, - )) - .push( - Text::new(&value.to_string()) - .horizontal_alignment(HorizontalAlignment::Center), - ) - } - - fn rows_and_columns( - layout: Layout, - spacing_slider: &'a mut slider::State, - spacing: u16, - ) -> Column<'a, StepMessage> { - let row_radio = Radio::new( - Layout::Row, - "Row", - Some(layout), - StepMessage::LayoutChanged, - ); - - let column_radio = Radio::new( - Layout::Column, - "Column", - Some(layout), - StepMessage::LayoutChanged, - ); - - let layout_section: Element<_> = match layout { - Layout::Row => Row::new() - .spacing(spacing) - .push(row_radio) - .push(column_radio) - .into(), - Layout::Column => Column::new() - .spacing(spacing) - .push(row_radio) - .push(column_radio) - .into(), - }; - - let spacing_section = Column::new() - .spacing(10) - .push(Slider::new( - spacing_slider, - 0.0..=80.0, - spacing as f32, - StepMessage::SpacingChanged, - )) - .push( - Text::new(&format!("{} px", spacing)) - .horizontal_alignment(HorizontalAlignment::Center), - ); - - Self::container("Rows and columns") - .spacing(spacing) - .push(Text::new( - "Iced uses a layout model based on flexbox to position UI \ - elements.", - )) - .push(Text::new( - "Rows and columns can be used to distribute content \ - horizontally or vertically, respectively.", - )) - .push(layout_section) - .push(Text::new( - "You can also easily change the spacing between elements:", - )) - .push(spacing_section) - } - - fn text( - size_slider: &'a mut slider::State, - size: u16, - color_sliders: &'a mut [slider::State; 3], - color: Color, - ) -> Column<'a, StepMessage> { - let size_section = Column::new() - .padding(20) - .spacing(20) - .push(Text::new("You can change its size:")) - .push( - Text::new(&format!("This text is {} pixels", size)).size(size), - ) - .push(Slider::new( - size_slider, - 10.0..=70.0, - size as f32, - StepMessage::TextSizeChanged, - )); - - let [red, green, blue] = color_sliders; - let color_section = Column::new() - .padding(20) - .spacing(20) - .push(Text::new("And its color:")) - .push(Text::new(&format!("{:?}", color)).color(color)) - .push( - Row::new() - .spacing(10) - .push(Slider::new(red, 0.0..=1.0, color.r, move |r| { - StepMessage::TextColorChanged(Color { r, ..color }) - })) - .push(Slider::new(green, 0.0..=1.0, color.g, move |g| { - StepMessage::TextColorChanged(Color { g, ..color }) - })) - .push(Slider::new(blue, 0.0..=1.0, color.b, move |b| { - StepMessage::TextColorChanged(Color { b, ..color }) - })), - ); - - Self::container("Text") - .push(Text::new( - "Text is probably the most essential widget for your UI. \ - It will try to adapt to the dimensions of its container.", - )) - .push(size_section) - .push(color_section) - } - - fn radio(selection: Option<Language>) -> Column<'a, StepMessage> { - let question = Column::new() - .padding(20) - .spacing(10) - .push(Text::new("Iced is written in...").size(24)) - .push(Language::all().iter().cloned().fold( - Column::new().padding(10).spacing(20), - |choices, language| { - choices.push(Radio::new( - language, - language.into(), - selection, - StepMessage::LanguageSelected, - )) - }, - )); - - Self::container("Radio button") - .push(Text::new( - "A radio button is normally used to represent a choice... \ - Surprise test!", - )) - .push(question) - .push(Text::new( - "Iced works very well with iterators! The list above is \ - basically created by folding a column over the different \ - choices, creating a radio button for each one of them!", - )) - } - - 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(Slider::new( - slider, - 100.0..=500.0, - width as f32, - StepMessage::ImageWidthChanged, - )) - .push( - Text::new(&format!("Width: {} px", width.to_string())) - .horizontal_alignment(HorizontalAlignment::Center), - ) - } - - fn debugger(debug: bool) -> Column<'a, StepMessage> { - Self::container("Debugger") - .push(Text::new( - "You can ask Iced to visually explain the layouting of the \ - different elements comprising your UI!", - )) - .push(Text::new( - "Give it a shot! Check the following checkbox to be able to \ - see element boundaries.", - )) - .push(Checkbox::new( - debug, - "Explain layout", - StepMessage::DebugToggled, - )) - .push(Text::new("Feel free to go back and take a look.")) - } - - fn end() -> Column<'a, StepMessage> { - Self::container("You reached the end!") - .push(Text::new( - "This tour will be updated as more features are added.", - )) - .push(Text::new("Make sure to keep an eye on it!")) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Language { - Rust, - Elm, - Ruby, - Haskell, - C, - Other, -} - -impl Language { - fn all() -> [Language; 6] { - [ - Language::C, - Language::Elm, - Language::Ruby, - Language::Haskell, - Language::Rust, - Language::Other, - ] - } -} - -impl From<Language> for &str { - fn from(language: Language) -> &'static str { - match language { - Language::Rust => "Rust", - Language::Elm => "Elm", - Language::Ruby => "Ruby", - Language::Haskell => "Haskell", - Language::C => "C", - Language::Other => "Other", - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Layout { - Row, - Column, -} diff --git a/web/src/color.rs b/src/color.rs index 2624c3c9..5cc3a084 100644 --- a/web/src/color.rs +++ b/src/color.rs @@ -1,4 +1,6 @@ +/// A color in the sRGB color space. #[derive(Debug, Clone, Copy, PartialEq)] +#[allow(missing_docs)] pub struct Color { pub r: f32, pub g: f32, @@ -7,6 +9,7 @@ pub struct Color { } impl Color { + /// The black color. pub const BLACK: Color = Color { r: 0.0, g: 0.0, diff --git a/src/element.rs b/src/element.rs index 70d06f42..c13bf4a0 100644 --- a/src/element.rs +++ b/src/element.rs @@ -223,7 +223,10 @@ impl<'a, Message, Renderer> Element<'a, Message, Renderer> { } } - pub(crate) fn compute_layout(&self, renderer: &Renderer) -> result::Layout { + pub(crate) fn compute_layout( + &self, + renderer: &mut Renderer, + ) -> result::Layout { let node = self.widget.node(renderer); node.0.compute_layout(geometry::Size::undefined()).unwrap() @@ -264,7 +267,7 @@ impl<'a, A, B, Renderer> Widget<B, Renderer> for Map<'a, A, B, Renderer> where A: Copy, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { self.widget.node(renderer) } @@ -337,7 +340,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> where Renderer: renderer::Debugger, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { self.element.widget.node(renderer) } @@ -200,6 +200,7 @@ pub mod input; pub mod renderer; pub mod widget; +mod color; mod element; mod event; mod hasher; @@ -215,6 +216,7 @@ mod vector; #[doc(no_inline)] pub use stretch::{geometry::Size, number::Number}; +pub use color::Color; pub use element::Element; pub use event::Event; pub use hasher::Hasher; diff --git a/src/user_interface.rs b/src/user_interface.rs index 2c7cbf82..6a69f81a 100644 --- a/src/user_interface.rs +++ b/src/user_interface.rs @@ -69,7 +69,7 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { /// let user_interface = UserInterface::build( /// counter.view(), /// cache, - /// &renderer, + /// &mut renderer, /// ); /// /// // Update and draw the user interface here... @@ -82,7 +82,7 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { pub fn build<E: Into<Element<'a, Message, Renderer>>>( root: E, cache: Cache, - renderer: &Renderer, + renderer: &mut Renderer, ) -> Self { let root = root.into(); @@ -153,7 +153,7 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { /// let mut user_interface = UserInterface::build( /// counter.view(), /// cache, - /// &renderer, + /// &mut renderer, /// ); /// /// // Update the user interface @@ -236,7 +236,7 @@ impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer> { /// let mut user_interface = UserInterface::build( /// counter.view(), /// cache, - /// &renderer, + /// &mut renderer, /// ); /// /// let messages = user_interface.update(events.drain(..)); @@ -302,7 +302,7 @@ impl Cache { Cache { hash: hasher.finish(), - layout: root.compute_layout(&()), + layout: root.compute_layout(&mut ()), cursor_position: Point::new(0.0, 0.0), } } diff --git a/src/widget.rs b/src/widget.rs index 30606934..45451f47 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -59,7 +59,7 @@ pub trait Widget<Message, Renderer>: std::fmt::Debug { /// [`Node`]: ../struct.Node.html /// [`Widget`]: trait.Widget.html /// [`Layout`]: ../struct.Layout.html - fn node(&self, renderer: &Renderer) -> Node; + fn node(&self, renderer: &mut Renderer) -> Node; /// Draws the [`Widget`] using the associated `Renderer`. /// diff --git a/src/widget/button.rs b/src/widget/button.rs index 6f5d9908..d2ea70e4 100644 --- a/src/widget/button.rs +++ b/src/widget/button.rs @@ -133,7 +133,7 @@ where Renderer: self::Renderer, Message: Copy + std::fmt::Debug, { - fn node(&self, _renderer: &Renderer) -> Node { + fn node(&self, _renderer: &mut Renderer) -> Node { Node::new(self.style.height(50)) } diff --git a/src/widget/checkbox.rs b/src/widget/checkbox.rs index 4ae167ad..6c13252d 100644 --- a/src/widget/checkbox.rs +++ b/src/widget/checkbox.rs @@ -98,7 +98,7 @@ where Color: 'static + Copy + std::fmt::Debug, Renderer: self::Renderer + text::Renderer<Color>, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { Row::<(), Renderer>::new() .spacing(15) .align_items(Align::Center) diff --git a/src/widget/column.rs b/src/widget/column.rs index ff754e98..831f5b8f 100644 --- a/src/widget/column.rs +++ b/src/widget/column.rs @@ -136,7 +136,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget<Message, Renderer> for Column<'a, Message, Renderer> { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { let mut children: Vec<Node> = self .children .iter() diff --git a/src/widget/image.rs b/src/widget/image.rs index 8c869ab8..1601234e 100644 --- a/src/widget/image.rs +++ b/src/widget/image.rs @@ -99,7 +99,7 @@ where Renderer: self::Renderer<I>, I: Clone, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { renderer.node( self.style, &self.image, @@ -144,7 +144,7 @@ pub trait Renderer<I> { /// [`Style`]: ../../struct.Style.html /// [`Image`]: struct.Image.html fn node( - &self, + &mut self, style: Style, image: &I, width: Option<u16>, diff --git a/src/widget/radio.rs b/src/widget/radio.rs index 27c0ff17..ba082ef5 100644 --- a/src/widget/radio.rs +++ b/src/widget/radio.rs @@ -111,7 +111,7 @@ where Renderer: self::Renderer + text::Renderer<Color>, Message: Copy + std::fmt::Debug, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { Row::<(), Renderer>::new() .spacing(15) .align_items(Align::Center) diff --git a/src/widget/row.rs b/src/widget/row.rs index 959528dc..181020e3 100644 --- a/src/widget/row.rs +++ b/src/widget/row.rs @@ -133,7 +133,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> { impl<'a, Message, Renderer> Widget<Message, Renderer> for Row<'a, Message, Renderer> { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { let mut children: Vec<Node> = self .children .iter() diff --git a/src/widget/slider.rs b/src/widget/slider.rs index 8a0cea01..fb6db8c9 100644 --- a/src/widget/slider.rs +++ b/src/widget/slider.rs @@ -107,7 +107,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message> where Renderer: self::Renderer, { - fn node(&self, _renderer: &Renderer) -> Node { + fn node(&self, _renderer: &mut Renderer) -> Node { Node::new(self.style.height(25)) } diff --git a/src/widget/text.rs b/src/widget/text.rs index b529cfd2..457a6814 100644 --- a/src/widget/text.rs +++ b/src/widget/text.rs @@ -113,7 +113,7 @@ where Color: Copy + std::fmt::Debug, Renderer: self::Renderer<Color>, { - fn node(&self, renderer: &Renderer) -> Node { + fn node(&self, renderer: &mut Renderer) -> Node { renderer.node(self.style, &self.content, self.size) } diff --git a/web/examples/tour/Cargo.toml b/web/examples/tour/Cargo.toml deleted file mode 100644 index 65a860e2..00000000 --- a/web/examples/tour/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "iced_web_tour" -version = "0.0.0" -authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] -edition = "2018" -publish = false - -[lib] -crate-type = ["cdylib"] - -[dependencies] -iced_web = { path = "../.." } -wasm-bindgen = "0.2.50" -futures-preview = "=0.3.0-alpha.18" -log = "0.4" -console_error_panic_hook = "0.1.6" -console_log = "0.1.2" diff --git a/web/examples/tour/resources/ferris.png b/web/examples/tour/resources/ferris.png deleted file mode 120000 index 9c4fb51c..00000000 --- a/web/examples/tour/resources/ferris.png +++ /dev/null @@ -1 +0,0 @@ -../../../../examples/resources/ferris.png
\ No newline at end of file diff --git a/web/src/lib.rs b/web/src/lib.rs index 5a0dd6f2..a6dc2b79 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -3,14 +3,12 @@ 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; +pub use iced::{Align, Color}; pub use widget::*; pub trait UserInterface { |