From f9de39ddaa3020a9585b1648afb0ead45dfd7aa9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 19 Sep 2019 15:01:12 +0200 Subject: Unify `web` and `ggez` tour examples :tada: --- examples/tour/src/iced_ggez/main.rs | 189 +++++++++++++++++++++++ examples/tour/src/iced_ggez/renderer.rs | 77 +++++++++ examples/tour/src/iced_ggez/renderer/button.rs | 145 +++++++++++++++++ examples/tour/src/iced_ggez/renderer/checkbox.rs | 64 ++++++++ examples/tour/src/iced_ggez/renderer/debugger.rs | 30 ++++ examples/tour/src/iced_ggez/renderer/image.rs | 86 +++++++++++ examples/tour/src/iced_ggez/renderer/radio.rs | 63 ++++++++ examples/tour/src/iced_ggez/renderer/slider.rs | 82 ++++++++++ examples/tour/src/iced_ggez/renderer/text.rs | 118 ++++++++++++++ examples/tour/src/iced_ggez/widget.rs | 12 ++ 10 files changed, 866 insertions(+) create mode 100644 examples/tour/src/iced_ggez/main.rs create mode 100644 examples/tour/src/iced_ggez/renderer.rs create mode 100644 examples/tour/src/iced_ggez/renderer/button.rs create mode 100644 examples/tour/src/iced_ggez/renderer/checkbox.rs create mode 100644 examples/tour/src/iced_ggez/renderer/debugger.rs create mode 100644 examples/tour/src/iced_ggez/renderer/image.rs create mode 100644 examples/tour/src/iced_ggez/renderer/radio.rs create mode 100644 examples/tour/src/iced_ggez/renderer/slider.rs create mode 100644 examples/tour/src/iced_ggez/renderer/text.rs create mode 100644 examples/tour/src/iced_ggez/widget.rs (limited to 'examples/tour/src/iced_ggez') diff --git a/examples/tour/src/iced_ggez/main.rs b/examples/tour/src/iced_ggez/main.rs new file mode 100644 index 00000000..a8cf09e5 --- /dev/null +++ b/examples/tour/src/iced_ggez/main.rs @@ -0,0 +1,189 @@ +use iced_tour::{iced_ggez, Tour}; + +use ggez; +use ggez::event; +use ggez::filesystem; +use ggez::graphics; +use ggez::input::mouse; + +pub fn main() -> ggez::GameResult { + let (context, event_loop) = { + &mut ggez::ContextBuilder::new("iced", "ggez") + .window_mode(ggez::conf::WindowMode { + width: 1280.0, + height: 1024.0, + resizable: true, + ..ggez::conf::WindowMode::default() + }) + .build()? + }; + + filesystem::mount( + context, + std::path::Path::new(env!("CARGO_MANIFEST_DIR")), + true, + ); + + let state = &mut Game::new(context)?; + + event::run(context, event_loop, state) +} + +struct Game { + spritesheet: graphics::Image, + font: graphics::Font, + images: iced_ggez::ImageCache, + tour: Tour, + + events: Vec, + cache: Option, +} + +impl Game { + fn new(context: &mut ggez::Context) -> ggez::GameResult { + graphics::set_default_filter(context, graphics::FilterMode::Nearest); + + Ok(Game { + 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()), + }) + } +} + +impl event::EventHandler for Game { + fn update(&mut self, _ctx: &mut ggez::Context) -> ggez::GameResult { + Ok(()) + } + + fn mouse_button_down_event( + &mut self, + _context: &mut ggez::Context, + _button: mouse::MouseButton, + _x: f32, + _y: f32, + ) { + self.events.push(iced::Event::Mouse( + iced::input::mouse::Event::Input { + state: iced::input::ButtonState::Pressed, + button: iced::input::mouse::Button::Left, // TODO: Map `button` + }, + )); + } + + fn mouse_button_up_event( + &mut self, + _context: &mut ggez::Context, + _button: mouse::MouseButton, + _x: f32, + _y: f32, + ) { + self.events.push(iced::Event::Mouse( + iced::input::mouse::Event::Input { + state: iced::input::ButtonState::Released, + button: iced::input::mouse::Button::Left, // TODO: Map `button` + }, + )); + } + + fn mouse_motion_event( + &mut self, + _context: &mut ggez::Context, + x: f32, + y: f32, + _dx: f32, + _dy: f32, + ) { + self.events.push(iced::Event::Mouse( + iced::input::mouse::Event::CursorMoved { x, y }, + )); + } + + fn resize_event( + &mut self, + context: &mut ggez::Context, + width: f32, + height: f32, + ) { + graphics::set_screen_coordinates( + context, + graphics::Rect { + x: 0.0, + y: 0.0, + w: width, + h: height, + }, + ) + .expect("Set screen coordinates"); + } + + fn draw(&mut self, context: &mut ggez::Context) -> ggez::GameResult { + graphics::clear(context, graphics::WHITE); + + let screen = graphics::screen_coordinates(context); + + let (messages, cursor) = { + let view = self.tour.view(); + + let content = iced_ggez::Column::new() + .width(screen.w as u16) + .height(screen.h as u16) + .padding(20) + .align_items(iced::Align::Center) + .justify_content(iced::Justify::Center) + .push(view); + + let renderer = &mut iced_ggez::Renderer::new( + context, + &mut self.images, + self.spritesheet.clone(), + self.font, + ); + + let mut ui = iced::UserInterface::build( + content, + self.cache.take().unwrap(), + renderer, + ); + + let messages = ui.update(self.events.drain(..)); + let cursor = ui.draw(renderer); + + self.cache = Some(ui.into_cache()); + + renderer.flush(); + + (messages, cursor) + }; + + for message in messages { + self.tour.update(message); + } + + let cursor_type = into_cursor_type(cursor); + + if mouse::cursor_type(context) != cursor_type { + mouse::set_cursor_type(context, cursor_type); + } + + graphics::present(context)?; + Ok(()) + } +} + +fn into_cursor_type(cursor: iced::MouseCursor) -> mouse::MouseCursor { + match cursor { + iced::MouseCursor::OutOfBounds => mouse::MouseCursor::Default, + iced::MouseCursor::Idle => mouse::MouseCursor::Default, + iced::MouseCursor::Pointer => mouse::MouseCursor::Hand, + iced::MouseCursor::Working => mouse::MouseCursor::Progress, + iced::MouseCursor::Grab => mouse::MouseCursor::Grab, + iced::MouseCursor::Grabbing => mouse::MouseCursor::Grabbing, + } +} diff --git a/examples/tour/src/iced_ggez/renderer.rs b/examples/tour/src/iced_ggez/renderer.rs new file mode 100644 index 00000000..e3181eaa --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer.rs @@ -0,0 +1,77 @@ +mod button; +mod checkbox; +mod debugger; +mod image; +mod radio; +mod slider; +mod text; + +use ggez::graphics::{ + self, spritebatch::SpriteBatch, Font, Image, MeshBuilder, +}; +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, + font_size: f32, + debug_mesh: Option, +} + +impl<'a> Renderer<'a> { + pub fn new( + context: &'a mut Context, + images: &'a mut image::Cache, + spritesheet: Image, + font: Font, + ) -> Renderer<'a> { + Renderer { + context, + images, + sprites: SpriteBatch::new(spritesheet.clone()), + spritesheet, + font, + font_size: 20.0, + debug_mesh: None, + } + } + + pub fn flush(&mut self) { + graphics::draw( + self.context, + &self.sprites, + graphics::DrawParam::default(), + ) + .expect("Draw sprites"); + + graphics::draw_queued_text( + self.context, + graphics::DrawParam::default(), + Default::default(), + graphics::FilterMode::Linear, + ) + .expect("Draw text"); + + if let Some(debug_mesh) = self.debug_mesh.take() { + let mesh = + debug_mesh.build(self.context).expect("Build debug mesh"); + + graphics::draw(self.context, &mesh, graphics::DrawParam::default()) + .expect("Draw debug mesh"); + } + } +} + +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/src/iced_ggez/renderer/button.rs b/examples/tour/src/iced_ggez/renderer/button.rs new file mode 100644 index 00000000..486e07ed --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/button.rs @@ -0,0 +1,145 @@ +use super::Renderer; +use ggez::graphics::{ + self, Align, Color, DrawParam, Rect, Scale, Text, TextFragment, WHITE, +}; +use iced::{button, MouseCursor}; + +const LEFT: Rect = Rect { + x: 0.0, + y: 34.0, + w: 6.0, + h: 49.0, +}; + +const BACKGROUND: Rect = Rect { + x: LEFT.w, + y: LEFT.y, + w: 1.0, + h: LEFT.h, +}; + +const RIGHT: Rect = Rect { + x: LEFT.h - LEFT.w, + y: LEFT.y, + w: LEFT.w, + h: LEFT.h, +}; + +impl button::Renderer for Renderer<'_> { + fn draw( + &mut self, + cursor_position: iced::Point, + mut bounds: iced::Rectangle, + state: &button::State, + label: &str, + class: button::Class, + ) -> MouseCursor { + let mouse_over = bounds.contains(cursor_position); + + let mut state_offset = 0.0; + + if mouse_over { + if state.is_pressed() { + bounds.y += 4.0; + state_offset = RIGHT.x + RIGHT.w; + } else { + bounds.y -= 1.0; + } + } + + let class_index = match class { + button::Class::Primary => 0, + button::Class::Secondary => 1, + button::Class::Positive => 2, + }; + + let width = self.spritesheet.width() as f32; + let height = self.spritesheet.height() as f32; + + self.sprites.add(DrawParam { + src: Rect { + x: (LEFT.x + state_offset) / width, + y: (LEFT.y + class_index as f32 * LEFT.h) / height, + w: LEFT.w / width, + h: LEFT.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + ..DrawParam::default() + }); + + self.sprites.add(DrawParam { + src: Rect { + x: (BACKGROUND.x + state_offset) / width, + y: (BACKGROUND.y + class_index as f32 * BACKGROUND.h) / height, + w: BACKGROUND.w / width, + h: BACKGROUND.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x + LEFT.w, + y: bounds.y, + }, + scale: ggez::mint::Vector2 { + x: bounds.width - LEFT.w - RIGHT.w, + y: 1.0, + }, + ..DrawParam::default() + }); + + self.sprites.add(DrawParam { + src: Rect { + x: (RIGHT.x + state_offset) / width, + y: (RIGHT.y + class_index as f32 * RIGHT.h) / height, + w: RIGHT.w / width, + h: RIGHT.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x + bounds.width - RIGHT.w, + y: bounds.y, + }, + ..DrawParam::default() + }); + + let mut text = Text::new(TextFragment { + text: String::from(label), + font: Some(self.font), + scale: Some(Scale { x: 20.0, y: 20.0 }), + ..Default::default() + }); + + text.set_bounds( + ggez::mint::Point2 { + x: bounds.width, + y: bounds.height, + }, + Align::Center, + ); + + graphics::queue_text( + self.context, + &text, + ggez::mint::Point2 { + x: bounds.x, + y: bounds.y + BACKGROUND.h / 4.0, + }, + Some(if mouse_over { + WHITE + } else { + Color { + r: 0.9, + g: 0.9, + b: 0.9, + a: 1.0, + } + }), + ); + + if mouse_over { + MouseCursor::Pointer + } else { + MouseCursor::OutOfBounds + } + } +} diff --git a/examples/tour/src/iced_ggez/renderer/checkbox.rs b/examples/tour/src/iced_ggez/renderer/checkbox.rs new file mode 100644 index 00000000..20a91be5 --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/checkbox.rs @@ -0,0 +1,64 @@ +use super::Renderer; + +use ggez::graphics::{DrawParam, Rect}; +use iced::{checkbox, MouseCursor}; + +const SPRITE: Rect = Rect { + x: 98.0, + y: 0.0, + w: 28.0, + h: 28.0, +}; + +impl checkbox::Renderer for Renderer<'_> { + fn draw( + &mut self, + cursor_position: iced::Point, + bounds: iced::Rectangle, + text_bounds: iced::Rectangle, + is_checked: bool, + ) -> MouseCursor { + let mouse_over = bounds.contains(cursor_position) + || text_bounds.contains(cursor_position); + + let width = self.spritesheet.width() as f32; + let height = self.spritesheet.height() as f32; + + self.sprites.add(DrawParam { + src: Rect { + x: (SPRITE.x + (if mouse_over { SPRITE.w } else { 0.0 })) + / width, + y: SPRITE.y / height, + w: SPRITE.w / width, + h: SPRITE.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + ..DrawParam::default() + }); + + if is_checked { + self.sprites.add(DrawParam { + src: Rect { + x: (SPRITE.x + SPRITE.w * 2.0) / width, + y: SPRITE.y / height, + w: SPRITE.w / width, + h: SPRITE.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + ..DrawParam::default() + }); + } + + if mouse_over { + MouseCursor::Pointer + } else { + MouseCursor::OutOfBounds + } + } +} diff --git a/examples/tour/src/iced_ggez/renderer/debugger.rs b/examples/tour/src/iced_ggez/renderer/debugger.rs new file mode 100644 index 00000000..c6727881 --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/debugger.rs @@ -0,0 +1,30 @@ +use super::{into_color, Renderer}; +use ggez::graphics::{DrawMode, MeshBuilder, Rect}; + +impl iced::renderer::Debugger for Renderer<'_> { + type Color = iced::Color; + + fn explain(&mut self, layout: &iced::Layout<'_>, color: iced::Color) { + let bounds = layout.bounds(); + + let mut debug_mesh = + self.debug_mesh.take().unwrap_or(MeshBuilder::new()); + + debug_mesh.rectangle( + DrawMode::stroke(1.0), + Rect { + x: bounds.x, + y: bounds.y, + w: bounds.width, + h: bounds.height, + }, + into_color(color), + ); + + self.debug_mesh = Some(debug_mesh); + + for child in layout.children() { + self.explain(&child, color); + } + } +} diff --git a/examples/tour/src/iced_ggez/renderer/image.rs b/examples/tour/src/iced_ggez/renderer/image.rs new file mode 100644 index 00000000..17c6a56e --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/image.rs @@ -0,0 +1,86 @@ +use super::Renderer; + +use ggez::{graphics, nalgebra}; +use iced::image; + +pub struct Cache { + images: std::collections::HashMap, +} + +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( + &mut self, + style: iced::Style, + name: &&'a str, + width: Option, + height: Option, + _source: Option>, + ) -> 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) { + (Some(width), Some(height)) => style.width(width).height(height), + (Some(width), None) => style + .width(width) + .height((width as f32 / aspect_ratio).round() as u16), + (None, Some(height)) => style + .height(height) + .width((height as f32 * aspect_ratio).round() as u16), + (None, None) => style.width(image.width()).height(image.height()), + }; + + iced::Node::new(style) + } + + fn draw( + &mut self, + name: &&'a str, + bounds: iced::Rectangle, + _source: Option>, + ) { + 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, + graphics::DrawParam::new() + .dest(nalgebra::Point2::new(bounds.x, bounds.y)) + .scale(nalgebra::Vector2::new( + bounds.width / image.width() as f32, + bounds.height / image.height() as f32, + )), + ) + .expect("Draw image"); + } +} diff --git a/examples/tour/src/iced_ggez/renderer/radio.rs b/examples/tour/src/iced_ggez/renderer/radio.rs new file mode 100644 index 00000000..0f7815d6 --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/radio.rs @@ -0,0 +1,63 @@ +use super::Renderer; + +use ggez::graphics::{DrawParam, Rect}; +use iced::{radio, MouseCursor, Point, Rectangle}; + +const SPRITE: Rect = Rect { + x: 98.0, + y: 28.0, + w: 28.0, + h: 28.0, +}; + +impl radio::Renderer for Renderer<'_> { + fn draw( + &mut self, + cursor_position: Point, + bounds: Rectangle, + bounds_with_label: Rectangle, + is_selected: bool, + ) -> MouseCursor { + let mouse_over = bounds_with_label.contains(cursor_position); + + let width = self.spritesheet.width() as f32; + let height = self.spritesheet.height() as f32; + + self.sprites.add(DrawParam { + src: Rect { + x: (SPRITE.x + (if mouse_over { SPRITE.w } else { 0.0 })) + / width, + y: SPRITE.y / height, + w: SPRITE.w / width, + h: SPRITE.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + ..DrawParam::default() + }); + + if is_selected { + self.sprites.add(DrawParam { + src: Rect { + x: (SPRITE.x + SPRITE.w * 2.0) / width, + y: SPRITE.y / height, + w: SPRITE.w / width, + h: SPRITE.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + ..DrawParam::default() + }); + } + + if mouse_over { + MouseCursor::Pointer + } else { + MouseCursor::OutOfBounds + } + } +} diff --git a/examples/tour/src/iced_ggez/renderer/slider.rs b/examples/tour/src/iced_ggez/renderer/slider.rs new file mode 100644 index 00000000..146cee18 --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/slider.rs @@ -0,0 +1,82 @@ +use super::Renderer; + +use ggez::graphics::{DrawParam, Rect}; +use iced::{slider, MouseCursor, Point, Rectangle}; +use std::ops::RangeInclusive; + +const RAIL: Rect = Rect { + x: 98.0, + y: 56.0, + w: 1.0, + h: 4.0, +}; + +const MARKER: Rect = Rect { + x: RAIL.x + 28.0, + y: RAIL.y, + w: 16.0, + h: 24.0, +}; + +impl slider::Renderer for Renderer<'_> { + fn draw( + &mut self, + cursor_position: Point, + bounds: Rectangle, + state: &slider::State, + range: RangeInclusive, + value: f32, + ) -> MouseCursor { + let width = self.spritesheet.width() as f32; + let height = self.spritesheet.height() as f32; + + self.sprites.add(DrawParam { + src: Rect { + x: RAIL.x / width, + y: RAIL.y / height, + w: RAIL.w / width, + h: RAIL.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x + MARKER.w as f32 / 2.0, + y: bounds.y + 12.5, + }, + scale: ggez::mint::Vector2 { + x: bounds.width - MARKER.w as f32, + y: 1.0, + }, + ..DrawParam::default() + }); + + let (range_start, range_end) = range.into_inner(); + + let marker_offset = (bounds.width - MARKER.w as f32) + * ((value - range_start) / (range_end - range_start).max(1.0)); + + let mouse_over = bounds.contains(cursor_position); + let is_active = state.is_dragging() || mouse_over; + + self.sprites.add(DrawParam { + src: Rect { + x: (MARKER.x + (if is_active { MARKER.w } else { 0.0 })) + / width, + y: MARKER.y / height, + w: MARKER.w / width, + h: MARKER.h / height, + }, + dest: ggez::mint::Point2 { + x: bounds.x + marker_offset.round(), + y: bounds.y + (if state.is_dragging() { 2.0 } else { 0.0 }), + }, + ..DrawParam::default() + }); + + if state.is_dragging() { + MouseCursor::Grabbing + } else if mouse_over { + MouseCursor::Grab + } else { + MouseCursor::OutOfBounds + } + } +} diff --git a/examples/tour/src/iced_ggez/renderer/text.rs b/examples/tour/src/iced_ggez/renderer/text.rs new file mode 100644 index 00000000..b5010639 --- /dev/null +++ b/examples/tour/src/iced_ggez/renderer/text.rs @@ -0,0 +1,118 @@ +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 for Renderer<'_> { + fn node( + &self, + style: iced::Style, + content: &str, + size: Option, + ) -> iced::Node { + let font = self.font; + let font_cache = graphics::font_cache(self.context); + let content = String::from(content); + + // TODO: Investigate why stretch tries to measure this MANY times + // with every ancestor's bounds. + // Bug? Using the library wrong? I should probably open an issue on + // the stretch repository. + // I noticed that the first measure is the one that matters in + // practice. Here, we use a RefCell to store the cached measurement. + let measure = RefCell::new(None); + let size = size.map(f32::from).unwrap_or(self.font_size); + + iced::Node::with_measure(style, move |bounds| { + let mut measure = measure.borrow_mut(); + + if measure.is_none() { + let bounds = ( + match bounds.width { + iced::Number::Undefined => f32::INFINITY, + iced::Number::Defined(w) => w, + }, + match bounds.height { + iced::Number::Undefined => f32::INFINITY, + iced::Number::Defined(h) => h, + }, + ); + + let mut text = Text::new(TextFragment { + text: content.clone(), + font: Some(font), + scale: Some(Scale { x: size, y: size }), + ..Default::default() + }); + + text.set_bounds( + mint::Point2 { + x: bounds.0, + y: bounds.1, + }, + Align::Left, + ); + + let (width, height) = font_cache.dimensions(&text); + + let size = iced::Size { + width: width as f32, + height: height as f32, + }; + + // If the text has no width boundary we avoid caching as the + // layout engine may just be measuring text in a row. + if bounds.0 == f32::INFINITY { + return size; + } else { + *measure = Some(size); + } + } + + measure.unwrap() + }) + } + + fn draw( + &mut self, + bounds: iced::Rectangle, + content: &str, + size: Option, + color: Option, + horizontal_alignment: text::HorizontalAlignment, + _vertical_alignment: text::VerticalAlignment, + ) { + let size = size.map(f32::from).unwrap_or(self.font_size); + + let mut text = Text::new(TextFragment { + text: String::from(content), + font: Some(self.font), + scale: Some(Scale { x: size, y: size }), + ..Default::default() + }); + + text.set_bounds( + mint::Point2 { + x: bounds.width, + y: bounds.height, + }, + match horizontal_alignment { + text::HorizontalAlignment::Left => graphics::Align::Left, + text::HorizontalAlignment::Center => graphics::Align::Center, + text::HorizontalAlignment::Right => graphics::Align::Right, + }, + ); + + graphics::queue_text( + self.context, + &text, + mint::Point2 { + x: bounds.x, + y: bounds.y, + }, + color.or(Some(iced::Color::BLACK)).map(into_color), + ); + } +} diff --git a/examples/tour/src/iced_ggez/widget.rs b/examples/tour/src/iced_ggez/widget.rs new file mode 100644 index 00000000..a365daca --- /dev/null +++ b/examples/tour/src/iced_ggez/widget.rs @@ -0,0 +1,12 @@ +use super::Renderer; + +pub use iced::{button, slider, text, Align, Button, Color, Slider}; + +pub type Text = iced::Text; +pub type Checkbox = iced::Checkbox; +pub type Radio = iced::Radio; +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>>; +pub type Element<'a, Message> = iced::Element<'a, Message, Renderer<'a>>; -- cgit From b83a4b42dd912b5f59d40e7d4f7f7ccdabc43019 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 19 Sep 2019 18:47:01 +0200 Subject: Remove generic `Color` in widgets --- examples/tour/src/iced_ggez/renderer/debugger.rs | 2 -- examples/tour/src/iced_ggez/renderer/text.rs | 2 +- examples/tour/src/iced_ggez/widget.rs | 7 +++---- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'examples/tour/src/iced_ggez') diff --git a/examples/tour/src/iced_ggez/renderer/debugger.rs b/examples/tour/src/iced_ggez/renderer/debugger.rs index c6727881..eba03ebf 100644 --- a/examples/tour/src/iced_ggez/renderer/debugger.rs +++ b/examples/tour/src/iced_ggez/renderer/debugger.rs @@ -2,8 +2,6 @@ use super::{into_color, Renderer}; use ggez::graphics::{DrawMode, MeshBuilder, Rect}; impl iced::renderer::Debugger for Renderer<'_> { - type Color = iced::Color; - fn explain(&mut self, layout: &iced::Layout<'_>, color: iced::Color) { let bounds = layout.bounds(); diff --git a/examples/tour/src/iced_ggez/renderer/text.rs b/examples/tour/src/iced_ggez/renderer/text.rs index b5010639..450ca2cd 100644 --- a/examples/tour/src/iced_ggez/renderer/text.rs +++ b/examples/tour/src/iced_ggez/renderer/text.rs @@ -5,7 +5,7 @@ use iced::text; use std::cell::RefCell; use std::f32; -impl text::Renderer for Renderer<'_> { +impl text::Renderer for Renderer<'_> { fn node( &self, style: iced::Style, diff --git a/examples/tour/src/iced_ggez/widget.rs b/examples/tour/src/iced_ggez/widget.rs index a365daca..c9f857f6 100644 --- a/examples/tour/src/iced_ggez/widget.rs +++ b/examples/tour/src/iced_ggez/widget.rs @@ -1,10 +1,9 @@ use super::Renderer; -pub use iced::{button, slider, text, Align, Button, Color, Slider}; +pub use iced::{ + button, slider, text, Align, Button, Checkbox, Color, Radio, Slider, Text, +}; -pub type Text = iced::Text; -pub type Checkbox = iced::Checkbox; -pub type Radio = iced::Radio; pub type Image<'a> = iced::Image<&'a str>; pub type Column<'a, Message> = iced::Column<'a, Message, Renderer<'a>>; -- cgit From b9e0f7494881ad7cdfbcbc16878ecc6ef717753f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 20 Sep 2019 19:15:31 +0200 Subject: Create `iced_core` and `iced_native` --- examples/tour/src/iced_ggez/main.rs | 50 ++++++++++----------- examples/tour/src/iced_ggez/renderer.rs | 2 +- examples/tour/src/iced_ggez/renderer/button.rs | 29 +++++++----- examples/tour/src/iced_ggez/renderer/checkbox.rs | 46 +++++++++++++++---- examples/tour/src/iced_ggez/renderer/debugger.rs | 8 +++- examples/tour/src/iced_ggez/renderer/image.rs | 46 ++++++++----------- examples/tour/src/iced_ggez/renderer/radio.rs | 45 +++++++++++++++---- examples/tour/src/iced_ggez/renderer/slider.rs | 35 ++++++++++----- examples/tour/src/iced_ggez/renderer/text.rs | 56 ++++++++++-------------- examples/tour/src/iced_ggez/widget.rs | 13 +++--- 10 files changed, 198 insertions(+), 132 deletions(-) (limited to 'examples/tour/src/iced_ggez') diff --git a/examples/tour/src/iced_ggez/main.rs b/examples/tour/src/iced_ggez/main.rs index a8cf09e5..72774d38 100644 --- a/examples/tour/src/iced_ggez/main.rs +++ b/examples/tour/src/iced_ggez/main.rs @@ -35,8 +35,8 @@ struct Game { images: iced_ggez::ImageCache, tour: Tour, - events: Vec, - cache: Option, + events: Vec, + cache: Option, } impl Game { @@ -52,7 +52,7 @@ impl Game { tour: Tour::new(), events: Vec::new(), - cache: Some(iced::Cache::default()), + cache: Some(iced_native::Cache::default()), }) } } @@ -69,10 +69,10 @@ impl event::EventHandler for Game { _x: f32, _y: f32, ) { - self.events.push(iced::Event::Mouse( - iced::input::mouse::Event::Input { - state: iced::input::ButtonState::Pressed, - button: iced::input::mouse::Button::Left, // TODO: Map `button` + self.events.push(iced_native::Event::Mouse( + iced_native::input::mouse::Event::Input { + state: iced_native::input::ButtonState::Pressed, + button: iced_native::input::mouse::Button::Left, // TODO: Map `button` }, )); } @@ -84,10 +84,10 @@ impl event::EventHandler for Game { _x: f32, _y: f32, ) { - self.events.push(iced::Event::Mouse( - iced::input::mouse::Event::Input { - state: iced::input::ButtonState::Released, - button: iced::input::mouse::Button::Left, // TODO: Map `button` + self.events.push(iced_native::Event::Mouse( + iced_native::input::mouse::Event::Input { + state: iced_native::input::ButtonState::Released, + button: iced_native::input::mouse::Button::Left, // TODO: Map `button` }, )); } @@ -100,8 +100,8 @@ impl event::EventHandler for Game { _dx: f32, _dy: f32, ) { - self.events.push(iced::Event::Mouse( - iced::input::mouse::Event::CursorMoved { x, y }, + self.events.push(iced_native::Event::Mouse( + iced_native::input::mouse::Event::CursorMoved { x, y }, )); } @@ -132,11 +132,11 @@ impl event::EventHandler for Game { let view = self.tour.view(); let content = iced_ggez::Column::new() - .width(screen.w as u16) - .height(screen.h as u16) + .width(iced_native::Length::Units(screen.w as u16)) + .height(iced_native::Length::Units(screen.h as u16)) .padding(20) - .align_items(iced::Align::Center) - .justify_content(iced::Justify::Center) + .align_items(iced_native::Align::Center) + .justify_content(iced_native::Justify::Center) .push(view); let renderer = &mut iced_ggez::Renderer::new( @@ -146,7 +146,7 @@ impl event::EventHandler for Game { self.font, ); - let mut ui = iced::UserInterface::build( + let mut ui = iced_native::UserInterface::build( content, self.cache.take().unwrap(), renderer, @@ -177,13 +177,13 @@ impl event::EventHandler for Game { } } -fn into_cursor_type(cursor: iced::MouseCursor) -> mouse::MouseCursor { +fn into_cursor_type(cursor: iced_native::MouseCursor) -> mouse::MouseCursor { match cursor { - iced::MouseCursor::OutOfBounds => mouse::MouseCursor::Default, - iced::MouseCursor::Idle => mouse::MouseCursor::Default, - iced::MouseCursor::Pointer => mouse::MouseCursor::Hand, - iced::MouseCursor::Working => mouse::MouseCursor::Progress, - iced::MouseCursor::Grab => mouse::MouseCursor::Grab, - iced::MouseCursor::Grabbing => mouse::MouseCursor::Grabbing, + iced_native::MouseCursor::OutOfBounds => mouse::MouseCursor::Default, + iced_native::MouseCursor::Idle => mouse::MouseCursor::Default, + iced_native::MouseCursor::Pointer => mouse::MouseCursor::Hand, + iced_native::MouseCursor::Working => mouse::MouseCursor::Progress, + iced_native::MouseCursor::Grab => mouse::MouseCursor::Grab, + iced_native::MouseCursor::Grabbing => mouse::MouseCursor::Grabbing, } } diff --git a/examples/tour/src/iced_ggez/renderer.rs b/examples/tour/src/iced_ggez/renderer.rs index e3181eaa..c0e6d559 100644 --- a/examples/tour/src/iced_ggez/renderer.rs +++ b/examples/tour/src/iced_ggez/renderer.rs @@ -67,7 +67,7 @@ impl<'a> Renderer<'a> { } } -pub fn into_color(color: iced::Color) -> graphics::Color { +pub fn into_color(color: iced_native::Color) -> graphics::Color { graphics::Color { r: color.r, g: color.g, diff --git a/examples/tour/src/iced_ggez/renderer/button.rs b/examples/tour/src/iced_ggez/renderer/button.rs index 486e07ed..78a5de07 100644 --- a/examples/tour/src/iced_ggez/renderer/button.rs +++ b/examples/tour/src/iced_ggez/renderer/button.rs @@ -2,7 +2,7 @@ use super::Renderer; use ggez::graphics::{ self, Align, Color, DrawParam, Rect, Scale, Text, TextFragment, WHITE, }; -use iced::{button, MouseCursor}; +use iced_native::{button, Button, Layout, Length, MouseCursor, Node, Style}; const LEFT: Rect = Rect { x: 0.0, @@ -26,20 +26,29 @@ const RIGHT: Rect = Rect { }; impl button::Renderer for Renderer<'_> { - fn draw( + fn node(&self, button: &Button<'_, Message>) -> Node { + let style = Style::default() + .width(button.width) + .height(Length::Units(LEFT.h as u16)) + .min_width(Length::Units(100)) + .align_self(button.align_self); + + Node::new(style) + } + + fn draw( &mut self, - cursor_position: iced::Point, - mut bounds: iced::Rectangle, - state: &button::State, - label: &str, - class: button::Class, + button: &Button<'_, Message>, + layout: Layout<'_>, + cursor_position: iced_native::Point, ) -> MouseCursor { + let mut bounds = layout.bounds(); let mouse_over = bounds.contains(cursor_position); let mut state_offset = 0.0; if mouse_over { - if state.is_pressed() { + if button.state.is_pressed() { bounds.y += 4.0; state_offset = RIGHT.x + RIGHT.w; } else { @@ -47,7 +56,7 @@ impl button::Renderer for Renderer<'_> { } } - let class_index = match class { + let class_index = match button.class { button::Class::Primary => 0, button::Class::Secondary => 1, button::Class::Positive => 2, @@ -103,7 +112,7 @@ impl button::Renderer for Renderer<'_> { }); let mut text = Text::new(TextFragment { - text: String::from(label), + text: button.label.clone(), font: Some(self.font), scale: Some(Scale { x: 20.0, y: 20.0 }), ..Default::default() diff --git a/examples/tour/src/iced_ggez/renderer/checkbox.rs b/examples/tour/src/iced_ggez/renderer/checkbox.rs index 20a91be5..807185d9 100644 --- a/examples/tour/src/iced_ggez/renderer/checkbox.rs +++ b/examples/tour/src/iced_ggez/renderer/checkbox.rs @@ -1,7 +1,10 @@ use super::Renderer; use ggez::graphics::{DrawParam, Rect}; -use iced::{checkbox, MouseCursor}; +use iced_native::{ + checkbox, text, Align, Checkbox, Column, Layout, Length, MouseCursor, Node, + Row, Text, Widget, +}; const SPRITE: Rect = Rect { x: 98.0, @@ -10,14 +13,41 @@ const SPRITE: Rect = Rect { h: 28.0, }; -impl checkbox::Renderer for Renderer<'_> { - fn draw( +impl checkbox::Renderer for Renderer<'_> +where + Self: text::Renderer, +{ + fn node(&mut self, checkbox: &Checkbox) -> Node { + Row::<(), Self>::new() + .spacing(15) + .align_items(Align::Center) + .push( + Column::new() + .width(Length::Units(SPRITE.w as u16)) + .height(Length::Units(SPRITE.h as u16)), + ) + .push(Text::new(&checkbox.label)) + .node(self) + } + + fn draw( &mut self, - cursor_position: iced::Point, - bounds: iced::Rectangle, - text_bounds: iced::Rectangle, - is_checked: bool, + checkbox: &Checkbox, + layout: Layout<'_>, + cursor_position: iced_native::Point, ) -> MouseCursor { + let bounds = layout.bounds(); + let children: Vec<_> = layout.children().collect(); + let text_bounds = children[1].bounds(); + + let mut text = Text::new(&checkbox.label); + + if let Some(label_color) = checkbox.label_color { + text = text.color(label_color); + } + + text::Renderer::draw(self, &text, children[1]); + let mouse_over = bounds.contains(cursor_position) || text_bounds.contains(cursor_position); @@ -39,7 +69,7 @@ impl checkbox::Renderer for Renderer<'_> { ..DrawParam::default() }); - if is_checked { + if checkbox.is_checked { self.sprites.add(DrawParam { src: Rect { x: (SPRITE.x + SPRITE.w * 2.0) / width, diff --git a/examples/tour/src/iced_ggez/renderer/debugger.rs b/examples/tour/src/iced_ggez/renderer/debugger.rs index eba03ebf..ffb658af 100644 --- a/examples/tour/src/iced_ggez/renderer/debugger.rs +++ b/examples/tour/src/iced_ggez/renderer/debugger.rs @@ -1,8 +1,12 @@ use super::{into_color, Renderer}; use ggez::graphics::{DrawMode, MeshBuilder, Rect}; -impl iced::renderer::Debugger for Renderer<'_> { - fn explain(&mut self, layout: &iced::Layout<'_>, color: iced::Color) { +impl iced_native::renderer::Debugger for Renderer<'_> { + fn explain( + &mut self, + layout: &iced_native::Layout<'_>, + color: iced_native::Color, + ) { let bounds = layout.bounds(); let mut debug_mesh = diff --git a/examples/tour/src/iced_ggez/renderer/image.rs b/examples/tour/src/iced_ggez/renderer/image.rs index 17c6a56e..b12b65c3 100644 --- a/examples/tour/src/iced_ggez/renderer/image.rs +++ b/examples/tour/src/iced_ggez/renderer/image.rs @@ -1,7 +1,7 @@ use super::Renderer; use ggez::{graphics, nalgebra}; -use iced::image; +use iced_native::{image, Image, Layout, Length, Style}; pub struct Cache { images: std::collections::HashMap, @@ -35,39 +35,29 @@ impl Cache { } impl<'a> image::Renderer<&'a str> for Renderer<'_> { - fn node( - &mut self, - style: iced::Style, - name: &&'a str, - width: Option, - height: Option, - _source: Option>, - ) -> iced::Node { - let image = self.images.get(name, self.context); + fn node(&mut self, image: &Image<&'a str>) -> iced_native::Node { + let ggez_image = self.images.get(image.handle, self.context); + + let aspect_ratio = + ggez_image.width() as f32 / ggez_image.height() as f32; - let aspect_ratio = image.width() as f32 / image.height() as f32; + let mut style = Style::default().align_self(image.align_self); - let style = match (width, height) { - (Some(width), Some(height)) => style.width(width).height(height), - (Some(width), None) => style - .width(width) - .height((width as f32 / aspect_ratio).round() as u16), - (None, Some(height)) => style - .height(height) - .width((height as f32 * aspect_ratio).round() as u16), - (None, None) => style.width(image.width()).height(image.height()), + style = match (image.width, image.height) { + (Length::Units(width), _) => style.width(image.width).height( + Length::Units((width as f32 / aspect_ratio).round() as u16), + ), + (_, _) => style + .width(Length::Units(ggez_image.width())) + .height(Length::Units(ggez_image.height())), }; - iced::Node::new(style) + iced_native::Node::new(style) } - fn draw( - &mut self, - name: &&'a str, - bounds: iced::Rectangle, - _source: Option>, - ) { - let image = self.images.get(name, self.context); + fn draw(&mut self, image: &Image<&'a str>, layout: Layout<'_>) { + let image = self.images.get(image.handle, self.context); + let bounds = layout.bounds(); // We should probably use batches to draw images efficiently and keep // draw side-effect free, but this is good enough for the example. diff --git a/examples/tour/src/iced_ggez/renderer/radio.rs b/examples/tour/src/iced_ggez/renderer/radio.rs index 0f7815d6..dbd29ecd 100644 --- a/examples/tour/src/iced_ggez/renderer/radio.rs +++ b/examples/tour/src/iced_ggez/renderer/radio.rs @@ -1,7 +1,10 @@ use super::Renderer; use ggez::graphics::{DrawParam, Rect}; -use iced::{radio, MouseCursor, Point, Rectangle}; +use iced_native::{ + radio, text, Align, Column, Layout, Length, MouseCursor, Node, Point, + Radio, Row, Text, Widget, +}; const SPRITE: Rect = Rect { x: 98.0, @@ -10,15 +13,41 @@ const SPRITE: Rect = Rect { h: 28.0, }; -impl radio::Renderer for Renderer<'_> { - fn draw( +impl radio::Renderer for Renderer<'_> +where + Self: text::Renderer, +{ + fn node(&mut self, radio: &Radio) -> Node { + Row::<(), Self>::new() + .spacing(15) + .align_items(Align::Center) + .push( + Column::new() + .width(Length::Units(SPRITE.w as u16)) + .height(Length::Units(SPRITE.h as u16)), + ) + .push(Text::new(&radio.label)) + .node(self) + } + + fn draw( &mut self, + radio: &Radio, + layout: Layout<'_>, cursor_position: Point, - bounds: Rectangle, - bounds_with_label: Rectangle, - is_selected: bool, ) -> MouseCursor { - let mouse_over = bounds_with_label.contains(cursor_position); + let children: Vec<_> = layout.children().collect(); + + let mut text = Text::new(&radio.label); + + if let Some(label_color) = radio.label_color { + text = text.color(label_color); + } + + text::Renderer::draw(self, &text, children[1]); + + let bounds = layout.bounds(); + let mouse_over = bounds.contains(cursor_position); let width = self.spritesheet.width() as f32; let height = self.spritesheet.height() as f32; @@ -38,7 +67,7 @@ impl radio::Renderer for Renderer<'_> { ..DrawParam::default() }); - if is_selected { + if radio.is_selected { self.sprites.add(DrawParam { src: Rect { x: (SPRITE.x + SPRITE.w * 2.0) / width, diff --git a/examples/tour/src/iced_ggez/renderer/slider.rs b/examples/tour/src/iced_ggez/renderer/slider.rs index 146cee18..60c40c55 100644 --- a/examples/tour/src/iced_ggez/renderer/slider.rs +++ b/examples/tour/src/iced_ggez/renderer/slider.rs @@ -1,8 +1,9 @@ use super::Renderer; use ggez::graphics::{DrawParam, Rect}; -use iced::{slider, MouseCursor, Point, Rectangle}; -use std::ops::RangeInclusive; +use iced_native::{ + slider, Layout, Length, MouseCursor, Node, Point, Slider, Style, +}; const RAIL: Rect = Rect { x: 98.0, @@ -19,14 +20,22 @@ const MARKER: Rect = Rect { }; impl slider::Renderer for Renderer<'_> { - fn draw( + fn node(&self, slider: &Slider<'_, Message>) -> Node { + let style = Style::default() + .width(slider.width) + .height(Length::Units(25)) + .min_width(Length::Units(100)); + + Node::new(style) + } + + fn draw( &mut self, + slider: &Slider<'_, Message>, + layout: Layout<'_>, cursor_position: Point, - bounds: Rectangle, - state: &slider::State, - range: RangeInclusive, - value: f32, ) -> MouseCursor { + let bounds = layout.bounds(); let width = self.spritesheet.width() as f32; let height = self.spritesheet.height() as f32; @@ -48,13 +57,14 @@ impl slider::Renderer for Renderer<'_> { ..DrawParam::default() }); - let (range_start, range_end) = range.into_inner(); + let (range_start, range_end) = slider.range.clone().into_inner(); let marker_offset = (bounds.width - MARKER.w as f32) - * ((value - range_start) / (range_end - range_start).max(1.0)); + * ((slider.value - range_start) + / (range_end - range_start).max(1.0)); let mouse_over = bounds.contains(cursor_position); - let is_active = state.is_dragging() || mouse_over; + let is_active = slider.state.is_dragging() || mouse_over; self.sprites.add(DrawParam { src: Rect { @@ -66,12 +76,13 @@ impl slider::Renderer for Renderer<'_> { }, dest: ggez::mint::Point2 { x: bounds.x + marker_offset.round(), - y: bounds.y + (if state.is_dragging() { 2.0 } else { 0.0 }), + y: bounds.y + + (if slider.state.is_dragging() { 2.0 } else { 0.0 }), }, ..DrawParam::default() }); - if state.is_dragging() { + if slider.state.is_dragging() { MouseCursor::Grabbing } else if mouse_over { MouseCursor::Grab diff --git a/examples/tour/src/iced_ggez/renderer/text.rs b/examples/tour/src/iced_ggez/renderer/text.rs index 450ca2cd..b51cc220 100644 --- a/examples/tour/src/iced_ggez/renderer/text.rs +++ b/examples/tour/src/iced_ggez/renderer/text.rs @@ -1,20 +1,15 @@ use super::{into_color, Renderer}; use ggez::graphics::{self, mint, Align, Scale, Text, TextFragment}; -use iced::text; +use iced_native::{text, Layout, Node, Style}; use std::cell::RefCell; use std::f32; impl text::Renderer for Renderer<'_> { - fn node( - &self, - style: iced::Style, - content: &str, - size: Option, - ) -> iced::Node { + fn node(&self, text: &iced_native::Text) -> Node { let font = self.font; let font_cache = graphics::font_cache(self.context); - let content = String::from(content); + let content = String::from(&text.content); // TODO: Investigate why stretch tries to measure this MANY times // with every ancestor's bounds. @@ -23,20 +18,22 @@ impl text::Renderer for Renderer<'_> { // I noticed that the first measure is the one that matters in // practice. Here, we use a RefCell to store the cached measurement. let measure = RefCell::new(None); - let size = size.map(f32::from).unwrap_or(self.font_size); + let size = text.size.map(f32::from).unwrap_or(self.font_size); - iced::Node::with_measure(style, move |bounds| { + let style = Style::default().width(text.width); + + iced_native::Node::with_measure(style, move |bounds| { let mut measure = measure.borrow_mut(); if measure.is_none() { let bounds = ( match bounds.width { - iced::Number::Undefined => f32::INFINITY, - iced::Number::Defined(w) => w, + iced_native::Number::Undefined => f32::INFINITY, + iced_native::Number::Defined(w) => w, }, match bounds.height { - iced::Number::Undefined => f32::INFINITY, - iced::Number::Defined(h) => h, + iced_native::Number::Undefined => f32::INFINITY, + iced_native::Number::Defined(h) => h, }, ); @@ -57,7 +54,7 @@ impl text::Renderer for Renderer<'_> { let (width, height) = font_cache.dimensions(&text); - let size = iced::Size { + let size = iced_native::Size { width: width as f32, height: height as f32, }; @@ -75,30 +72,23 @@ impl text::Renderer for Renderer<'_> { }) } - fn draw( - &mut self, - bounds: iced::Rectangle, - content: &str, - size: Option, - color: Option, - horizontal_alignment: text::HorizontalAlignment, - _vertical_alignment: text::VerticalAlignment, - ) { - let size = size.map(f32::from).unwrap_or(self.font_size); - - let mut text = Text::new(TextFragment { - text: String::from(content), + fn draw(&mut self, text: &iced_native::Text, layout: Layout<'_>) { + let size = text.size.map(f32::from).unwrap_or(self.font_size); + let bounds = layout.bounds(); + + let mut ggez_text = Text::new(TextFragment { + text: text.content.clone(), font: Some(self.font), scale: Some(Scale { x: size, y: size }), ..Default::default() }); - text.set_bounds( + ggez_text.set_bounds( mint::Point2 { x: bounds.width, y: bounds.height, }, - match horizontal_alignment { + match text.horizontal_alignment { text::HorizontalAlignment::Left => graphics::Align::Left, text::HorizontalAlignment::Center => graphics::Align::Center, text::HorizontalAlignment::Right => graphics::Align::Right, @@ -107,12 +97,14 @@ impl text::Renderer for Renderer<'_> { graphics::queue_text( self.context, - &text, + &ggez_text, mint::Point2 { x: bounds.x, y: bounds.y, }, - color.or(Some(iced::Color::BLACK)).map(into_color), + text.color + .or(Some(iced_native::Color::BLACK)) + .map(into_color), ); } } diff --git a/examples/tour/src/iced_ggez/widget.rs b/examples/tour/src/iced_ggez/widget.rs index c9f857f6..948f9fc6 100644 --- a/examples/tour/src/iced_ggez/widget.rs +++ b/examples/tour/src/iced_ggez/widget.rs @@ -1,11 +1,12 @@ use super::Renderer; -pub use iced::{ - button, slider, text, Align, Button, Checkbox, Color, Radio, Slider, Text, +pub use iced_native::{ + button, slider, text, Align, Button, Checkbox, Color, Length, Radio, + Slider, Text, }; -pub type Image<'a> = iced::Image<&'a str>; +pub type Image<'a> = iced_native::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>>; -pub type Element<'a, Message> = iced::Element<'a, Message, Renderer<'a>>; +pub type Column<'a, Message> = iced_native::Column<'a, Message, Renderer<'a>>; +pub type Row<'a, Message> = iced_native::Row<'a, Message, Renderer<'a>>; +pub type Element<'a, Message> = iced_native::Element<'a, Message, Renderer<'a>>; -- cgit From 86dede4c4cc2bca9be7d2e6bd831daa98bd7043d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 21 Sep 2019 13:38:14 +0200 Subject: Make example work on web and update READMEs --- examples/tour/src/iced_ggez/main.rs | 189 ------------------------------------ 1 file changed, 189 deletions(-) delete mode 100644 examples/tour/src/iced_ggez/main.rs (limited to 'examples/tour/src/iced_ggez') diff --git a/examples/tour/src/iced_ggez/main.rs b/examples/tour/src/iced_ggez/main.rs deleted file mode 100644 index 72774d38..00000000 --- a/examples/tour/src/iced_ggez/main.rs +++ /dev/null @@ -1,189 +0,0 @@ -use iced_tour::{iced_ggez, Tour}; - -use ggez; -use ggez::event; -use ggez::filesystem; -use ggez::graphics; -use ggez::input::mouse; - -pub fn main() -> ggez::GameResult { - let (context, event_loop) = { - &mut ggez::ContextBuilder::new("iced", "ggez") - .window_mode(ggez::conf::WindowMode { - width: 1280.0, - height: 1024.0, - resizable: true, - ..ggez::conf::WindowMode::default() - }) - .build()? - }; - - filesystem::mount( - context, - std::path::Path::new(env!("CARGO_MANIFEST_DIR")), - true, - ); - - let state = &mut Game::new(context)?; - - event::run(context, event_loop, state) -} - -struct Game { - spritesheet: graphics::Image, - font: graphics::Font, - images: iced_ggez::ImageCache, - tour: Tour, - - events: Vec, - cache: Option, -} - -impl Game { - fn new(context: &mut ggez::Context) -> ggez::GameResult { - graphics::set_default_filter(context, graphics::FilterMode::Nearest); - - Ok(Game { - 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_native::Cache::default()), - }) - } -} - -impl event::EventHandler for Game { - fn update(&mut self, _ctx: &mut ggez::Context) -> ggez::GameResult { - Ok(()) - } - - fn mouse_button_down_event( - &mut self, - _context: &mut ggez::Context, - _button: mouse::MouseButton, - _x: f32, - _y: f32, - ) { - self.events.push(iced_native::Event::Mouse( - iced_native::input::mouse::Event::Input { - state: iced_native::input::ButtonState::Pressed, - button: iced_native::input::mouse::Button::Left, // TODO: Map `button` - }, - )); - } - - fn mouse_button_up_event( - &mut self, - _context: &mut ggez::Context, - _button: mouse::MouseButton, - _x: f32, - _y: f32, - ) { - self.events.push(iced_native::Event::Mouse( - iced_native::input::mouse::Event::Input { - state: iced_native::input::ButtonState::Released, - button: iced_native::input::mouse::Button::Left, // TODO: Map `button` - }, - )); - } - - fn mouse_motion_event( - &mut self, - _context: &mut ggez::Context, - x: f32, - y: f32, - _dx: f32, - _dy: f32, - ) { - self.events.push(iced_native::Event::Mouse( - iced_native::input::mouse::Event::CursorMoved { x, y }, - )); - } - - fn resize_event( - &mut self, - context: &mut ggez::Context, - width: f32, - height: f32, - ) { - graphics::set_screen_coordinates( - context, - graphics::Rect { - x: 0.0, - y: 0.0, - w: width, - h: height, - }, - ) - .expect("Set screen coordinates"); - } - - fn draw(&mut self, context: &mut ggez::Context) -> ggez::GameResult { - graphics::clear(context, graphics::WHITE); - - let screen = graphics::screen_coordinates(context); - - let (messages, cursor) = { - let view = self.tour.view(); - - let content = iced_ggez::Column::new() - .width(iced_native::Length::Units(screen.w as u16)) - .height(iced_native::Length::Units(screen.h as u16)) - .padding(20) - .align_items(iced_native::Align::Center) - .justify_content(iced_native::Justify::Center) - .push(view); - - let renderer = &mut iced_ggez::Renderer::new( - context, - &mut self.images, - self.spritesheet.clone(), - self.font, - ); - - let mut ui = iced_native::UserInterface::build( - content, - self.cache.take().unwrap(), - renderer, - ); - - let messages = ui.update(self.events.drain(..)); - let cursor = ui.draw(renderer); - - self.cache = Some(ui.into_cache()); - - renderer.flush(); - - (messages, cursor) - }; - - for message in messages { - self.tour.update(message); - } - - let cursor_type = into_cursor_type(cursor); - - if mouse::cursor_type(context) != cursor_type { - mouse::set_cursor_type(context, cursor_type); - } - - graphics::present(context)?; - Ok(()) - } -} - -fn into_cursor_type(cursor: iced_native::MouseCursor) -> mouse::MouseCursor { - match cursor { - iced_native::MouseCursor::OutOfBounds => mouse::MouseCursor::Default, - iced_native::MouseCursor::Idle => mouse::MouseCursor::Default, - iced_native::MouseCursor::Pointer => mouse::MouseCursor::Hand, - iced_native::MouseCursor::Working => mouse::MouseCursor::Progress, - iced_native::MouseCursor::Grab => mouse::MouseCursor::Grab, - iced_native::MouseCursor::Grabbing => mouse::MouseCursor::Grabbing, - } -} -- cgit