diff options
Diffstat (limited to 'examples')
28 files changed, 602 insertions, 364 deletions
diff --git a/examples/README.md b/examples/README.md index 74cf145b..111e8910 100644 --- a/examples/README.md +++ b/examples/README.md @@ -93,8 +93,7 @@ A bunch of simpler examples exist: - [`download_progress`](download_progress), a basic application that asynchronously downloads a dummy file of 100 MB and tracks the download progress. - [`events`](events), a log of native events displayed using a conditional `Subscription`. - [`geometry`](geometry), a custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../wgpu). -- [`integration_opengl`](integration_opengl), a demonstration of how to integrate Iced in an existing OpenGL application. -- [`integration_wgpu`](integration_wgpu), a demonstration of how to integrate Iced in an existing [`wgpu`] application. +- [`integration`](integration), a demonstration of how to integrate Iced in an existing [`wgpu`] application. - [`pane_grid`](pane_grid), a grid of panes that can be split, resized, and reorganized. - [`pick_list`](pick_list), a dropdown list of selectable options. - [`pokedex`](pokedex), an application that displays a random Pokédex entry (sprite included!) by using the [PokéAPI]. diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index 80ad0b5b..df565859 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -1,8 +1,9 @@ use std::{f32::consts::PI, time::Instant}; use iced::executor; +use iced::mouse; use iced::widget::canvas::{ - self, stroke, Cache, Canvas, Cursor, Geometry, Path, Stroke, + self, stroke, Cache, Canvas, Geometry, Path, Stroke, }; use iced::{ Application, Command, Element, Length, Point, Rectangle, Renderer, @@ -78,7 +79,7 @@ impl<Message> canvas::Program<Message> for Arc { renderer: &Renderer, theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index f1c83a16..310be28f 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -61,9 +61,7 @@ impl Sandbox for Example { mod bezier { use iced::mouse; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - self, Canvas, Cursor, Frame, Geometry, Path, Stroke, - }; + use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke}; use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; #[derive(Default)] @@ -100,10 +98,10 @@ mod bezier { state: &mut Self::State, event: Event, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Curve>) { let cursor_position = - if let Some(position) = cursor.position_in(&bounds) { + if let Some(position) = cursor.position_in(bounds) { position } else { return (event::Status::Ignored, None); @@ -155,7 +153,7 @@ mod bezier { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry> { let content = self.state.cache.draw( renderer, @@ -183,9 +181,9 @@ mod bezier { &self, _state: &Self::State, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> mouse::Interaction { - if cursor.is_over(&bounds) { + if cursor.is_over(bounds) { mouse::Interaction::Crosshair } else { mouse::Interaction::default() @@ -224,11 +222,11 @@ mod bezier { &self, renderer: &Renderer, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Geometry { let mut frame = Frame::new(renderer, bounds.size()); - if let Some(cursor_position) = cursor.position_in(&bounds) { + if let Some(cursor_position) = cursor.position_in(bounds) { match *self { Pending::One { from } => { let line = Path::line(from, cursor_position); diff --git a/examples/checkbox/src/main.rs b/examples/checkbox/src/main.rs index ef61a974..ef1a054d 100644 --- a/examples/checkbox/src/main.rs +++ b/examples/checkbox/src/main.rs @@ -31,7 +31,7 @@ impl Application for Example { fn new(_flags: Self::Flags) -> (Self, Command<Message>) { ( Self::default(), - font::load(include_bytes!("../fonts/icons.ttf").as_ref()) + font::load(include_bytes!("../fonts/icons.ttf").as_slice()) .map(Message::FontLoaded), ) } diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 6425e2da..fae77bc0 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,7 +1,6 @@ use iced::executor; -use iced::widget::canvas::{ - stroke, Cache, Cursor, Geometry, LineCap, Path, Stroke, -}; +use iced::mouse; +use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; use iced::{ Application, Color, Command, Element, Length, Point, Rectangle, Renderer, @@ -92,7 +91,7 @@ impl<Message> canvas::Program<Message, Renderer> for Clock { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let clock = self.clock.draw(renderer, bounds.size(), |frame| { let center = frame.center(); diff --git a/examples/color_palette/Cargo.toml b/examples/color_palette/Cargo.toml index 8fd37202..3be732bb 100644 --- a/examples/color_palette/Cargo.toml +++ b/examples/color_palette/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced = { path = "../..", features = ["canvas", "palette"] } -palette = "0.6.0" +palette = "0.7.0" diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index 5c4304ee..736a9d53 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -1,10 +1,14 @@ -use iced::widget::canvas::{self, Canvas, Cursor, Frame, Geometry, Path}; +use iced::alignment::{self, Alignment}; +use iced::mouse; +use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path}; use iced::widget::{column, row, text, Slider}; use iced::{ - alignment, Alignment, Color, Element, Length, Point, Rectangle, Renderer, - Sandbox, Settings, Size, Vector, + Color, Element, Length, Point, Rectangle, Renderer, Sandbox, Settings, + Size, Vector, +}; +use palette::{ + self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue, }; -use palette::{self, convert::FromColor, Hsl, Srgb}; use std::marker::PhantomData; use std::ops::RangeInclusive; @@ -49,12 +53,12 @@ impl Sandbox for ColorPalette { fn update(&mut self, message: Message) { let srgb = match message { - Message::RgbColorChanged(rgb) => palette::Srgb::from(rgb), - Message::HslColorChanged(hsl) => palette::Srgb::from_color(hsl), - Message::HsvColorChanged(hsv) => palette::Srgb::from_color(hsv), - Message::HwbColorChanged(hwb) => palette::Srgb::from_color(hwb), - Message::LabColorChanged(lab) => palette::Srgb::from_color(lab), - Message::LchColorChanged(lch) => palette::Srgb::from_color(lch), + Message::RgbColorChanged(rgb) => Rgb::from(rgb), + Message::HslColorChanged(hsl) => Rgb::from_color(hsl), + Message::HsvColorChanged(hsv) => Rgb::from_color(hsv), + Message::HwbColorChanged(hwb) => Rgb::from_color(hwb), + Message::LabColorChanged(lab) => Rgb::from_color(lab), + Message::LchColorChanged(lch) => Rgb::from_color(lch), }; self.theme = Theme::new(srgb); @@ -63,7 +67,7 @@ impl Sandbox for ColorPalette { fn view(&self) -> Element<Message> { let base = self.theme.base; - let srgb = palette::Srgb::from(base); + let srgb = Rgb::from(base); let hsl = palette::Hsl::from_color(srgb); let hsv = palette::Hsv::from_color(srgb); let hwb = palette::Hwb::from_color(srgb); @@ -95,12 +99,10 @@ struct Theme { impl Theme { pub fn new(base: impl Into<Color>) -> Theme { - use palette::{Hue, Shade}; - let base = base.into(); // Convert to HSL color for manipulation - let hsl = Hsl::from_color(Srgb::from(base)); + let hsl = Hsl::from_color(Rgb::from(base)); let lower = [ hsl.shift_hue(-135.0).lighten(0.075), @@ -119,12 +121,12 @@ impl Theme { Theme { lower: lower .iter() - .map(|&color| Srgb::from_color(color).into()) + .map(|&color| Rgb::from_color(color).into()) .collect(), base, higher: higher .iter() - .map(|&color| Srgb::from_color(color).into()) + .map(|&color| Rgb::from_color(color).into()) .collect(), canvas_cache: canvas::Cache::default(), } @@ -209,14 +211,14 @@ impl Theme { text.vertical_alignment = alignment::Vertical::Bottom; - let hsl = Hsl::from_color(Srgb::from(self.base)); + let hsl = Hsl::from_color(Rgb::from(self.base)); for i in 0..self.len() { let pct = (i as f32 + 1.0) / (self.len() as f32 + 1.0); let graded = Hsl { lightness: 1.0 - pct, ..hsl }; - let color: Color = Srgb::from_color(graded).into(); + let color: Color = Rgb::from_color(graded).into(); let anchor = Point { x: (i as f32) * box_size.width, @@ -246,7 +248,7 @@ impl<Message> canvas::Program<Message> for Theme { renderer: &Renderer, _theme: &iced::Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| { self.draw(frame); @@ -352,7 +354,7 @@ impl ColorSpace for palette::Hsl { fn components(&self) -> [f32; 3] { [ - self.hue.to_positive_degrees(), + self.hue.into_positive_degrees(), self.saturation, self.lightness, ] @@ -361,7 +363,7 @@ impl ColorSpace for palette::Hsl { fn to_string(&self) -> String { format!( "hsl({:.1}, {:.1}%, {:.1}%)", - self.hue.to_positive_degrees(), + self.hue.into_positive_degrees(), 100.0 * self.saturation, 100.0 * self.lightness ) @@ -378,13 +380,17 @@ impl ColorSpace for palette::Hsv { } fn components(&self) -> [f32; 3] { - [self.hue.to_positive_degrees(), self.saturation, self.value] + [ + self.hue.into_positive_degrees(), + self.saturation, + self.value, + ] } fn to_string(&self) -> String { format!( "hsv({:.1}, {:.1}%, {:.1}%)", - self.hue.to_positive_degrees(), + self.hue.into_positive_degrees(), 100.0 * self.saturation, 100.0 * self.value ) @@ -406,7 +412,7 @@ impl ColorSpace for palette::Hwb { fn components(&self) -> [f32; 3] { [ - self.hue.to_positive_degrees(), + self.hue.into_positive_degrees(), self.whiteness, self.blackness, ] @@ -415,7 +421,7 @@ impl ColorSpace for palette::Hwb { fn to_string(&self) -> String { format!( "hwb({:.1}, {:.1}%, {:.1}%)", - self.hue.to_positive_degrees(), + self.hue.into_positive_degrees(), 100.0 * self.whiteness, 100.0 * self.blackness ) @@ -450,7 +456,7 @@ impl ColorSpace for palette::Lch { } fn components(&self) -> [f32; 3] { - [self.l, self.chroma, self.hue.to_positive_degrees()] + [self.l, self.chroma, self.hue.into_positive_degrees()] } fn to_string(&self) -> String { @@ -458,7 +464,7 @@ impl ColorSpace for palette::Lch { "Lch({:.1}, {:.1}, {:.1})", self.l, self.chroma, - self.hue.to_positive_degrees() + self.hue.into_positive_degrees() ) } } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index b07f42ce..4b300116 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -3,7 +3,8 @@ mod quad { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{Color, Element, Length, Point, Rectangle, Size}; + use iced::mouse; + use iced::{Color, Element, Length, Rectangle, Size}; pub struct CustomQuad { size: f32, @@ -48,7 +49,7 @@ mod quad { _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { renderer.fill_quad( diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index 7854548c..713bc62d 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -12,7 +12,8 @@ mod circle { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{Color, Element, Length, Point, Rectangle, Size}; + use iced::mouse; + use iced::{Color, Element, Length, Rectangle, Size}; pub struct Circle { radius: f32, @@ -55,7 +56,7 @@ mod circle { _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, - _cursor_position: Point, + _cursor: mouse::Cursor, _viewport: &Rectangle, ) { renderer.fill_quad( diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index eab8908b..e951d734 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -204,15 +204,14 @@ fn view_controls<'a>( mod grid { use crate::Preset; + use iced::alignment; + use iced::mouse; use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - Cache, Canvas, Cursor, Frame, Geometry, Path, Text, - }; + use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text}; use iced::{ - alignment, mouse, Color, Element, Length, Point, Rectangle, Renderer, - Size, Theme, Vector, + Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, }; use rustc_hash::{FxHashMap, FxHashSet}; use std::future::Future; @@ -401,14 +400,14 @@ mod grid { interaction: &mut Interaction, event: Event, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event { *interaction = Interaction::None; } let cursor_position = - if let Some(position) = cursor.position_in(&bounds) { + if let Some(position) = cursor.position_in(bounds) { position } else { return (event::Status::Ignored, None); @@ -539,7 +538,7 @@ mod grid { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> Vec<Geometry> { let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0); @@ -568,10 +567,9 @@ mod grid { let overlay = { let mut frame = Frame::new(renderer, bounds.size()); - let hovered_cell = - cursor.position_in(&bounds).map(|position| { - Cell::at(self.project(position, frame.size())) - }); + let hovered_cell = cursor.position_in(bounds).map(|position| { + Cell::at(self.project(position, frame.size())) + }); if let Some(cell) = hovered_cell { frame.with_save(|frame| { @@ -670,13 +668,13 @@ mod grid { &self, interaction: &Interaction, bounds: Rectangle, - cursor: Cursor, + cursor: mouse::Cursor, ) -> mouse::Interaction { match interaction { Interaction::Drawing => mouse::Interaction::Crosshair, Interaction::Erasing => mouse::Interaction::Crosshair, Interaction::Panning { .. } => mouse::Interaction::Grabbing, - Interaction::None if cursor.is_over(&bounds) => { + Interaction::None if cursor.is_over(bounds) => { mouse::Interaction::Crosshair } _ => mouse::Interaction::default(), diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 5cb41184..29f78ea1 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -3,12 +3,12 @@ mod rainbow { use iced_graphics::primitive::{ColoredVertex2D, Primitive}; + use iced::advanced::graphics::color; use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{ - Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, - }; + use iced::mouse; + use iced::{Element, Length, Rectangle, Renderer, Size, Theme, Vector}; #[derive(Debug, Clone, Copy, Default)] pub struct Rainbow; @@ -43,13 +43,13 @@ mod rainbow { _theme: &Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, _viewport: &Rectangle, ) { use iced::advanced::Renderer as _; use iced_graphics::primitive::Mesh2D; - let b = layout.bounds(); + let bounds = layout.bounds(); // R O Y G B I V let color_r = [1.0, 0.0, 0.0, 1.0]; @@ -62,61 +62,61 @@ mod rainbow { let color_v = [0.75, 0.0, 0.5, 1.0]; let posn_center = { - if b.contains(cursor_position) { - [cursor_position.x - b.x, cursor_position.y - b.y] + if let Some(cursor_position) = cursor.position_in(bounds) { + [cursor_position.x, cursor_position.y] } else { - [b.width / 2.0, b.height / 2.0] + [bounds.width / 2.0, bounds.height / 2.0] } }; let posn_tl = [0.0, 0.0]; - let posn_t = [b.width / 2.0, 0.0]; - let posn_tr = [b.width, 0.0]; - let posn_r = [b.width, b.height / 2.0]; - let posn_br = [b.width, b.height]; - let posn_b = [(b.width / 2.0), b.height]; - let posn_bl = [0.0, b.height]; - let posn_l = [0.0, b.height / 2.0]; + let posn_t = [bounds.width / 2.0, 0.0]; + let posn_tr = [bounds.width, 0.0]; + let posn_r = [bounds.width, bounds.height / 2.0]; + let posn_br = [bounds.width, bounds.height]; + let posn_b = [(bounds.width / 2.0), bounds.height]; + let posn_bl = [0.0, bounds.height]; + let posn_l = [0.0, bounds.height / 2.0]; let mesh = Primitive::SolidMesh { - size: b.size(), + size: bounds.size(), buffers: Mesh2D { vertices: vec![ ColoredVertex2D { position: posn_center, - color: [1.0, 1.0, 1.0, 1.0], + color: color::pack([1.0, 1.0, 1.0, 1.0]), }, ColoredVertex2D { position: posn_tl, - color: color_r, + color: color::pack(color_r), }, ColoredVertex2D { position: posn_t, - color: color_o, + color: color::pack(color_o), }, ColoredVertex2D { position: posn_tr, - color: color_y, + color: color::pack(color_y), }, ColoredVertex2D { position: posn_r, - color: color_g, + color: color::pack(color_g), }, ColoredVertex2D { position: posn_br, - color: color_gb, + color: color::pack(color_gb), }, ColoredVertex2D { position: posn_b, - color: color_b, + color: color::pack(color_b), }, ColoredVertex2D { position: posn_bl, - color: color_i, + color: color::pack(color_i), }, ColoredVertex2D { position: posn_l, - color: color_v, + color: color::pack(color_v), }, ], indices: vec![ @@ -132,9 +132,12 @@ mod rainbow { }, }; - renderer.with_translation(Vector::new(b.x, b.y), |renderer| { - renderer.draw_primitive(mesh); - }); + renderer.with_translation( + Vector::new(bounds.x, bounds.y), + |renderer| { + renderer.draw_primitive(mesh); + }, + ); } } diff --git a/examples/integration/Cargo.toml b/examples/integration/Cargo.toml index 2ab5d75f..22914742 100644 --- a/examples/integration/Cargo.toml +++ b/examples/integration/Cargo.toml @@ -9,7 +9,7 @@ publish = false iced_winit = { path = "../../winit" } iced_wgpu = { path = "../../wgpu" } iced_widget = { path = "../../widget" } -iced_renderer = { path = "../../renderer", features = ["wgpu", "tiny-skia"] } +iced_renderer = { path = "../../renderer", features = ["wgpu"] } env_logger = "0.10" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index c935aca7..342d4c69 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -6,6 +6,7 @@ use scene::Scene; use iced_wgpu::graphics::Viewport; use iced_wgpu::{wgpu, Backend, Renderer, Settings}; +use iced_winit::core::mouse; use iced_winit::core::renderer; use iced_winit::core::{Color, Size}; use iced_winit::runtime::program; @@ -14,7 +15,6 @@ use iced_winit::style::Theme; use iced_winit::{conversion, futures, winit, Clipboard}; use winit::{ - dpi::PhysicalPosition, event::{Event, ModifiersState, WindowEvent}, event_loop::{ControlFlow, EventLoop}, }; @@ -39,6 +39,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { .and_then(|element| element.dyn_into::<HtmlCanvasElement>().ok()) .expect("Get canvas element") }; + #[cfg(not(target_arch = "wasm32"))] env_logger::init(); @@ -58,7 +59,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { Size::new(physical_size.width, physical_size.height), window.scale_factor(), ); - let mut cursor_position = PhysicalPosition::new(-1.0, -1.0); + let mut cursor_position = None; let mut modifiers = ModifiersState::default(); let mut clipboard = Clipboard::connect(&window); @@ -165,7 +166,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { Event::WindowEvent { event, .. } => { match event { WindowEvent::CursorMoved { position, .. } => { - cursor_position = position; + cursor_position = Some(position); } WindowEvent::ModifiersChanged(new_modifiers) => { modifiers = new_modifiers; @@ -194,13 +195,20 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { // We update iced let _ = state.update( viewport.logical_size(), - conversion::cursor_position( - cursor_position, - viewport.scale_factor(), - ), + cursor_position + .map(|p| { + conversion::cursor_position( + p, + viewport.scale_factor(), + ) + }) + .map(mouse::Cursor::Available) + .unwrap_or(mouse::Cursor::Unavailable), &mut renderer, &Theme::Dark, - &renderer::Style { text_color: Color::WHITE }, + &renderer::Style { + text_color: Color::WHITE, + }, &mut clipboard, &mut debug, ); @@ -242,7 +250,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { let program = state.program(); - let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default()); + let view = frame.texture.create_view( + &wgpu::TextureViewDescriptor::default(), + ); { // We clear the frame @@ -275,15 +285,18 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { frame.present(); // Update the mouse cursor - window.set_cursor_icon( - iced_winit::conversion::mouse_interaction( - state.mouse_interaction(), - ), - ); + window.set_cursor_icon( + iced_winit::conversion::mouse_interaction( + state.mouse_interaction(), + ), + ); } Err(error) => match error { wgpu::SurfaceError::OutOfMemory => { - panic!("Swapchain error: {error}. Rendering cannot continue.") + panic!( + "Swapchain error: {error}. \ + Rendering cannot continue." + ) } _ => { // Try rendering again next frame. diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index f48afb69..7fcbbfe4 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -1,12 +1,15 @@ +use iced::executor; +use iced::keyboard; +use iced::subscription::{self, Subscription}; +use iced::theme; use iced::widget::{ - self, button, column, container, horizontal_space, row, text, text_input, -}; -use iced::{ - executor, keyboard, subscription, theme, Alignment, Application, Command, - Element, Event, Length, Settings, Subscription, + self, button, column, container, horizontal_space, pick_list, row, text, + text_input, }; +use iced::{Alignment, Application, Command, Element, Event, Length, Settings}; -use self::modal::Modal; +use modal::Modal; +use std::fmt; pub fn main() -> iced::Result { App::run(Settings::default()) @@ -17,6 +20,7 @@ struct App { show_modal: bool, email: String, password: String, + plan: Plan, } #[derive(Debug, Clone)] @@ -25,6 +29,7 @@ enum Message { HideModal, Email(String), Password(String), + Plan(Plan), Submit, Event(Event), } @@ -65,6 +70,10 @@ impl Application for App { self.password = password; Command::none() } + Message::Plan(plan) => { + self.plan = plan; + Command::none() + } Message::Submit => { if !self.email.is_empty() && !self.password.is_empty() { self.hide_modal(); @@ -148,6 +157,16 @@ impl Application for App { .padding(5), ] .spacing(5), + column![ + text("Plan").size(12), + pick_list( + Plan::ALL, + Some(self.plan), + Message::Plan + ) + .padding(5), + ] + .spacing(5), button(text("Submit")).on_press(Message::HideModal), ] .spacing(10) @@ -175,6 +194,29 @@ impl App { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +enum Plan { + #[default] + Basic, + Pro, + Enterprise, +} + +impl Plan { + pub const ALL: &[Self] = &[Self::Basic, Self::Pro, Self::Enterprise]; +} + +impl fmt::Display for Plan { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Plan::Basic => "Basic", + Plan::Pro => "Pro", + Plan::Enterprise => "Enterprise", + } + .fmt(f) + } +} + mod modal { use iced::advanced::layout::{self, Layout}; use iced::advanced::overlay; @@ -254,7 +296,7 @@ mod modal { state: &mut widget::Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -263,7 +305,7 @@ mod modal { &mut state.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -277,7 +319,7 @@ mod modal { theme: &<Renderer as advanced::Renderer>::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.base.as_widget().draw( @@ -286,7 +328,7 @@ mod modal { theme, style, layout, - cursor_position, + cursor, viewport, ); } @@ -312,14 +354,14 @@ mod modal { &self, state: &widget::Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.base.as_widget().mouse_interaction( &state.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -377,7 +419,7 @@ mod modal { &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -389,7 +431,7 @@ mod modal { mouse::Button::Left, )) = &event { - if !content_bounds.contains(cursor_position) { + if !cursor.is_over(content_bounds) { shell.publish(message.clone()); return event::Status::Captured; } @@ -400,7 +442,7 @@ mod modal { self.tree, event, layout.children().next().unwrap(), - cursor_position, + cursor, renderer, clipboard, shell, @@ -413,12 +455,12 @@ mod modal { theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border_radius: renderer::BorderRadius::from(0.0), + border_radius: Default::default(), border_width: 0.0, border_color: Color::TRANSPARENT, }, @@ -434,7 +476,7 @@ mod modal { theme, style, layout.children().next().unwrap(), - cursor_position, + cursor, &layout.bounds(), ); } @@ -456,18 +498,30 @@ mod modal { fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( self.tree, layout.children().next().unwrap(), - cursor_position, + cursor, viewport, renderer, ) } + + fn overlay<'c>( + &'c mut self, + layout: Layout<'_>, + renderer: &Renderer, + ) -> Option<overlay::Element<'c, Message, Renderer>> { + self.content.as_widget_mut().overlay( + self.tree, + layout.children().next().unwrap(), + renderer, + ) + } } impl<'a, Message, Renderer> From<Modal<'a, Message, Renderer>> diff --git a/examples/modern_art/Cargo.toml b/examples/modern_art/Cargo.toml deleted file mode 100644 index 4242d209..00000000 --- a/examples/modern_art/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "modern_art" -version = "0.1.0" -authors = ["Bingus <shankern@protonmail.com>"] -edition = "2021" -publish = false - -[dependencies] -iced = { path = "../..", features = ["canvas", "tokio", "debug"] } -rand = "0.8.5" -env_logger = "0.9" diff --git a/examples/modern_art/src/main.rs b/examples/modern_art/src/main.rs deleted file mode 100644 index a43a2b2b..00000000 --- a/examples/modern_art/src/main.rs +++ /dev/null @@ -1,143 +0,0 @@ -use iced::widget::canvas::{ - self, gradient::Location, gradient::Position, Cache, Canvas, Cursor, Frame, - Geometry, Gradient, -}; -use iced::{ - executor, Application, Color, Command, Element, Length, Point, Rectangle, - Renderer, Settings, Size, Theme, -}; -use rand::{thread_rng, Rng}; - -fn main() -> iced::Result { - env_logger::builder().format_timestamp(None).init(); - - ModernArt::run(Settings { - antialiasing: true, - ..Settings::default() - }) -} - -#[derive(Debug, Clone, Copy)] -enum Message {} - -struct ModernArt { - cache: Cache, -} - -impl Application for ModernArt { - type Executor = executor::Default; - type Message = Message; - type Theme = Theme; - type Flags = (); - - fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) { - ( - ModernArt { - cache: Default::default(), - }, - Command::none(), - ) - } - - fn title(&self) -> String { - String::from("Modern Art") - } - - fn update(&mut self, _message: Message) -> Command<Message> { - Command::none() - } - - fn view(&self) -> Element<'_, Self::Message, Renderer<Self::Theme>> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -impl<Message> canvas::Program<Message, Renderer> for ModernArt { - type State = (); - - fn draw( - &self, - _state: &Self::State, - renderer: &Renderer, - _theme: &Theme, - bounds: Rectangle, - _cursor: Cursor, - ) -> Vec<Geometry> { - let geometry = self.cache.draw(renderer, bounds.size(), |frame| { - let num_squares = thread_rng().gen_range(0..1200); - - let mut i = 0; - while i <= num_squares { - generate_box(frame, bounds.size()); - i += 1; - } - }); - - vec![geometry] - } -} - -fn random_direction() -> Location { - match thread_rng().gen_range(0..8) { - 0 => Location::TopLeft, - 1 => Location::Top, - 2 => Location::TopRight, - 3 => Location::Right, - 4 => Location::BottomRight, - 5 => Location::Bottom, - 6 => Location::BottomLeft, - 7 => Location::Left, - _ => Location::TopLeft, - } -} - -fn generate_box(frame: &mut Frame, bounds: Size) -> bool { - let solid = rand::random::<bool>(); - - let random_color = || -> Color { - Color::from_rgb( - thread_rng().gen_range(0.0..1.0), - thread_rng().gen_range(0.0..1.0), - thread_rng().gen_range(0.0..1.0), - ) - }; - - let gradient = |top_left: Point, size: Size| -> Gradient { - let mut builder = Gradient::linear(Position::Relative { - top_left, - size, - start: random_direction(), - end: random_direction(), - }); - let stops = thread_rng().gen_range(1..15u32); - - let mut i = 0; - while i <= stops { - builder = builder.add_stop(i as f32 / stops as f32, random_color()); - i += 1; - } - - builder.build().unwrap() - }; - - let top_left = Point::new( - thread_rng().gen_range(0.0..bounds.width), - thread_rng().gen_range(0.0..bounds.height), - ); - - let size = Size::new( - thread_rng().gen_range(50.0..200.0), - thread_rng().gen_range(50.0..200.0), - ); - - if solid { - frame.fill_rectangle(top_left, size, random_color()); - } else { - frame.fill_rectangle(top_left, size, gradient(top_left, size)); - }; - - solid -} diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs index 7df6c929..2830b78d 100644 --- a/examples/multitouch/src/main.rs +++ b/examples/multitouch/src/main.rs @@ -1,9 +1,10 @@ //! This example shows how to use touch events in `Canvas` to draw //! a circle around each fingertip. This only works on touch-enabled //! computers like Microsoft Surface. +use iced::mouse; use iced::widget::canvas::event; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{self, Canvas, Cursor, Geometry}; +use iced::widget::canvas::{self, Canvas, Geometry}; use iced::{ executor, touch, window, Application, Color, Command, Element, Length, Point, Rectangle, Renderer, Settings, Subscription, Theme, @@ -103,7 +104,7 @@ impl canvas::Program<Message, Renderer> for State { _state: &mut Self::State, event: event::Event, _bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { match event { event::Event::Touch(touch_event) => match touch_event { @@ -128,7 +129,7 @@ impl canvas::Program<Message, Renderer> for State { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<Geometry> { let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { if self.fingers.len() < 2 { diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index dfb80853..54c36d69 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -108,8 +108,9 @@ impl Application for Example { Message::Dragged(pane_grid::DragEvent::Dropped { pane, target, + region, }) => { - self.panes.swap(&pane, &target); + self.panes.split_with(&target, &pane, region); } Message::Dragged(_) => {} Message::TogglePin(pane) => { @@ -255,6 +256,7 @@ fn handle_hotkey(key_code: keyboard::KeyCode) -> Option<Message> { } } +#[derive(Clone, Copy)] struct Pane { id: usize, pub is_pinned: bool, @@ -298,7 +300,7 @@ fn view_content<'a>( ) ] .spacing(5) - .max_width(150); + .max_width(160); if total_panes > 1 && !is_pinned { controls = controls.push( diff --git a/examples/screenshot/Cargo.toml b/examples/screenshot/Cargo.toml new file mode 100644 index 00000000..b79300b7 --- /dev/null +++ b/examples/screenshot/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "screenshot" +version = "0.1.0" +authors = ["Bingus <shankern@protonmail.com>"] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../..", features = ["debug", "image", "advanced"] } +image = { version = "0.24.6", features = ["png"]} +env_logger = "0.10.0" diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs new file mode 100644 index 00000000..83824535 --- /dev/null +++ b/examples/screenshot/src/main.rs @@ -0,0 +1,320 @@ +use iced::alignment; +use iced::keyboard::KeyCode; +use iced::theme::{Button, Container}; +use iced::widget::{button, column, container, image, row, text, text_input}; +use iced::window::screenshot::{self, Screenshot}; +use iced::{ + event, executor, keyboard, subscription, Alignment, Application, Command, + ContentFit, Element, Event, Length, Rectangle, Renderer, Subscription, + Theme, +}; + +use ::image as img; +use ::image::ColorType; + +fn main() -> iced::Result { + env_logger::builder().format_timestamp(None).init(); + + Example::run(iced::Settings::default()) +} + +struct Example { + screenshot: Option<Screenshot>, + saved_png_path: Option<Result<String, PngError>>, + png_saving: bool, + crop_error: Option<screenshot::CropError>, + x_input_value: Option<u32>, + y_input_value: Option<u32>, + width_input_value: Option<u32>, + height_input_value: Option<u32>, +} + +#[derive(Clone, Debug)] +enum Message { + Crop, + Screenshot, + ScreenshotData(Screenshot), + Png, + PngSaved(Result<String, PngError>), + XInputChanged(Option<u32>), + YInputChanged(Option<u32>), + WidthInputChanged(Option<u32>), + HeightInputChanged(Option<u32>), +} + +impl Application for Example { + type Executor = executor::Default; + type Message = Message; + type Theme = Theme; + type Flags = (); + + fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) { + ( + Example { + screenshot: None, + saved_png_path: None, + png_saving: false, + crop_error: None, + x_input_value: None, + y_input_value: None, + width_input_value: None, + height_input_value: None, + }, + Command::none(), + ) + } + + fn title(&self) -> String { + "Screenshot".to_string() + } + + fn update(&mut self, message: Self::Message) -> Command<Self::Message> { + match message { + Message::Screenshot => { + return iced::window::screenshot(Message::ScreenshotData); + } + Message::ScreenshotData(screenshot) => { + self.screenshot = Some(screenshot); + } + Message::Png => { + if let Some(screenshot) = &self.screenshot { + self.png_saving = true; + + return Command::perform( + save_to_png(screenshot.clone()), + Message::PngSaved, + ); + } + } + Message::PngSaved(res) => { + self.png_saving = false; + self.saved_png_path = Some(res); + } + Message::XInputChanged(new_value) => { + self.x_input_value = new_value; + } + Message::YInputChanged(new_value) => { + self.y_input_value = new_value; + } + Message::WidthInputChanged(new_value) => { + self.width_input_value = new_value; + } + Message::HeightInputChanged(new_value) => { + self.height_input_value = new_value; + } + Message::Crop => { + if let Some(screenshot) = &self.screenshot { + let cropped = screenshot.crop(Rectangle::<u32> { + x: self.x_input_value.unwrap_or(0), + y: self.y_input_value.unwrap_or(0), + width: self.width_input_value.unwrap_or(0), + height: self.height_input_value.unwrap_or(0), + }); + + match cropped { + Ok(screenshot) => { + self.screenshot = Some(screenshot); + self.crop_error = None; + } + Err(crop_error) => { + self.crop_error = Some(crop_error); + } + } + } + } + } + + Command::none() + } + + fn view(&self) -> Element<'_, Self::Message, Renderer<Self::Theme>> { + let image: Element<Message> = if let Some(screenshot) = &self.screenshot + { + image(image::Handle::from_pixels( + screenshot.size.width, + screenshot.size.height, + screenshot.clone(), + )) + .content_fit(ContentFit::Contain) + .width(Length::Fill) + .height(Length::Fill) + .into() + } else { + text("Press the button to take a screenshot!").into() + }; + + let image = container(image) + .padding(10) + .style(Container::Box) + .width(Length::FillPortion(2)) + .height(Length::Fill) + .center_x() + .center_y(); + + let crop_origin_controls = row![ + text("X:") + .vertical_alignment(alignment::Vertical::Center) + .width(30), + numeric_input("0", self.x_input_value).map(Message::XInputChanged), + text("Y:") + .vertical_alignment(alignment::Vertical::Center) + .width(30), + numeric_input("0", self.y_input_value).map(Message::YInputChanged) + ] + .spacing(10) + .align_items(Alignment::Center); + + let crop_dimension_controls = row![ + text("W:") + .vertical_alignment(alignment::Vertical::Center) + .width(30), + numeric_input("0", self.width_input_value) + .map(Message::WidthInputChanged), + text("H:") + .vertical_alignment(alignment::Vertical::Center) + .width(30), + numeric_input("0", self.height_input_value) + .map(Message::HeightInputChanged) + ] + .spacing(10) + .align_items(Alignment::Center); + + let mut crop_controls = + column![crop_origin_controls, crop_dimension_controls] + .spacing(10) + .align_items(Alignment::Center); + + if let Some(crop_error) = &self.crop_error { + crop_controls = crop_controls + .push(text(format!("Crop error! \n{}", crop_error))); + } + + let mut controls = column![ + column![ + button(centered_text("Screenshot!")) + .padding([10, 20, 10, 20]) + .width(Length::Fill) + .on_press(Message::Screenshot), + if !self.png_saving { + button(centered_text("Save as png")).on_press_maybe( + self.screenshot.is_some().then(|| Message::Png), + ) + } else { + button(centered_text("Saving...")).style(Button::Secondary) + } + .style(Button::Secondary) + .padding([10, 20, 10, 20]) + .width(Length::Fill) + ] + .spacing(10), + column![ + crop_controls, + button(centered_text("Crop")) + .on_press(Message::Crop) + .style(Button::Destructive) + .padding([10, 20, 10, 20]) + .width(Length::Fill), + ] + .spacing(10) + .align_items(Alignment::Center), + ] + .spacing(40); + + if let Some(png_result) = &self.saved_png_path { + let msg = match png_result { + Ok(path) => format!("Png saved as: {:?}!", path), + Err(msg) => { + format!("Png could not be saved due to:\n{:?}", msg) + } + }; + + controls = controls.push(text(msg)); + } + + let side_content = container(controls) + .align_x(alignment::Horizontal::Center) + .width(Length::FillPortion(1)) + .height(Length::Fill) + .center_y() + .center_x(); + + let content = row![side_content, image] + .spacing(10) + .width(Length::Fill) + .height(Length::Fill) + .align_items(Alignment::Center); + + container(content) + .width(Length::Fill) + .height(Length::Fill) + .padding(10) + .center_x() + .center_y() + .into() + } + + fn subscription(&self) -> Subscription<Self::Message> { + subscription::events_with(|event, status| { + if let event::Status::Captured = status { + return None; + } + + if let Event::Keyboard(keyboard::Event::KeyPressed { + key_code: KeyCode::F5, + .. + }) = event + { + Some(Message::Screenshot) + } else { + None + } + }) + } +} + +async fn save_to_png(screenshot: Screenshot) -> Result<String, PngError> { + let path = "screenshot.png".to_string(); + img::save_buffer( + &path, + &screenshot.bytes, + screenshot.size.width, + screenshot.size.height, + ColorType::Rgba8, + ) + .map(|_| path) + .map_err(|err| PngError(format!("{:?}", err))) +} + +#[derive(Clone, Debug)] +struct PngError(String); + +fn numeric_input( + placeholder: &str, + value: Option<u32>, +) -> Element<'_, Option<u32>> { + text_input( + placeholder, + &value + .as_ref() + .map(ToString::to_string) + .unwrap_or_else(String::new), + ) + .on_input(move |text| { + if text.is_empty() { + None + } else if let Ok(new_value) = text.parse() { + Some(new_value) + } else { + value + } + }) + .width(40) + .into() +} + +fn centered_text(content: &str) -> Element<'_, Message> { + text(content) + .width(Length::Fill) + .horizontal_alignment(alignment::Horizontal::Center) + .into() +} diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index 97344c94..3038661e 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -289,18 +289,13 @@ impl Application for ScrollableDemo { } Direction::Horizontal => { progress_bar(0.0..=1.0, self.current_scroll_offset.x) - .style(theme::ProgressBar::Custom(Box::new( - ProgressBarCustomStyle, - ))) + .style(progress_bar_custom_style) .into() } Direction::Multi => column![ progress_bar(0.0..=1.0, self.current_scroll_offset.y), - progress_bar(0.0..=1.0, self.current_scroll_offset.x).style( - theme::ProgressBar::Custom(Box::new( - ProgressBarCustomStyle, - )) - ) + progress_bar(0.0..=1.0, self.current_scroll_offset.x) + .style(progress_bar_custom_style) ] .spacing(10) .into(), @@ -356,12 +351,12 @@ impl scrollable::StyleSheet for ScrollbarCustomStyle { background: style .active(&theme::Scrollable::default()) .background, - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Default::default(), scroller: Scroller { color: Color::from_rgb8(250, 85, 134), - border_radius: 0.0, + border_radius: 0.0.into(), border_width: 0.0, border_color: Default::default(), }, @@ -372,16 +367,10 @@ impl scrollable::StyleSheet for ScrollbarCustomStyle { } } -struct ProgressBarCustomStyle; - -impl progress_bar::StyleSheet for ProgressBarCustomStyle { - type Style = Theme; - - fn appearance(&self, style: &Self::Style) -> progress_bar::Appearance { - progress_bar::Appearance { - background: style.extended_palette().background.strong.color.into(), - bar: Color::from_rgb8(250, 85, 134).into(), - border_radius: 0.0, - } +fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Appearance { + progress_bar::Appearance { + background: theme.extended_palette().background.strong.color.into(), + bar: Color::from_rgb8(250, 85, 134).into(), + border_radius: 0.0.into(), } } diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index 4faac6d6..885d3c63 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use iced::executor; +use iced::mouse; use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::{self, Canvas}; use iced::widget::{column, row, slider, text}; @@ -105,14 +106,14 @@ impl canvas::Program<Message> for SierpinskiGraph { _state: &mut Self::State, event: Event, bounds: Rectangle, - cursor: canvas::Cursor, + cursor: mouse::Cursor, ) -> (event::Status, Option<Message>) { - let cursor_position = - if let Some(position) = cursor.position_in(&bounds) { - position - } else { - return (event::Status::Ignored, None); - }; + let cursor_position = if let Some(position) = cursor.position_in(bounds) + { + position + } else { + return (event::Status::Ignored, None); + }; match event { Event::Mouse(mouse_event) => { @@ -137,7 +138,7 @@ impl canvas::Program<Message> for SierpinskiGraph { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: canvas::Cursor, + _cursor: mouse::Cursor, ) -> Vec<canvas::Geometry> { let geom = self.cache.draw(renderer, bounds.size(), |frame| { frame.stroke( diff --git a/examples/solar_system/Cargo.toml b/examples/solar_system/Cargo.toml index 835396b0..1a98a87e 100644 --- a/examples/solar_system/Cargo.toml +++ b/examples/solar_system/Cargo.toml @@ -7,4 +7,5 @@ publish = false [dependencies] iced = { path = "../..", features = ["canvas", "tokio", "debug"] } +env_logger = "0.10.0" rand = "0.8.3" diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index f2606feb..58d06206 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -8,11 +8,12 @@ //! [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations#An_animated_solar_system use iced::application; use iced::executor; +use iced::mouse; use iced::theme::{self, Theme}; use iced::widget::canvas; -use iced::widget::canvas::gradient::{self, Gradient}; +use iced::widget::canvas::gradient; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{Cursor, Path}; +use iced::widget::canvas::Path; use iced::window; use iced::{ Application, Color, Command, Element, Length, Point, Rectangle, Renderer, @@ -22,6 +23,8 @@ use iced::{ use std::time::Instant; pub fn main() -> iced::Result { + env_logger::builder().format_timestamp(None).init(); + SolarSystem::run(Settings { antialiasing: true, ..Settings::default() @@ -159,7 +162,7 @@ impl<Message> canvas::Program<Message> for State { renderer: &Renderer, _theme: &Theme, bounds: Rectangle, - _cursor: Cursor, + _cursor: mouse::Cursor, ) -> Vec<canvas::Geometry> { use std::f32::consts::PI; @@ -208,15 +211,12 @@ impl<Message> canvas::Program<Message> for State { let earth = Path::circle(Point::ORIGIN, Self::EARTH_RADIUS); - let earth_fill = - Gradient::linear(gradient::Position::Absolute { - start: Point::new(-Self::EARTH_RADIUS, 0.0), - end: Point::new(Self::EARTH_RADIUS, 0.0), - }) - .add_stop(0.2, Color::from_rgb(0.15, 0.50, 1.0)) - .add_stop(0.8, Color::from_rgb(0.0, 0.20, 0.47)) - .build() - .expect("Build Earth fill gradient"); + let earth_fill = gradient::Linear::new( + Point::new(-Self::EARTH_RADIUS, 0.0), + Point::new(Self::EARTH_RADIUS, 0.0), + ) + .add_stop(0.2, Color::from_rgb(0.15, 0.50, 1.0)) + .add_stop(0.8, Color::from_rgb(0.0, 0.20, 0.47)); frame.fill(&earth, earth_fill); diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index e2015bac..f8a4c80a 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -127,7 +127,9 @@ impl Sandbox for Styling { let content = column![ choose_theme, horizontal_rule(38), - row![text_input, button].spacing(10), + row![text_input, button] + .spacing(10) + .align_items(Alignment::Center), slider, progress_bar, row![ diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index 9d859258..4282ddcf 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -1,10 +1,10 @@ +use iced::executor; +use iced::keyboard; +use iced::subscription::{self, Subscription}; use iced::widget::{ self, button, column, container, pick_list, row, slider, text, text_input, }; -use iced::{ - executor, keyboard, subscription, Alignment, Application, Command, Element, - Event, Length, Settings, Subscription, -}; +use iced::{Alignment, Application, Command, Element, Event, Length, Settings}; use toast::{Status, Toast}; @@ -226,7 +226,7 @@ mod toast { }; container::Appearance { - background: pair.color.into(), + background: Some(pair.color.into()), text_color: pair.text.into(), ..Default::default() } @@ -396,7 +396,7 @@ mod toast { state: &mut Tree, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -405,7 +405,7 @@ mod toast { &mut state.children[0], event, layout, - cursor_position, + cursor, renderer, clipboard, shell, @@ -419,7 +419,7 @@ mod toast { theme: &Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, ) { self.content.as_widget().draw( @@ -428,7 +428,7 @@ mod toast { theme, style, layout, - cursor_position, + cursor, viewport, ); } @@ -437,14 +437,14 @@ mod toast { &self, state: &Tree, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( &state.children[0], layout, - cursor_position, + cursor, viewport, renderer, ) @@ -523,7 +523,7 @@ mod toast { &mut self, event: Event, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, @@ -572,7 +572,7 @@ mod toast { state, event.clone(), layout, - cursor_position, + cursor, renderer, clipboard, &mut local_shell, @@ -595,7 +595,7 @@ mod toast { theme: &<Renderer as advanced::Renderer>::Theme, style: &renderer::Style, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, ) { let viewport = layout.bounds(); @@ -606,13 +606,7 @@ mod toast { .zip(layout.children()) { child.as_widget().draw( - state, - renderer, - theme, - style, - layout, - cursor_position, - &viewport, + state, renderer, theme, style, layout, cursor, &viewport, ); } } @@ -639,7 +633,7 @@ mod toast { fn mouse_interaction( &self, layout: Layout<'_>, - cursor_position: Point, + cursor: mouse::Cursor, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { @@ -649,18 +643,19 @@ mod toast { .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget().mouse_interaction( - state, - layout, - cursor_position, - viewport, - renderer, + state, layout, cursor, viewport, renderer, ) }) .max() .unwrap_or_default() } - fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool { + fn is_over( + &self, + layout: Layout<'_>, + _renderer: &Renderer, + cursor_position: Point, + ) -> bool { layout .children() .any(|layout| layout.bounds().contains(cursor_position)) diff --git a/examples/tour/Cargo.toml b/examples/tour/Cargo.toml index 39e83671..48471f2d 100644 --- a/examples/tour/Cargo.toml +++ b/examples/tour/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced = { path = "../..", features = ["image", "debug"] } -env_logger = "0.8" +env_logger = "0.10.0" diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index 9c38ad0e..13bcd5ff 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -62,11 +62,8 @@ impl Sandbox for Tour { controls = controls.push(horizontal_space(Length::Fill)); if steps.can_continue() { - controls = controls.push( - button("Next") - .on_press(Message::NextPressed) - .style(theme::Button::Primary), - ); + controls = + controls.push(button("Next").on_press(Message::NextPressed)); } let content: Element<_> = column![ |