From 5007e548ada35b56aa26d68688ded47d0ea1f25b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 Mar 2024 07:08:25 +0100 Subject: Fix redundant import in `color_palette` example --- examples/color_palette/src/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index 29337508..d9325edb 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -6,9 +6,7 @@ use iced::{ Color, Element, Font, Length, Pixels, Point, Rectangle, Renderer, Size, Vector, }; -use palette::{ - self, convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue, -}; +use palette::{convert::FromColor, rgb::Rgb, Darken, Hsl, Lighten, ShiftHue}; use std::marker::PhantomData; use std::ops::RangeInclusive; -- cgit From 3645d34d6a1ba1247238e830e9eefd52d9e5b986 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 22:27:17 +0100 Subject: Implement composable, type-safe renderer fallback --- examples/arc/src/main.rs | 10 ++++------ examples/bezier_tool/src/main.rs | 33 +++++++++++++------------------ examples/clock/src/main.rs | 8 ++++---- examples/color_palette/src/main.rs | 10 +++++----- examples/game_of_life/src/main.rs | 18 ++++++++--------- examples/geometry/src/main.rs | 4 +++- examples/layout/src/main.rs | 10 ++++++---- examples/loading_spinners/src/circular.rs | 6 ++---- examples/multitouch/src/main.rs | 10 ++++++---- examples/sierpinski_triangle/src/main.rs | 8 +++++--- examples/solar_system/src/main.rs | 7 ++++--- examples/vectorial_text/src/main.rs | 8 +++++--- 12 files changed, 67 insertions(+), 65 deletions(-) (limited to 'examples') diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index 4576404f..a7893efa 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -1,9 +1,7 @@ use std::{f32::consts::PI, time::Instant}; use iced::mouse; -use iced::widget::canvas::{ - self, stroke, Cache, Canvas, Geometry, Path, Stroke, -}; +use iced::widget::canvas::{self, stroke, Cache, Canvas, Frame, Path, Stroke}; use iced::{Element, Length, Point, Rectangle, Renderer, Subscription, Theme}; pub fn main() -> iced::Result { @@ -57,11 +55,11 @@ impl canvas::Program for Arc { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); @@ -104,6 +102,6 @@ impl canvas::Program for Arc { ); }); - vec![geometry] + renderer.draw_geometry([geometry]); } } diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index cf70bd40..e51f2a31 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -52,7 +52,7 @@ impl Example { mod bezier { use iced::mouse; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke}; + use iced::widget::canvas::{self, frame, Canvas, Frame, Path, Stroke}; use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; #[derive(Default)] @@ -138,30 +138,25 @@ mod bezier { fn draw( &self, state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, _theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) -> Vec { - let content = self.state.cache.draw( - renderer, - bounds.size(), - |frame: &mut Frame| { + ) { + let content = + self.state.cache.draw(renderer, bounds.size(), |frame| { Curve::draw_all(self.curves, frame); frame.stroke( &Path::rectangle(Point::ORIGIN, frame.size()), Stroke::default().with_width(2.0), ); - }, - ); + }); - if let Some(pending) = state { - let pending_curve = pending.draw(renderer, bounds, cursor); + renderer.draw_geometry([content]); - vec![content, pending_curve] - } else { - vec![content] + if let Some(pending) = state { + pending.draw(renderer, bounds, cursor); } } @@ -187,7 +182,7 @@ mod bezier { } impl Curve { - fn draw_all(curves: &[Curve], frame: &mut Frame) { + fn draw_all(curves: &[Curve], frame: &mut impl Frame) { let curves = Path::new(|p| { for curve in curves { p.move_to(curve.from); @@ -208,11 +203,11 @@ mod bezier { impl Pending { fn draw( &self, - renderer: &Renderer, + renderer: &mut Renderer, bounds: Rectangle, cursor: mouse::Cursor, - ) -> Geometry { - let mut frame = Frame::new(renderer, bounds.size()); + ) { + let mut frame = frame(renderer, bounds.size()); if let Some(cursor_position) = cursor.position_in(bounds) { match *self { @@ -232,7 +227,7 @@ mod bezier { }; } - frame.into_geometry() + renderer.draw_geometry([frame]); } } } diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 897f8f1b..9f78903c 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,6 +1,6 @@ use iced::alignment; use iced::mouse; -use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; +use iced::widget::canvas::{stroke, Cache, Frame, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; use iced::{ Degrees, Element, Font, Length, Point, Rectangle, Renderer, Subscription, @@ -82,11 +82,11 @@ impl canvas::Program for Clock { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { let clock = self.clock.draw(renderer, bounds.size(), |frame| { let palette = theme.extended_palette(); @@ -163,7 +163,7 @@ impl canvas::Program for Clock { }); }); - vec![clock] + renderer.draw_geometry([clock]); } } diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index d9325edb..400766ff 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -1,6 +1,6 @@ use iced::alignment::{self, Alignment}; use iced::mouse; -use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path}; +use iced::widget::canvas::{self, Canvas, Frame, Path}; use iced::widget::{column, row, text, Slider}; use iced::{ Color, Element, Font, Length, Pixels, Point, Rectangle, Renderer, Size, @@ -156,7 +156,7 @@ impl Theme { .into() } - fn draw(&self, frame: &mut Frame, text_color: Color) { + fn draw(&self, frame: &mut impl Frame, text_color: Color) { let pad = 20.0; let box_size = Size { @@ -252,18 +252,18 @@ impl canvas::Program for Theme { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, theme: &iced::Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| { let palette = theme.extended_palette(); self.draw(frame, palette.background.base.text); }); - vec![theme] + renderer.draw_geometry([theme]); } } diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index 2b0fae0b..f681b4cc 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -193,7 +193,7 @@ mod grid { use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text}; + use iced::widget::canvas::{frame, Cache, Canvas, Frame, Path, Text}; use iced::{ Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, }; @@ -516,11 +516,11 @@ mod grid { fn draw( &self, _interaction: &Interaction, - renderer: &Renderer, + renderer: &mut Renderer, _theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) -> Vec { + ) { let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0); let life = self.life_cache.draw(renderer, bounds.size(), |frame| { @@ -546,7 +546,7 @@ mod grid { }); let overlay = { - let mut frame = Frame::new(renderer, bounds.size()); + let mut frame = frame(renderer, bounds.size()); let hovered_cell = cursor.position_in(bounds).map(|position| { Cell::at(self.project(position, frame.size())) @@ -599,12 +599,10 @@ mod grid { ..text }); - frame.into_geometry() + frame.into() }; - if self.scaling < 0.2 || !self.show_lines { - vec![life, overlay] - } else { + if self.scaling >= 0.2 && self.show_lines { let grid = self.grid_cache.draw(renderer, bounds.size(), |frame| { frame.translate(center); @@ -640,7 +638,9 @@ mod grid { } }); - vec![life, grid, overlay] + renderer.draw_geometry([life, grid, overlay]); + } else { + renderer.draw_geometry([life, overlay]); } } diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 63efcbdd..16cdb86f 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -44,7 +44,9 @@ mod rainbow { cursor: mouse::Cursor, _viewport: &Rectangle, ) { - use iced::advanced::graphics::mesh::{self, Mesh, SolidVertex2D}; + use iced::advanced::graphics::mesh::{ + self, Mesh, Renderer as _, SolidVertex2D, + }; use iced::advanced::Renderer as _; let bounds = layout.bounds(); diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 713e2b70..198237f5 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -292,12 +292,14 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { - let mut frame = canvas::Frame::new(renderer, bounds.size()); + ) { + use canvas::Frame; + + let mut frame = canvas::frame(renderer, bounds.size()); let palette = theme.extended_palette(); @@ -307,7 +309,7 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { palette.background.strong.color, ); - vec![frame.into_geometry()] + renderer.draw_geometry([frame]); } } diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index 12670ed1..306988af 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -6,7 +6,7 @@ use iced::advanced::{self, Clipboard, Layout, Shell, Widget}; use iced::event; use iced::mouse; use iced::time::Instant; -use iced::widget::canvas; +use iced::widget::canvas::{self, Frame}; use iced::window::{self, RedrawRequest}; use iced::{ Background, Color, Element, Event, Length, Radians, Rectangle, Renderer, @@ -356,9 +356,7 @@ where renderer.with_translation( Vector::new(bounds.x, bounds.y), |renderer| { - use iced::advanced::graphics::geometry::Renderer as _; - - renderer.draw(vec![geometry]); + renderer.draw_geometry([geometry]); }, ); } diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs index 2453c7f5..41bd0151 100644 --- a/examples/multitouch/src/main.rs +++ b/examples/multitouch/src/main.rs @@ -5,7 +5,7 @@ use iced::mouse; use iced::touch; use iced::widget::canvas::event; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{self, Canvas, Geometry}; +use iced::widget::canvas::{self, Canvas}; use iced::{Color, Element, Length, Point, Rectangle, Renderer, Theme}; use std::collections::HashMap; @@ -83,11 +83,13 @@ impl canvas::Program for Multitouch { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { + use canvas::Frame; + let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { if self.fingers.len() < 2 { return; @@ -154,6 +156,6 @@ impl canvas::Program for Multitouch { } }); - vec![fingerweb] + renderer.draw_geometry([fingerweb]); } } diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index 07ae05d6..b440b8b4 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -107,11 +107,13 @@ impl canvas::Program for SierpinskiGraph { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { + use canvas::Frame; + let geom = self.cache.draw(renderer, bounds.size(), |frame| { frame.stroke( &canvas::Path::rectangle(Point::ORIGIN, frame.size()), @@ -139,7 +141,7 @@ impl canvas::Program for SierpinskiGraph { }); }); - vec![geom] + renderer.draw_geometry([geom]); } } diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index b5228f09..dd36b711 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -126,11 +126,12 @@ impl canvas::Program for State { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { + use canvas::Frame; use std::f32::consts::PI; let background = @@ -197,7 +198,7 @@ impl canvas::Program for State { }); }); - vec![background, system] + renderer.draw_geometry([background, system]); } } diff --git a/examples/vectorial_text/src/main.rs b/examples/vectorial_text/src/main.rs index a7391e23..9f5baac8 100644 --- a/examples/vectorial_text/src/main.rs +++ b/examples/vectorial_text/src/main.rs @@ -124,11 +124,13 @@ impl canvas::Program for State { fn draw( &self, _state: &Self::State, - renderer: &Renderer, + renderer: &mut Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) { + use canvas::Frame; + let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); let center = bounds.center(); @@ -153,7 +155,7 @@ impl canvas::Program for State { }); }); - vec![geometry] + renderer.draw_geometry([geometry]); } } -- cgit From b972ebca8f8c23d2df1b45bb26038789766a5a65 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 23:30:36 +0100 Subject: Restore `canvas::Program` API --- examples/arc/src/main.rs | 10 ++++++---- examples/bezier_tool/src/main.rs | 20 +++++++++++--------- examples/clock/src/main.rs | 10 ++++++---- examples/color_palette/src/main.rs | 8 ++++---- examples/game_of_life/src/main.rs | 12 +++++++----- examples/layout/src/main.rs | 6 +++--- examples/multitouch/src/main.rs | 8 ++++---- examples/sierpinski_triangle/src/main.rs | 8 ++++---- examples/solar_system/src/main.rs | 8 ++++---- examples/vectorial_text/src/main.rs | 6 +++--- 10 files changed, 52 insertions(+), 44 deletions(-) (limited to 'examples') diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index a7893efa..0aba82a9 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -1,7 +1,9 @@ use std::{f32::consts::PI, time::Instant}; use iced::mouse; -use iced::widget::canvas::{self, stroke, Cache, Canvas, Frame, Path, Stroke}; +use iced::widget::canvas::{ + self, stroke, Cache, Canvas, Frame, Geometry, Path, Stroke, +}; use iced::{Element, Length, Point, Rectangle, Renderer, Subscription, Theme}; pub fn main() -> iced::Result { @@ -55,11 +57,11 @@ impl canvas::Program for Arc { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); @@ -102,6 +104,6 @@ impl canvas::Program for Arc { ); }); - renderer.draw_geometry([geometry]); + vec![geometry] } } diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index e51f2a31..31d1e29c 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -52,7 +52,9 @@ impl Example { mod bezier { use iced::mouse; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{self, frame, Canvas, Frame, Path, Stroke}; + use iced::widget::canvas::{ + self, frame, Canvas, Frame, Geometry, Path, Stroke, + }; use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; #[derive(Default)] @@ -138,11 +140,11 @@ mod bezier { fn draw( &self, state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, _theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) { + ) -> Vec { let content = self.state.cache.draw(renderer, bounds.size(), |frame| { Curve::draw_all(self.curves, frame); @@ -153,10 +155,10 @@ mod bezier { ); }); - renderer.draw_geometry([content]); - if let Some(pending) = state { - pending.draw(renderer, bounds, cursor); + vec![content, pending.draw(renderer, bounds, cursor)] + } else { + vec![content] } } @@ -203,10 +205,10 @@ mod bezier { impl Pending { fn draw( &self, - renderer: &mut Renderer, + renderer: &Renderer, bounds: Rectangle, cursor: mouse::Cursor, - ) { + ) -> Geometry { let mut frame = frame(renderer, bounds.size()); if let Some(cursor_position) = cursor.position_in(bounds) { @@ -227,7 +229,7 @@ mod bezier { }; } - renderer.draw_geometry([frame]); + frame.into() } } } diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 9f78903c..468443bc 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,6 +1,8 @@ use iced::alignment; use iced::mouse; -use iced::widget::canvas::{stroke, Cache, Frame, LineCap, Path, Stroke}; +use iced::widget::canvas::{ + stroke, Cache, Frame, Geometry, LineCap, Path, Stroke, +}; use iced::widget::{canvas, container}; use iced::{ Degrees, Element, Font, Length, Point, Rectangle, Renderer, Subscription, @@ -82,11 +84,11 @@ impl canvas::Program for Clock { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { let clock = self.clock.draw(renderer, bounds.size(), |frame| { let palette = theme.extended_palette(); @@ -163,7 +165,7 @@ impl canvas::Program for Clock { }); }); - renderer.draw_geometry([clock]); + vec![clock] } } diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index 400766ff..81ad6e41 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -1,6 +1,6 @@ use iced::alignment::{self, Alignment}; use iced::mouse; -use iced::widget::canvas::{self, Canvas, Frame, Path}; +use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path}; use iced::widget::{column, row, text, Slider}; use iced::{ Color, Element, Font, Length, Pixels, Point, Rectangle, Renderer, Size, @@ -252,18 +252,18 @@ impl canvas::Program for Theme { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, theme: &iced::Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { let theme = self.canvas_cache.draw(renderer, bounds.size(), |frame| { let palette = theme.extended_palette(); self.draw(frame, palette.background.base.text); }); - renderer.draw_geometry([theme]); + vec![theme] } } diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index f681b4cc..a3d385f3 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -193,7 +193,9 @@ mod grid { use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{frame, Cache, Canvas, Frame, Path, Text}; + use iced::widget::canvas::{ + frame, Cache, Canvas, Frame, Geometry, Path, Text, + }; use iced::{ Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, }; @@ -516,11 +518,11 @@ mod grid { fn draw( &self, _interaction: &Interaction, - renderer: &mut Renderer, + renderer: &Renderer, _theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, - ) { + ) -> Vec { let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0); let life = self.life_cache.draw(renderer, bounds.size(), |frame| { @@ -638,9 +640,9 @@ mod grid { } }); - renderer.draw_geometry([life, grid, overlay]); + vec![life, grid, overlay] } else { - renderer.draw_geometry([life, overlay]); + vec![life, overlay] } } diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 198237f5..35d2d3ba 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -292,11 +292,11 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { use canvas::Frame; let mut frame = canvas::frame(renderer, bounds.size()); @@ -309,7 +309,7 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { palette.background.strong.color, ); - renderer.draw_geometry([frame]); + vec![frame.into()] } } diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs index 41bd0151..6d9039fa 100644 --- a/examples/multitouch/src/main.rs +++ b/examples/multitouch/src/main.rs @@ -5,7 +5,7 @@ use iced::mouse; use iced::touch; use iced::widget::canvas::event; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::{self, Canvas}; +use iced::widget::canvas::{self, Canvas, Geometry}; use iced::{Color, Element, Length, Point, Rectangle, Renderer, Theme}; use std::collections::HashMap; @@ -83,11 +83,11 @@ impl canvas::Program for Multitouch { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { use canvas::Frame; let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { @@ -156,6 +156,6 @@ impl canvas::Program for Multitouch { } }); - renderer.draw_geometry([fingerweb]); + vec![fingerweb] } } diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index b440b8b4..409bc718 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -1,6 +1,6 @@ use iced::mouse; use iced::widget::canvas::event::{self, Event}; -use iced::widget::canvas::{self, Canvas}; +use iced::widget::canvas::{self, Canvas, Geometry}; use iced::widget::{column, row, slider, text}; use iced::{Color, Length, Point, Rectangle, Renderer, Size, Theme}; @@ -107,11 +107,11 @@ impl canvas::Program for SierpinskiGraph { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { use canvas::Frame; let geom = self.cache.draw(renderer, bounds.size(), |frame| { @@ -141,7 +141,7 @@ impl canvas::Program for SierpinskiGraph { }); }); - renderer.draw_geometry([geom]); + vec![geom] } } diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index dd36b711..e8f94ed0 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -10,7 +10,7 @@ use iced::mouse; use iced::widget::canvas; use iced::widget::canvas::gradient; use iced::widget::canvas::stroke::{self, Stroke}; -use iced::widget::canvas::Path; +use iced::widget::canvas::{Geometry, Path}; use iced::window; use iced::{ Color, Element, Length, Point, Rectangle, Renderer, Size, Subscription, @@ -126,11 +126,11 @@ impl canvas::Program for State { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { use canvas::Frame; use std::f32::consts::PI; @@ -198,7 +198,7 @@ impl canvas::Program for State { }); }); - renderer.draw_geometry([background, system]); + vec![background, system] } } diff --git a/examples/vectorial_text/src/main.rs b/examples/vectorial_text/src/main.rs index 9f5baac8..9b605d23 100644 --- a/examples/vectorial_text/src/main.rs +++ b/examples/vectorial_text/src/main.rs @@ -124,11 +124,11 @@ impl canvas::Program for State { fn draw( &self, _state: &Self::State, - renderer: &mut Renderer, + renderer: &Renderer, theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) { + ) -> Vec { use canvas::Frame; let geometry = self.cache.draw(renderer, bounds.size(), |frame| { @@ -155,7 +155,7 @@ impl canvas::Program for State { }); }); - renderer.draw_geometry([geometry]); + vec![geometry] } } -- cgit From 53a183fe0d6aed460fbb8155ac9541757277aab3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 Mar 2024 01:35:14 +0100 Subject: Restore `canvas::Frame` API --- examples/arc/src/main.rs | 2 +- examples/bezier_tool/src/main.rs | 10 ++++------ examples/clock/src/main.rs | 4 +--- examples/color_palette/src/main.rs | 2 +- examples/game_of_life/src/main.rs | 8 +++----- examples/layout/src/main.rs | 6 ++---- examples/loading_spinners/src/circular.rs | 2 +- examples/multitouch/src/main.rs | 2 -- examples/sierpinski_triangle/src/main.rs | 2 -- examples/solar_system/src/main.rs | 1 - examples/vectorial_text/src/main.rs | 2 -- 11 files changed, 13 insertions(+), 28 deletions(-) (limited to 'examples') diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index 0aba82a9..4576404f 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -2,7 +2,7 @@ use std::{f32::consts::PI, time::Instant}; use iced::mouse; use iced::widget::canvas::{ - self, stroke, Cache, Canvas, Frame, Geometry, Path, Stroke, + self, stroke, Cache, Canvas, Geometry, Path, Stroke, }; use iced::{Element, Length, Point, Rectangle, Renderer, Subscription, Theme}; diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index 31d1e29c..289c919b 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -52,9 +52,7 @@ impl Example { mod bezier { use iced::mouse; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - self, frame, Canvas, Frame, Geometry, Path, Stroke, - }; + use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke}; use iced::{Element, Length, Point, Rectangle, Renderer, Theme}; #[derive(Default)] @@ -184,7 +182,7 @@ mod bezier { } impl Curve { - fn draw_all(curves: &[Curve], frame: &mut impl Frame) { + fn draw_all(curves: &[Curve], frame: &mut Frame) { let curves = Path::new(|p| { for curve in curves { p.move_to(curve.from); @@ -209,7 +207,7 @@ mod bezier { bounds: Rectangle, cursor: mouse::Cursor, ) -> Geometry { - let mut frame = frame(renderer, bounds.size()); + let mut frame = Frame::new(renderer, bounds.size()); if let Some(cursor_position) = cursor.position_in(bounds) { match *self { @@ -229,7 +227,7 @@ mod bezier { }; } - frame.into() + frame.into_geometry() } } } diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 468443bc..897f8f1b 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,8 +1,6 @@ use iced::alignment; use iced::mouse; -use iced::widget::canvas::{ - stroke, Cache, Frame, Geometry, LineCap, Path, Stroke, -}; +use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; use iced::{ Degrees, Element, Font, Length, Point, Rectangle, Renderer, Subscription, diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index 81ad6e41..d9325edb 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -156,7 +156,7 @@ impl Theme { .into() } - fn draw(&self, frame: &mut impl Frame, text_color: Color) { + fn draw(&self, frame: &mut Frame, text_color: Color) { let pad = 20.0; let box_size = Size { diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index a3d385f3..0716b2a4 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -193,9 +193,7 @@ mod grid { use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; - use iced::widget::canvas::{ - frame, Cache, Canvas, Frame, Geometry, Path, Text, - }; + use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text}; use iced::{ Color, Element, Length, Point, Rectangle, Renderer, Size, Theme, Vector, }; @@ -548,7 +546,7 @@ mod grid { }); let overlay = { - let mut frame = frame(renderer, bounds.size()); + let mut frame = Frame::new(renderer, bounds.size()); let hovered_cell = cursor.position_in(bounds).map(|position| { Cell::at(self.project(position, frame.size())) @@ -601,7 +599,7 @@ mod grid { ..text }); - frame.into() + frame.into_geometry() }; if self.scaling >= 0.2 && self.show_lines { diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 35d2d3ba..713e2b70 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -297,9 +297,7 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { - use canvas::Frame; - - let mut frame = canvas::frame(renderer, bounds.size()); + let mut frame = canvas::Frame::new(renderer, bounds.size()); let palette = theme.extended_palette(); @@ -309,7 +307,7 @@ fn square<'a>(size: impl Into + Copy) -> Element<'a, Message> { palette.background.strong.color, ); - vec![frame.into()] + vec![frame.into_geometry()] } } diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index 306988af..cdc6b7ac 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -6,7 +6,7 @@ use iced::advanced::{self, Clipboard, Layout, Shell, Widget}; use iced::event; use iced::mouse; use iced::time::Instant; -use iced::widget::canvas::{self, Frame}; +use iced::widget::canvas; use iced::window::{self, RedrawRequest}; use iced::{ Background, Color, Element, Event, Length, Radians, Rectangle, Renderer, diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs index 6d9039fa..2453c7f5 100644 --- a/examples/multitouch/src/main.rs +++ b/examples/multitouch/src/main.rs @@ -88,8 +88,6 @@ impl canvas::Program for Multitouch { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { - use canvas::Frame; - let fingerweb = self.cache.draw(renderer, bounds.size(), |frame| { if self.fingers.len() < 2 { return; diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index 409bc718..9cd6237f 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -112,8 +112,6 @@ impl canvas::Program for SierpinskiGraph { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { - use canvas::Frame; - let geom = self.cache.draw(renderer, bounds.size(), |frame| { frame.stroke( &canvas::Path::rectangle(Point::ORIGIN, frame.size()), diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index e8f94ed0..deb211d8 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -131,7 +131,6 @@ impl canvas::Program for State { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { - use canvas::Frame; use std::f32::consts::PI; let background = diff --git a/examples/vectorial_text/src/main.rs b/examples/vectorial_text/src/main.rs index 9b605d23..a7391e23 100644 --- a/examples/vectorial_text/src/main.rs +++ b/examples/vectorial_text/src/main.rs @@ -129,8 +129,6 @@ impl canvas::Program for State { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { - use canvas::Frame; - let geometry = self.cache.draw(renderer, bounds.size(), |frame| { let palette = theme.palette(); let center = bounds.center(); -- cgit From 1f13a91361258a1607c71f4840a26a6437f88612 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 Mar 2024 05:27:31 +0100 Subject: Make `iced_tiny_skia` optional with a `tiny-skia` feature --- examples/loading_spinners/src/circular.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index cdc6b7ac..de728af2 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -356,7 +356,9 @@ where renderer.with_translation( Vector::new(bounds.x, bounds.y), |renderer| { - renderer.draw_geometry([geometry]); + use iced::advanced::graphics::geometry::Renderer as _; + + renderer.draw_geometry(geometry); }, ); } -- cgit From 999ad2d288a9354f045bb2e1b838014b3d302779 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 23 Mar 2024 19:23:08 +0100 Subject: Try catalog theming approach with `Button` --- examples/component/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index 43ba3187..d5626087 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -74,7 +74,7 @@ mod numeric_input { impl Component for NumericInput where Theme: text::DefaultStyle - + button::DefaultStyle + + button::Catalog + text_input::DefaultStyle + 'static, { @@ -152,7 +152,7 @@ mod numeric_input { for Element<'a, Message, Theme> where Theme: text::DefaultStyle - + button::DefaultStyle + + button::Catalog + text_input::DefaultStyle + 'static, Message: 'a, -- cgit From e657dc2ecd2ffa72c0abd87f9a59dcc1acbc7083 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 24 Mar 2024 02:08:20 +0100 Subject: Fine-tune `Catalog` approach for `button`, `checkbox`, and `svg` --- examples/svg/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index cc686dca..0dcf9bc1 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -31,7 +31,7 @@ impl Tiger { )); let svg = svg(handle).width(Length::Fill).height(Length::Fill).style( - |_theme, _status| svg::Appearance { + |_theme, _status| svg::Style { color: if self.apply_color_filter { Some(color!(0x0000ff)) } else { -- cgit From f0ae9a0c38c2532220a7460916604914db94c078 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 24 Mar 2024 05:03:09 +0100 Subject: Use `Catalog` approach for all widgets --- examples/component/src/main.rs | 10 ++-------- examples/gradient/src/main.rs | 2 +- examples/layout/src/main.rs | 8 ++++---- examples/pane_grid/src/main.rs | 28 ++++++++-------------------- examples/scrollable/src/main.rs | 4 ++-- examples/toast/src/main.rs | 24 ++++++------------------ 6 files changed, 23 insertions(+), 53 deletions(-) (limited to 'examples') diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index d5626087..b2c71b3f 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -73,10 +73,7 @@ mod numeric_input { impl Component for NumericInput where - Theme: text::DefaultStyle - + button::Catalog - + text_input::DefaultStyle - + 'static, + Theme: text::Catalog + button::Catalog + text_input::Catalog + 'static, { type State = (); type Event = Event; @@ -151,10 +148,7 @@ mod numeric_input { impl<'a, Message, Theme> From> for Element<'a, Message, Theme> where - Theme: text::DefaultStyle - + button::Catalog - + text_input::DefaultStyle - + 'static, + Theme: text::Catalog + button::Catalog + text_input::Catalog + 'static, Message: 'a, { fn from(numeric_input: NumericInput) -> Self { diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs index 22c21cdd..2b906c32 100644 --- a/examples/gradient/src/main.rs +++ b/examples/gradient/src/main.rs @@ -60,7 +60,7 @@ impl Gradient { } = *self; let gradient_box = container(horizontal_space()) - .style(move |_theme, _status| { + .style(move |_theme| { let gradient = gradient::Linear::new(angle) .add_stop(0.0, start) .add_stop(1.0, end); diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 713e2b70..66d79091 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -81,10 +81,10 @@ impl Layout { } else { self.example.view() }) - .style(|theme, _status| { + .style(|theme| { let palette = theme.extended_palette(); - container::Appearance::default() + container::Style::default() .with_border(palette.background.strong.color, 4.0) }) .padding(4) @@ -245,10 +245,10 @@ fn application<'a>() -> Element<'a, Message> { .padding(10) .align_items(Alignment::Center), ) - .style(|theme, _status| { + .style(|theme| { let palette = theme.extended_palette(); - container::Appearance::default() + container::Style::default() .with_border(palette.background.strong.color, 1) }); diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index 829996d8..17112785 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -338,39 +338,30 @@ mod style { use iced::widget::container; use iced::{Border, Theme}; - pub fn title_bar_active( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + pub fn title_bar_active(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); - container::Appearance { + container::Style { text_color: Some(palette.background.strong.text), background: Some(palette.background.strong.color.into()), ..Default::default() } } - pub fn title_bar_focused( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + pub fn title_bar_focused(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); - container::Appearance { + container::Style { text_color: Some(palette.primary.strong.text), background: Some(palette.primary.strong.color.into()), ..Default::default() } } - pub fn pane_active( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + pub fn pane_active(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); - container::Appearance { + container::Style { background: Some(palette.background.weak.color.into()), border: Border { width: 2.0, @@ -381,13 +372,10 @@ mod style { } } - pub fn pane_focused( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + pub fn pane_focused(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); - container::Appearance { + container::Style { background: Some(palette.background.weak.color.into()), border: Border { width: 2.0, diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index 240ae908..c02e754b 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -341,8 +341,8 @@ impl Default for ScrollableDemo { } } -fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Appearance { - progress_bar::Appearance { +fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Style { + progress_bar::Style { background: theme.extended_palette().background.strong.color.into(), bar: Color::from_rgb8(250, 85, 134).into(), border: Border::default(), diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index fdae1dc1..9968962c 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -651,45 +651,33 @@ mod toast { } } - fn styled(pair: theme::palette::Pair) -> container::Appearance { - container::Appearance { + fn styled(pair: theme::palette::Pair) -> container::Style { + container::Style { background: Some(pair.color.into()), text_color: pair.text.into(), ..Default::default() } } - fn primary( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + fn primary(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); styled(palette.primary.weak) } - fn secondary( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + fn secondary(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); styled(palette.secondary.weak) } - fn success( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + fn success(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); styled(palette.success.weak) } - fn danger( - theme: &Theme, - _status: container::Status, - ) -> container::Appearance { + fn danger(theme: &Theme) -> container::Style { let palette = theme.extended_palette(); styled(palette.danger.weak) -- cgit From 1d83e59e8ab51d403baee0daa878644c6a37be3f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 1 Apr 2024 21:36:08 +0200 Subject: Specialize `widget::text` helper with custom `IntoContent` trait --- examples/lazy/src/main.rs | 2 +- examples/tour/src/main.rs | 6 +++--- examples/websocket/src/main.rs | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/lazy/src/main.rs b/examples/lazy/src/main.rs index 2d53df93..c3f6b8de 100644 --- a/examples/lazy/src/main.rs +++ b/examples/lazy/src/main.rs @@ -173,7 +173,7 @@ impl App { .style(button::danger); row![ - text(&item.name).color(item.color), + text(item.name.clone()).color(item.color), horizontal_space(), pick_list(Color::ALL, Some(item.color), move |color| { Message::ItemColorChanged(item.clone(), color) diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index a88c0dba..e3a2ca87 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -357,7 +357,7 @@ impl<'a> Step { .into() } - fn container(title: &str) -> Column<'a, StepMessage> { + fn container(title: &str) -> Column<'_, StepMessage> { column![text(title).size(50)].spacing(20) } @@ -589,7 +589,7 @@ impl<'a> Step { value: &str, is_secure: bool, is_showing_icon: bool, - ) -> Column<'a, StepMessage> { + ) -> Column<'_, StepMessage> { let mut text_input = text_input("Type something to continue...", value) .on_input(StepMessage::InputChanged) .padding(10) @@ -674,7 +674,7 @@ fn ferris<'a>( .center_x() } -fn padded_button<'a, Message: Clone>(label: &str) -> Button<'a, Message> { +fn padded_button(label: &str) -> Button<'_, Message> { button(text(label)).padding([12, 24]) } diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index 460d9a08..ef450524 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -97,7 +97,11 @@ impl WebSocket { } else { scrollable( column( - self.messages.iter().cloned().map(text).map(Element::from), + self.messages + .iter() + .map(ToString::to_string) + .map(text) + .map(Element::from), ) .spacing(10), ) -- cgit From b8d5df28172a9f50c8b48123df05a336801f2bdc Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 1 Apr 2024 21:36:52 +0200 Subject: Reintroduce old `text` helper as `value` helper --- examples/websocket/src/main.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index ef450524..369ae820 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -2,7 +2,7 @@ mod echo; use iced::alignment::{self, Alignment}; use iced::widget::{ - button, column, container, row, scrollable, text, text_input, + button, column, container, row, scrollable, text, text_input, value, }; use iced::{color, Command, Element, Length, Subscription}; use once_cell::sync::Lazy; @@ -96,14 +96,8 @@ impl WebSocket { .into() } else { scrollable( - column( - self.messages - .iter() - .map(ToString::to_string) - .map(text) - .map(Element::from), - ) - .spacing(10), + column(self.messages.iter().map(value).map(Element::from)) + .spacing(10), ) .id(MESSAGE_LOG.clone()) .height(Length::Fill) -- cgit From 488cac714896002791f3c7b9a99181310c1d1b5c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 2 Apr 2024 09:29:16 +0200 Subject: Avoid extra text allocations in `websocket` example --- examples/websocket/src/echo.rs | 23 ++++++++++++++++------- examples/websocket/src/main.rs | 4 ++-- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/websocket/src/echo.rs b/examples/websocket/src/echo.rs index 281ed4bd..cd32cb66 100644 --- a/examples/websocket/src/echo.rs +++ b/examples/websocket/src/echo.rs @@ -2,6 +2,7 @@ pub mod server; use iced::futures; use iced::subscription::{self, Subscription}; +use iced::widget::text; use futures::channel::mpsc; use futures::sink::SinkExt; @@ -136,16 +137,24 @@ impl Message { pub fn disconnected() -> Self { Message::Disconnected } + + pub fn as_str(&self) -> &str { + match self { + Message::Connected => "Connected successfully!", + Message::Disconnected => "Connection lost... Retrying...", + Message::User(message) => message.as_str(), + } + } } impl fmt::Display for Message { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Message::Connected => write!(f, "Connected successfully!"), - Message::Disconnected => { - write!(f, "Connection lost... Retrying...") - } - Message::User(message) => write!(f, "{message}"), - } + f.write_str(self.as_str()) + } +} + +impl<'a> text::IntoFragment<'a> for &'a Message { + fn into_fragment(self) -> text::Fragment<'a> { + text::Fragment::Borrowed(self.as_str()) } } diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index 369ae820..b479fe89 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -2,7 +2,7 @@ mod echo; use iced::alignment::{self, Alignment}; use iced::widget::{ - button, column, container, row, scrollable, text, text_input, value, + button, column, container, row, scrollable, text, text_input, }; use iced::{color, Command, Element, Length, Subscription}; use once_cell::sync::Lazy; @@ -96,7 +96,7 @@ impl WebSocket { .into() } else { scrollable( - column(self.messages.iter().map(value).map(Element::from)) + column(self.messages.iter().map(text).map(Element::from)) .spacing(10), ) .id(MESSAGE_LOG.clone()) -- cgit From b05e61f5c8ae61c9f3c7cc08cded53901ebbccfd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 3 Apr 2024 21:07:54 +0200 Subject: Redesign `iced_wgpu` layering architecture --- examples/geometry/src/main.rs | 6 +++++- examples/integration/src/main.rs | 35 +++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'examples') diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 16cdb86f..9532a24a 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -6,7 +6,10 @@ mod rainbow { use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; use iced::mouse; - use iced::{Element, Length, Rectangle, Renderer, Size, Theme, Vector}; + use iced::{ + Element, Length, Rectangle, Renderer, Size, Theme, Transformation, + Vector, + }; #[derive(Debug, Clone, Copy, Default)] pub struct Rainbow; @@ -130,6 +133,7 @@ mod rainbow { 0, 8, 1, // L ], }, + transformation: Transformation::IDENTITY, }; renderer.with_translation( diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index 9cd801b2..c292709f 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -5,12 +5,12 @@ use controls::Controls; use scene::Scene; use iced_wgpu::graphics::Viewport; -use iced_wgpu::{wgpu, Backend, Renderer, Settings}; +use iced_wgpu::{wgpu, Engine, Renderer, Settings}; use iced_winit::conversion; use iced_winit::core::mouse; use iced_winit::core::renderer; use iced_winit::core::window; -use iced_winit::core::{Color, Font, Pixels, Size, Theme}; +use iced_winit::core::{Color, Size, Theme}; use iced_winit::futures; use iced_winit::runtime::program; use iced_winit::runtime::Debug; @@ -155,11 +155,8 @@ pub fn main() -> Result<(), Box> { // Initialize iced let mut debug = Debug::new(); - let mut renderer = Renderer::new( - Backend::new(&adapter, &device, &queue, Settings::default(), format), - Font::default(), - Pixels(16.0), - ); + let mut engine = Engine::new(&adapter, &device, &queue, format, None); + let mut renderer = Renderer::new(Settings::default(), &engine); let mut state = program::State::new( controls, @@ -228,19 +225,17 @@ pub fn main() -> Result<(), Box> { } // And then iced on top - renderer.with_primitives(|backend, primitive| { - backend.present( - &device, - &queue, - &mut encoder, - None, - frame.texture.format(), - &view, - primitive, - &viewport, - &debug.overlay(), - ); - }); + renderer.present( + &mut engine, + &device, + &queue, + &mut encoder, + None, + frame.texture.format(), + &view, + &viewport, + &debug.overlay(), + ); // Then we submit the work queue.submit(Some(encoder.finish())); -- cgit From 6d3e1d835e1688fbc58622a03a784ed25ed3f0e1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 5 Apr 2024 23:59:21 +0200 Subject: Decouple caching from layering and simplify everything --- examples/geometry/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 9532a24a..31b8a4ce 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -82,7 +82,6 @@ mod rainbow { let posn_l = [0.0, bounds.height / 2.0]; let mesh = Mesh::Solid { - size: bounds.size(), buffers: mesh::Indexed { vertices: vec![ SolidVertex2D { @@ -134,6 +133,7 @@ mod rainbow { ], }, transformation: Transformation::IDENTITY, + clip_bounds: Rectangle::INFINITE, }; renderer.with_translation( -- cgit From d922b478156488a7bc03c6e791e05c040d702634 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 8 Apr 2024 15:04:35 +0200 Subject: Reintroduce support for custom primitives in `iced_wgpu` --- examples/custom_shader/src/scene.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/custom_shader/src/scene.rs b/examples/custom_shader/src/scene.rs index a35efdd9..5fa42188 100644 --- a/examples/custom_shader/src/scene.rs +++ b/examples/custom_shader/src/scene.rs @@ -9,8 +9,8 @@ use pipeline::cube::{self, Cube}; use iced::mouse; use iced::time::Duration; -use iced::widget::shader; -use iced::{Color, Rectangle, Size}; +use iced::widget::shader::{self, Viewport}; +use iced::{Color, Rectangle}; use glam::Vec3; use rand::Rng; @@ -130,25 +130,29 @@ impl Primitive { impl shader::Primitive for Primitive { fn prepare( &self, - format: wgpu::TextureFormat, device: &wgpu::Device, queue: &wgpu::Queue, - _bounds: Rectangle, - target_size: Size, - _scale_factor: f32, + format: wgpu::TextureFormat, storage: &mut shader::Storage, + _bounds: &Rectangle, + viewport: &Viewport, ) { if !storage.has::() { - storage.store(Pipeline::new(device, queue, format, target_size)); + storage.store(Pipeline::new( + device, + queue, + format, + viewport.physical_size(), + )); } let pipeline = storage.get_mut::().unwrap(); - //upload data to GPU + // Upload data to GPU pipeline.update( device, queue, - target_size, + viewport.physical_size(), &self.uniforms, self.cubes.len(), &self.cubes, @@ -157,20 +161,19 @@ impl shader::Primitive for Primitive { fn render( &self, + encoder: &mut wgpu::CommandEncoder, storage: &shader::Storage, target: &wgpu::TextureView, - _target_size: Size, - viewport: Rectangle, - encoder: &mut wgpu::CommandEncoder, + clip_bounds: &Rectangle, ) { - //at this point our pipeline should always be initialized + // At this point our pipeline should always be initialized let pipeline = storage.get::().unwrap(); - //render primitive + // Render primitive pipeline.render( target, encoder, - viewport, + *clip_bounds, self.cubes.len() as u32, self.show_depth_buffer, ); -- cgit From 2c6fd9ac14c5d270e05b97b7a7fab811d25834c4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 8 Apr 2024 15:35:54 +0200 Subject: Make arguments of `Renderer::new` explicit in `iced_wgpu` --- examples/integration/src/main.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index c292709f..c4b57ecf 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -5,12 +5,12 @@ use controls::Controls; use scene::Scene; use iced_wgpu::graphics::Viewport; -use iced_wgpu::{wgpu, Engine, Renderer, Settings}; +use iced_wgpu::{wgpu, Engine, Renderer}; use iced_winit::conversion; use iced_winit::core::mouse; use iced_winit::core::renderer; use iced_winit::core::window; -use iced_winit::core::{Color, Size, Theme}; +use iced_winit::core::{Color, Font, Pixels, Size, Theme}; use iced_winit::futures; use iced_winit::runtime::program; use iced_winit::runtime::Debug; @@ -156,7 +156,8 @@ pub fn main() -> Result<(), Box> { // Initialize iced let mut debug = Debug::new(); let mut engine = Engine::new(&adapter, &device, &queue, format, None); - let mut renderer = Renderer::new(Settings::default(), &engine); + let mut renderer = + Renderer::new(&engine, Font::default(), Pixels::from(16)); let mut state = program::State::new( controls, -- cgit From 9cbad0a352fcf12c5352e37bc15c0d20be6f89d7 Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:37:37 +0100 Subject: Remove extra Download struct from dowload_progress example --- examples/download_progress/src/download.rs | 6 ------ 1 file changed, 6 deletions(-) (limited to 'examples') diff --git a/examples/download_progress/src/download.rs b/examples/download_progress/src/download.rs index 3b11cb76..d6cc1e24 100644 --- a/examples/download_progress/src/download.rs +++ b/examples/download_progress/src/download.rs @@ -12,12 +12,6 @@ pub fn file( }) } -#[derive(Debug, Hash, Clone)] -pub struct Download { - id: I, - url: String, -} - async fn download(id: I, state: State) -> ((I, Progress), State) { match state { State::Ready(url) => { -- cgit From 8b1c514c3816795437da2ec25c2cfc559ebe5b9a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 25 Apr 2024 01:40:06 +0200 Subject: Showcase new `Stack` widget in `bezier_tool` example --- examples/bezier_tool/src/main.rs | 53 ++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'examples') diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index 289c919b..ba51a00e 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -1,9 +1,11 @@ //! This example showcases an interactive `Canvas` for drawing Bézier curves. -use iced::widget::{button, column, text}; -use iced::{Alignment, Element, Length}; +use iced::alignment; +use iced::widget::{button, container, stack}; +use iced::{Element, Length, Theme}; pub fn main() -> iced::Result { iced::program("Bezier Tool - Iced", Example::update, Example::view) + .theme(|_| Theme::CatppuccinMocha) .antialiasing(true) .run() } @@ -35,16 +37,18 @@ impl Example { } fn view(&self) -> Element { - column![ - text("Bezier tool example").width(Length::Shrink).size(50), + container(stack![ self.bezier.view(&self.curves).map(Message::AddCurve), - button("Clear") - .style(button::danger) - .on_press(Message::Clear), - ] + container( + button("Clear") + .style(button::danger) + .on_press(Message::Clear) + ) + .padding(10) + .width(Length::Fill) + .align_x(alignment::Horizontal::Right), + ]) .padding(20) - .spacing(20) - .align_items(Alignment::Center) .into() } } @@ -139,22 +143,24 @@ mod bezier { &self, state: &Self::State, renderer: &Renderer, - _theme: &Theme, + theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, ) -> Vec { let content = self.state.cache.draw(renderer, bounds.size(), |frame| { - Curve::draw_all(self.curves, frame); + Curve::draw_all(self.curves, frame, theme); frame.stroke( &Path::rectangle(Point::ORIGIN, frame.size()), - Stroke::default().with_width(2.0), + Stroke::default() + .with_width(2.0) + .with_color(theme.palette().text), ); }); if let Some(pending) = state { - vec![content, pending.draw(renderer, bounds, cursor)] + vec![content, pending.draw(renderer, theme, bounds, cursor)] } else { vec![content] } @@ -182,7 +188,7 @@ mod bezier { } impl Curve { - fn draw_all(curves: &[Curve], frame: &mut Frame) { + fn draw_all(curves: &[Curve], frame: &mut Frame, theme: &Theme) { let curves = Path::new(|p| { for curve in curves { p.move_to(curve.from); @@ -190,7 +196,12 @@ mod bezier { } }); - frame.stroke(&curves, Stroke::default().with_width(2.0)); + frame.stroke( + &curves, + Stroke::default() + .with_width(2.0) + .with_color(theme.palette().text), + ); } } @@ -204,6 +215,7 @@ mod bezier { fn draw( &self, renderer: &Renderer, + theme: &Theme, bounds: Rectangle, cursor: mouse::Cursor, ) -> Geometry { @@ -213,7 +225,12 @@ mod bezier { match *self { Pending::One { from } => { let line = Path::line(from, cursor_position); - frame.stroke(&line, Stroke::default().with_width(2.0)); + frame.stroke( + &line, + Stroke::default() + .with_width(2.0) + .with_color(theme.palette().text), + ); } Pending::Two { from, to } => { let curve = Curve { @@ -222,7 +239,7 @@ mod bezier { control: cursor_position, }; - Curve::draw_all(&[curve], &mut frame); + Curve::draw_all(&[curve], &mut frame, theme); } }; } -- cgit From 4cd45643d7d2aa83212162f17a9b28ddae4a9340 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 25 Apr 2024 06:05:00 +0200 Subject: Introduce `opaque` widget helper --- examples/loupe/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/loupe/src/main.rs b/examples/loupe/src/main.rs index 6a5ff123..42b7f471 100644 --- a/examples/loupe/src/main.rs +++ b/examples/loupe/src/main.rs @@ -159,7 +159,7 @@ mod loupe { if cursor.is_over(layout.bounds()) { mouse::Interaction::ZoomIn } else { - mouse::Interaction::Idle + mouse::Interaction::None } } } -- cgit From 4fc342c97963a7a7e7983604b9399fccf017aa53 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 25 Apr 2024 06:05:40 +0200 Subject: Simplify `modal` example :tada: --- examples/modal/src/main.rs | 363 +++++---------------------------------------- 1 file changed, 35 insertions(+), 328 deletions(-) (limited to 'examples') diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 398728e0..a345924d 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -2,12 +2,11 @@ use iced::event::{self, Event}; use iced::keyboard; use iced::keyboard::key; use iced::widget::{ - self, button, column, container, horizontal_space, pick_list, row, text, - text_input, + self, button, column, container, horizontal_space, mouse_area, opaque, + pick_list, row, stack, text, text_input, }; -use iced::{Alignment, Command, Element, Length, Subscription}; +use iced::{Alignment, Color, Command, Element, Length, Subscription}; -use modal::Modal; use std::fmt; pub fn main() -> iced::Result { @@ -121,7 +120,7 @@ impl App { .height(Length::Fill); if self.show_modal { - let modal = container( + let signup = container( column![ text("Sign Up").size(24), column![ @@ -162,9 +161,7 @@ impl App { .padding(10) .style(container::rounded_box); - Modal::new(content, modal) - .on_blur(Message::HideModal) - .into() + modal(content, signup, Message::HideModal) } else { content.into() } @@ -203,326 +200,36 @@ impl fmt::Display for Plan { } } -mod modal { - use iced::advanced::layout::{self, Layout}; - use iced::advanced::overlay; - use iced::advanced::renderer; - use iced::advanced::widget::{self, Widget}; - use iced::advanced::{self, Clipboard, Shell}; - use iced::alignment::Alignment; - use iced::event; - use iced::mouse; - use iced::{Color, Element, Event, Length, Point, Rectangle, Size, Vector}; - - /// A widget that centers a modal element over some base element - pub struct Modal<'a, Message, Theme, Renderer> { - base: Element<'a, Message, Theme, Renderer>, - modal: Element<'a, Message, Theme, Renderer>, - on_blur: Option, - } - - impl<'a, Message, Theme, Renderer> Modal<'a, Message, Theme, Renderer> { - /// Returns a new [`Modal`] - pub fn new( - base: impl Into>, - modal: impl Into>, - ) -> Self { - Self { - base: base.into(), - modal: modal.into(), - on_blur: None, - } - } - - /// Sets the message that will be produces when the background - /// of the [`Modal`] is pressed - pub fn on_blur(self, on_blur: Message) -> Self { - Self { - on_blur: Some(on_blur), - ..self - } - } - } - - impl<'a, Message, Theme, Renderer> Widget - for Modal<'a, Message, Theme, Renderer> - where - Renderer: advanced::Renderer, - Message: Clone, - { - fn children(&self) -> Vec { - vec![ - widget::Tree::new(&self.base), - widget::Tree::new(&self.modal), - ] - } - - fn diff(&self, tree: &mut widget::Tree) { - tree.diff_children(&[&self.base, &self.modal]); - } - - fn size(&self) -> Size { - self.base.as_widget().size() - } - - fn layout( - &self, - tree: &mut widget::Tree, - renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - self.base.as_widget().layout( - &mut tree.children[0], - renderer, - limits, - ) - } - - fn on_event( - &mut self, - state: &mut widget::Tree, - event: Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - viewport: &Rectangle, - ) -> event::Status { - self.base.as_widget_mut().on_event( - &mut state.children[0], - event, - layout, - cursor, - renderer, - clipboard, - shell, - viewport, - ) - } - - fn draw( - &self, - state: &widget::Tree, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - ) { - self.base.as_widget().draw( - &state.children[0], - renderer, - theme, - style, - layout, - cursor, - viewport, - ); - } - - fn overlay<'b>( - &'b mut self, - state: &'b mut widget::Tree, - layout: Layout<'_>, - _renderer: &Renderer, - translation: Vector, - ) -> Option> { - Some(overlay::Element::new(Box::new(Overlay { - position: layout.position() + translation, - content: &mut self.modal, - tree: &mut state.children[1], - size: layout.bounds().size(), - on_blur: self.on_blur.clone(), - }))) - } - - fn mouse_interaction( - &self, - state: &widget::Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.base.as_widget().mouse_interaction( - &state.children[0], - layout, - cursor, - viewport, - renderer, - ) - } - - fn operate( - &self, - state: &mut widget::Tree, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation, - ) { - self.base.as_widget().operate( - &mut state.children[0], - layout, - renderer, - operation, - ); - } - } - - struct Overlay<'a, 'b, Message, Theme, Renderer> { - position: Point, - content: &'b mut Element<'a, Message, Theme, Renderer>, - tree: &'b mut widget::Tree, - size: Size, - on_blur: Option, - } - - impl<'a, 'b, Message, Theme, Renderer> - overlay::Overlay - for Overlay<'a, 'b, Message, Theme, Renderer> - where - Renderer: advanced::Renderer, - Message: Clone, - { - fn layout( - &mut self, - renderer: &Renderer, - _bounds: Size, - ) -> layout::Node { - let limits = layout::Limits::new(Size::ZERO, self.size) +fn modal<'a, Message>( + base: impl Into>, + content: impl Into>, + on_blur: Message, +) -> Element<'a, Message> +where + Message: Clone + 'a, +{ + stack![ + base.into(), + mouse_area( + container(opaque(content)) .width(Length::Fill) - .height(Length::Fill); - - let child = self - .content - .as_widget() - .layout(self.tree, renderer, &limits) - .align(Alignment::Center, Alignment::Center, limits.max()); - - layout::Node::with_children(self.size, vec![child]) - .move_to(self.position) - } - - fn on_event( - &mut self, - event: Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - ) -> event::Status { - let content_bounds = layout.children().next().unwrap().bounds(); - - if let Some(message) = self.on_blur.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Left, - )) = &event - { - if !cursor.is_over(content_bounds) { - shell.publish(message.clone()); - return event::Status::Captured; + .height(Length::Fill) + .center_x() + .center_y() + .style(|_theme| { + container::Style { + background: Some( + Color { + a: 0.8, + ..Color::BLACK + } + .into(), + ), + ..container::Style::default() } - } - } - - self.content.as_widget_mut().on_event( - self.tree, - event, - layout.children().next().unwrap(), - cursor, - renderer, - clipboard, - shell, - &layout.bounds(), - ) - } - - fn draw( - &self, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - ) { - renderer.fill_quad( - renderer::Quad { - bounds: layout.bounds(), - ..renderer::Quad::default() - }, - Color { - a: 0.80, - ..Color::BLACK - }, - ); - - self.content.as_widget().draw( - self.tree, - renderer, - theme, - style, - layout.children().next().unwrap(), - cursor, - &layout.bounds(), - ); - } - - fn operate( - &mut self, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation, - ) { - self.content.as_widget().operate( - self.tree, - layout.children().next().unwrap(), - renderer, - operation, - ); - } - - fn mouse_interaction( - &self, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.content.as_widget().mouse_interaction( - self.tree, - layout.children().next().unwrap(), - cursor, - viewport, - renderer, - ) - } - - fn overlay<'c>( - &'c mut self, - layout: Layout<'_>, - renderer: &Renderer, - ) -> Option> { - self.content.as_widget_mut().overlay( - self.tree, - layout.children().next().unwrap(), - renderer, - Vector::ZERO, - ) - } - } - - impl<'a, Message, Theme, Renderer> From> - for Element<'a, Message, Theme, Renderer> - where - Theme: 'a, - Message: 'a + Clone, - Renderer: 'a + advanced::Renderer, - { - fn from(modal: Modal<'a, Message, Theme, Renderer>) -> Self { - Element::new(modal) - } - } + }) + ) + .on_press(on_blur) + ] + .into() } -- cgit From a16a75a71d0bc76c17c2d76d827fa8c37eb56f09 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 27 Apr 2024 06:06:28 +0200 Subject: Use `hover` widget in `bezier_tool` example --- examples/bezier_tool/src/main.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'examples') diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index ba51a00e..29df3eeb 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -1,6 +1,6 @@ //! This example showcases an interactive `Canvas` for drawing Bézier curves. use iced::alignment; -use iced::widget::{button, container, stack}; +use iced::widget::{button, container, horizontal_space, hover}; use iced::{Element, Length, Theme}; pub fn main() -> iced::Result { @@ -37,17 +37,21 @@ impl Example { } fn view(&self) -> Element { - container(stack![ + container(hover( self.bezier.view(&self.curves).map(Message::AddCurve), - container( - button("Clear") - .style(button::danger) - .on_press(Message::Clear) - ) - .padding(10) - .width(Length::Fill) - .align_x(alignment::Horizontal::Right), - ]) + if self.curves.is_empty() { + container(horizontal_space()) + } else { + container( + button("Clear") + .style(button::danger) + .on_press(Message::Clear), + ) + .padding(10) + .width(Length::Fill) + .align_x(alignment::Horizontal::Right) + }, + )) .padding(20) .into() } -- cgit From aeede66963a2e512ed299bdfd502c2c63a99cca9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 27 Apr 2024 15:11:03 +0200 Subject: Create `the_matrix` example --- examples/the_matrix/Cargo.toml | 12 +++++ examples/the_matrix/src/main.rs | 116 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 examples/the_matrix/Cargo.toml create mode 100644 examples/the_matrix/src/main.rs (limited to 'examples') diff --git a/examples/the_matrix/Cargo.toml b/examples/the_matrix/Cargo.toml new file mode 100644 index 00000000..17cf443b --- /dev/null +++ b/examples/the_matrix/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "the_matrix" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez "] +edition = "2021" +publish = false + +[dependencies] +iced.workspace = true +iced.features = ["canvas", "tokio", "debug"] + +rand = "0.8" diff --git a/examples/the_matrix/src/main.rs b/examples/the_matrix/src/main.rs new file mode 100644 index 00000000..55c9da4b --- /dev/null +++ b/examples/the_matrix/src/main.rs @@ -0,0 +1,116 @@ +use iced::mouse; +use iced::time::{self, Instant}; +use iced::widget::canvas; +use iced::widget::canvas::{Cache, Geometry}; +use iced::{ + Color, Element, Font, Length, Point, Rectangle, Renderer, Subscription, + Theme, +}; + +pub fn main() -> iced::Result { + iced::program("The Matrix - Iced", TheMatrix::update, TheMatrix::view) + .subscription(TheMatrix::subscription) + .antialiasing(true) + .run() +} + +struct TheMatrix { + ticks: usize, + backgrounds: Vec, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + Tick(Instant), +} + +impl TheMatrix { + fn update(&mut self, message: Message) { + match message { + Message::Tick(_now) => { + self.ticks += 1; + } + } + } + + fn view(&self) -> Element { + canvas(self as &Self) + .width(Length::Fill) + .height(Length::Fill) + .into() + } + + fn subscription(&self) -> Subscription { + time::every(std::time::Duration::from_millis(50)).map(Message::Tick) + } +} + +impl Default for TheMatrix { + fn default() -> Self { + let mut backgrounds = Vec::with_capacity(30); + backgrounds.resize_with(30, Cache::default); + + Self { + ticks: 0, + backgrounds, + } + } +} + +impl canvas::Program for TheMatrix { + type State = (); + + fn draw( + &self, + _state: &Self::State, + renderer: &Renderer, + _theme: &Theme, + bounds: Rectangle, + _cursor: mouse::Cursor, + ) -> Vec { + use rand::distributions::Distribution; + use rand::Rng; + + const CELL_SIZE: f32 = 10.0; + + vec![self.backgrounds[self.ticks % self.backgrounds.len()].draw( + renderer, + bounds.size(), + |frame| { + frame.fill_rectangle(Point::ORIGIN, frame.size(), Color::BLACK); + + let mut rng = rand::thread_rng(); + let rows = (frame.height() / CELL_SIZE).ceil() as usize; + let columns = (frame.width() / CELL_SIZE).ceil() as usize; + + for row in 0..rows { + for column in 0..columns { + let position = Point::new( + column as f32 * CELL_SIZE, + row as f32 * CELL_SIZE, + ); + + let alphas = [0.05, 0.1, 0.2, 0.5]; + let weights = [10, 4, 2, 1]; + let distribution = + rand::distributions::WeightedIndex::new(weights) + .expect("Create distribution"); + + frame.fill_text(canvas::Text { + content: rng.gen_range('!'..'z').to_string(), + position, + color: Color { + a: alphas[distribution.sample(&mut rng)], + g: 1.0, + ..Color::BLACK + }, + size: CELL_SIZE.into(), + font: Font::MONOSPACE, + ..canvas::Text::default() + }); + } + } + }, + )] + } +} -- cgit From 3c7b43d031a06d59afbba83bc9d088517c096f20 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 Apr 2024 08:06:51 +0200 Subject: Use shared `Cache` group in `the_matrix` example --- examples/the_matrix/src/main.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/the_matrix/src/main.rs b/examples/the_matrix/src/main.rs index 55c9da4b..97ad31b9 100644 --- a/examples/the_matrix/src/main.rs +++ b/examples/the_matrix/src/main.rs @@ -1,12 +1,13 @@ use iced::mouse; use iced::time::{self, Instant}; use iced::widget::canvas; -use iced::widget::canvas::{Cache, Geometry}; use iced::{ Color, Element, Font, Length, Point, Rectangle, Renderer, Subscription, Theme, }; +use std::cell::RefCell; + pub fn main() -> iced::Result { iced::program("The Matrix - Iced", TheMatrix::update, TheMatrix::view) .subscription(TheMatrix::subscription) @@ -15,8 +16,7 @@ pub fn main() -> iced::Result { } struct TheMatrix { - ticks: usize, - backgrounds: Vec, + tick: usize, } #[derive(Debug, Clone, Copy)] @@ -28,7 +28,7 @@ impl TheMatrix { fn update(&mut self, message: Message) { match message { Message::Tick(_now) => { - self.ticks += 1; + self.tick += 1; } } } @@ -47,33 +47,35 @@ impl TheMatrix { impl Default for TheMatrix { fn default() -> Self { - let mut backgrounds = Vec::with_capacity(30); - backgrounds.resize_with(30, Cache::default); - - Self { - ticks: 0, - backgrounds, - } + Self { tick: 0 } } } impl canvas::Program for TheMatrix { - type State = (); + type State = RefCell>; fn draw( &self, - _state: &Self::State, + state: &Self::State, renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, - ) -> Vec { + ) -> Vec { use rand::distributions::Distribution; use rand::Rng; const CELL_SIZE: f32 = 10.0; - vec![self.backgrounds[self.ticks % self.backgrounds.len()].draw( + let mut caches = state.borrow_mut(); + + if caches.is_empty() { + let group = canvas::Group::unique(); + + caches.resize_with(30, || canvas::Cache::with_group(group)); + } + + vec![caches[self.tick % caches.len()].draw( renderer, bounds.size(), |frame| { -- cgit From cfe4ddb86620f9b21027c8a828e80df9a8887407 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 Apr 2024 08:10:22 +0200 Subject: Fix `clippy` lint in `the_matrix` example --- examples/the_matrix/src/main.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/the_matrix/src/main.rs b/examples/the_matrix/src/main.rs index 97ad31b9..4ed1db32 100644 --- a/examples/the_matrix/src/main.rs +++ b/examples/the_matrix/src/main.rs @@ -15,6 +15,7 @@ pub fn main() -> iced::Result { .run() } +#[derive(Default)] struct TheMatrix { tick: usize, } @@ -45,12 +46,6 @@ impl TheMatrix { } } -impl Default for TheMatrix { - fn default() -> Self { - Self { tick: 0 } - } -} - impl canvas::Program for TheMatrix { type State = RefCell>; -- cgit From c51b85e7ab067f5e7411eccd10a5ae192e6ee0a8 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 Apr 2024 21:59:46 +0200 Subject: Invalidate text uploads after atlas trimming --- examples/the_matrix/Cargo.toml | 1 + examples/the_matrix/src/main.rs | 2 ++ 2 files changed, 3 insertions(+) (limited to 'examples') diff --git a/examples/the_matrix/Cargo.toml b/examples/the_matrix/Cargo.toml index 17cf443b..775e76e0 100644 --- a/examples/the_matrix/Cargo.toml +++ b/examples/the_matrix/Cargo.toml @@ -10,3 +10,4 @@ iced.workspace = true iced.features = ["canvas", "tokio", "debug"] rand = "0.8" +tracing-subscriber = "0.3" diff --git a/examples/the_matrix/src/main.rs b/examples/the_matrix/src/main.rs index 4ed1db32..f3a67ac8 100644 --- a/examples/the_matrix/src/main.rs +++ b/examples/the_matrix/src/main.rs @@ -9,6 +9,8 @@ use iced::{ use std::cell::RefCell; pub fn main() -> iced::Result { + tracing_subscriber::fmt::init(); + iced::program("The Matrix - Iced", TheMatrix::update, TheMatrix::view) .subscription(TheMatrix::subscription) .antialiasing(true) -- cgit From 62433a65e92c025cd9c36e81fc16bab77790bacb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 Apr 2024 23:51:41 +0200 Subject: Enable logging in `clock` example --- examples/clock/Cargo.toml | 1 + examples/clock/src/main.rs | 2 ++ 2 files changed, 3 insertions(+) (limited to 'examples') diff --git a/examples/clock/Cargo.toml b/examples/clock/Cargo.toml index 2d3d5908..dc2e5382 100644 --- a/examples/clock/Cargo.toml +++ b/examples/clock/Cargo.toml @@ -10,3 +10,4 @@ iced.workspace = true iced.features = ["canvas", "tokio", "debug"] time = { version = "0.3", features = ["local-offset"] } +tracing-subscriber = "0.3" diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 897f8f1b..d717db36 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -8,6 +8,8 @@ use iced::{ }; pub fn main() -> iced::Result { + tracing_subscriber::fmt::init(); + iced::program("Clock - Iced", Clock::update, Clock::view) .subscription(Clock::subscription) .theme(Clock::theme) -- cgit From 58ea914ad21ea9c5ae7b7b1c167ed084c9ddb07a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 May 2024 01:52:49 +0200 Subject: Make `image::Id` actually opaque --- examples/pokedex/src/main.rs | 2 +- examples/screenshot/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/pokedex/src/main.rs b/examples/pokedex/src/main.rs index 0811c08d..35f23236 100644 --- a/examples/pokedex/src/main.rs +++ b/examples/pokedex/src/main.rs @@ -188,7 +188,7 @@ impl Pokemon { { let bytes = reqwest::get(&url).await?.bytes().await?; - Ok(image::Handle::from_memory(bytes)) + Ok(image::Handle::from_bytes(bytes)) } #[cfg(target_arch = "wasm32")] diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index d887c41b..5c175ccc 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -109,7 +109,7 @@ impl Example { fn view(&self) -> Element<'_, Message> { let image: Element = if let Some(screenshot) = &self.screenshot { - image(image::Handle::from_pixels( + image(image::Handle::from_rgba( screenshot.size.width, screenshot.size.height, screenshot.clone(), -- cgit From efc55b655bfce98fc32e698cf3c2007e27be941a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 May 2024 17:14:20 +0200 Subject: Create `ferris` example to showcase `ContentFit` and `Rotation` --- examples/ferris/Cargo.toml | 10 +++ examples/ferris/src/main.rs | 161 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 examples/ferris/Cargo.toml create mode 100644 examples/ferris/src/main.rs (limited to 'examples') diff --git a/examples/ferris/Cargo.toml b/examples/ferris/Cargo.toml new file mode 100644 index 00000000..c9fb8c13 --- /dev/null +++ b/examples/ferris/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "ferris" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez "] +edition = "2021" +publish = false + +[dependencies] +iced.workspace = true +iced.features = ["image"] diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs new file mode 100644 index 00000000..d846f560 --- /dev/null +++ b/examples/ferris/src/main.rs @@ -0,0 +1,161 @@ +use iced::widget::{column, container, image, pick_list, row, slider, text}; +use iced::{ + Alignment, Color, ContentFit, Degrees, Element, Length, Rotation, Theme, +}; + +pub fn main() -> iced::Result { + iced::program("Ferris - Iced", Image::update, Image::view) + .theme(|_| Theme::TokyoNight) + .run() +} + +struct Image { + width: f32, + rotation: Rotation, + content_fit: ContentFit, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + WidthChanged(f32), + RotationStrategyChanged(RotationStrategy), + RotationChanged(Degrees), + ContentFitChanged(ContentFit), +} + +impl Image { + fn update(&mut self, message: Message) { + match message { + Message::WidthChanged(width) => { + self.width = width; + } + Message::RotationStrategyChanged(strategy) => { + self.rotation = match strategy { + RotationStrategy::Floating => { + Rotation::Floating(self.rotation.radians()) + } + RotationStrategy::Solid => { + Rotation::Solid(self.rotation.radians()) + } + }; + } + Message::RotationChanged(rotation) => { + self.rotation = match self.rotation { + Rotation::Floating(_) => { + Rotation::Floating(rotation.into()) + } + Rotation::Solid(_) => Rotation::Solid(rotation.into()), + }; + } + Message::ContentFitChanged(content_fit) => { + self.content_fit = content_fit; + } + } + } + + fn view(&self) -> Element { + let i_am_ferris = container( + column![ + "Hello!", + Element::from( + image(format!( + "{}/../tour/images/ferris.png", + env!("CARGO_MANIFEST_DIR") + )) + .width(self.width) + .content_fit(self.content_fit) + .rotation(self.rotation) + ) + .explain(Color::WHITE), + "I am Ferris!" + ] + .spacing(20) + .align_items(Alignment::Center), + ) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y(); + + let sizing = row![ + pick_list( + [ + ContentFit::Contain, + ContentFit::Cover, + ContentFit::Fill, + ContentFit::None, + ContentFit::ScaleDown + ], + Some(self.content_fit), + Message::ContentFitChanged + ) + .width(Length::Fill), + column![ + slider(100.0..=500.0, self.width, Message::WidthChanged), + text(format!("Width: {}px", self.width)) + .size(14) + .line_height(1.0) + ] + .spacing(5) + .align_items(Alignment::Center) + ] + .spacing(10); + + let rotation = row![ + pick_list( + [RotationStrategy::Floating, RotationStrategy::Solid], + Some(match self.rotation { + Rotation::Floating(_) => RotationStrategy::Floating, + Rotation::Solid(_) => RotationStrategy::Solid, + }), + Message::RotationStrategyChanged, + ) + .width(Length::Fill), + column![ + slider( + Degrees::RANGE, + self.rotation.degrees(), + Message::RotationChanged + ), + text(format!( + "Rotation: {:.0}°", + f32::from(self.rotation.degrees()) + )) + .size(14) + .line_height(1.0) + ] + .spacing(5) + .align_items(Alignment::Center) + ] + .spacing(10); + + container(column![i_am_ferris, sizing, rotation].spacing(10)) + .padding(10) + .into() + } +} + +impl Default for Image { + fn default() -> Self { + Self { + width: 300.0, + rotation: Rotation::default(), + content_fit: ContentFit::default(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum RotationStrategy { + Floating, + Solid, +} + +impl std::fmt::Display for RotationStrategy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::Floating => "Floating", + Self::Solid => "Solid", + }) + } +} -- cgit From eac5bcb64f17dfbb52b64ea4f95693462986bb69 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 07:04:57 +0200 Subject: Fix `Image::bounds` when rotation present in `iced_graphics` --- examples/ferris/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/ferris/Cargo.toml b/examples/ferris/Cargo.toml index c9fb8c13..0d91749b 100644 --- a/examples/ferris/Cargo.toml +++ b/examples/ferris/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced.workspace = true -iced.features = ["image"] +iced.features = ["image", "debug"] -- cgit From f9124470b4b6adca19094dd0f5e663efd9471ec3 Mon Sep 17 00:00:00 2001 From: Skygrango Date: Fri, 3 May 2024 13:04:39 +0800 Subject: Fix `clock` example doesn't get the correct local time under unix system There is a long-standing problem (https://github.com/time-rs/time/issues/293) that has not yet been solved by time-rs Switch to chrono as it seemed to solve the problem (https://github.com/chronotope/chrono/pull/677) --- examples/clock/Cargo.toml | 3 +-- examples/clock/src/main.rs | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'examples') diff --git a/examples/clock/Cargo.toml b/examples/clock/Cargo.toml index dc2e5382..2fddc7da 100644 --- a/examples/clock/Cargo.toml +++ b/examples/clock/Cargo.toml @@ -8,6 +8,5 @@ publish = false [dependencies] iced.workspace = true iced.features = ["canvas", "tokio", "debug"] - -time = { version = "0.3", features = ["local-offset"] } +chrono = { version = "0.4", features = [ "clock" ] } tracing-subscriber = "0.3" diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index d717db36..3ffc9f07 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -7,6 +7,9 @@ use iced::{ Theme, Vector, }; +use chrono as time; +use time::Timelike; + pub fn main() -> iced::Result { tracing_subscriber::fmt::init(); @@ -18,13 +21,13 @@ pub fn main() -> iced::Result { } struct Clock { - now: time::OffsetDateTime, + now: time::DateTime, clock: Cache, } #[derive(Debug, Clone, Copy)] enum Message { - Tick(time::OffsetDateTime), + Tick(time::DateTime), } impl Clock { @@ -54,16 +57,12 @@ impl Clock { } fn subscription(&self) -> Subscription { - iced::time::every(std::time::Duration::from_millis(500)).map(|_| { - Message::Tick( - time::OffsetDateTime::now_local() - .unwrap_or_else(|_| time::OffsetDateTime::now_utc()), - ) - }) + iced::time::every(std::time::Duration::from_millis(500)) + .map(|_| Message::Tick(time::offset::Local::now())) } fn theme(&self) -> Theme { - Theme::ALL[(self.now.unix_timestamp() as usize / 10) % Theme::ALL.len()] + Theme::ALL[(self.now.timestamp() as usize / 10) % Theme::ALL.len()] .clone() } } @@ -71,8 +70,7 @@ impl Clock { impl Default for Clock { fn default() -> Self { Self { - now: time::OffsetDateTime::now_local() - .unwrap_or_else(|_| time::OffsetDateTime::now_utc()), + now: time::offset::Local::now(), clock: Cache::default(), } } @@ -127,17 +125,17 @@ impl canvas::Program for Clock { frame.translate(Vector::new(center.x, center.y)); frame.with_save(|frame| { - frame.rotate(hand_rotation(self.now.hour(), 12)); + frame.rotate(hand_rotation(self.now.hour() as u8, 12)); frame.stroke(&short_hand, wide_stroke()); }); frame.with_save(|frame| { - frame.rotate(hand_rotation(self.now.minute(), 60)); + frame.rotate(hand_rotation(self.now.minute() as u8, 60)); frame.stroke(&long_hand, wide_stroke()); }); frame.with_save(|frame| { - let rotation = hand_rotation(self.now.second(), 60); + let rotation = hand_rotation(self.now.second() as u8, 60); frame.rotate(rotation); frame.stroke(&long_hand, thin_stroke()); -- cgit From 4010e3983d40e24a5d7b590d8fec9801651199ce Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 07:23:55 +0200 Subject: Add `spin` mode to `ferris` example :crab: --- examples/ferris/Cargo.toml | 2 +- examples/ferris/src/main.rs | 68 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/ferris/Cargo.toml b/examples/ferris/Cargo.toml index 0d91749b..e98341d2 100644 --- a/examples/ferris/Cargo.toml +++ b/examples/ferris/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced.workspace = true -iced.features = ["image", "debug"] +iced.features = ["image", "tokio", "debug"] diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index d846f560..b7536740 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -1,10 +1,16 @@ -use iced::widget::{column, container, image, pick_list, row, slider, text}; +use iced::time::Instant; +use iced::widget::{ + checkbox, column, container, image, pick_list, row, slider, text, +}; +use iced::window; use iced::{ - Alignment, Color, ContentFit, Degrees, Element, Length, Rotation, Theme, + Alignment, Color, ContentFit, Degrees, Element, Length, Radians, Rotation, + Subscription, Theme, }; pub fn main() -> iced::Result { iced::program("Ferris - Iced", Image::update, Image::view) + .subscription(Image::subscription) .theme(|_| Theme::TokyoNight) .run() } @@ -13,6 +19,8 @@ struct Image { width: f32, rotation: Rotation, content_fit: ContentFit, + spin: bool, + last_tick: Instant, } #[derive(Debug, Clone, Copy)] @@ -21,6 +29,8 @@ enum Message { RotationStrategyChanged(RotationStrategy), RotationChanged(Degrees), ContentFitChanged(ContentFit), + SpinToggled(bool), + RedrawRequested(Instant), } impl Image { @@ -50,6 +60,29 @@ impl Image { Message::ContentFitChanged(content_fit) => { self.content_fit = content_fit; } + Message::SpinToggled(spin) => { + self.spin = spin; + self.last_tick = Instant::now(); + } + Message::RedrawRequested(now) => { + const ROTATION_SPEED: Degrees = Degrees(360.0); + + let delta = (now - self.last_tick).as_millis() as f32 / 1_000.0; + + *self.rotation.radians_mut() = (self.rotation.radians() + + ROTATION_SPEED * delta) + % (2.0 * Radians::PI); + + self.last_tick = now; + } + } + } + + fn subscription(&self) -> Subscription { + if self.spin { + window::frames().map(Message::RedrawRequested) + } else { + Subscription::none() } } @@ -111,18 +144,23 @@ impl Image { Message::RotationStrategyChanged, ) .width(Length::Fill), - column![ - slider( - Degrees::RANGE, - self.rotation.degrees(), - Message::RotationChanged - ), - text(format!( - "Rotation: {:.0}°", - f32::from(self.rotation.degrees()) - )) - .size(14) - .line_height(1.0) + row![ + column![ + slider( + Degrees::RANGE, + self.rotation.degrees(), + Message::RotationChanged + ), + text(format!( + "Rotation: {:.0}°", + f32::from(self.rotation.degrees()) + )) + .size(14) + .line_height(1.0) + ] + .spacing(5) + .align_items(Alignment::Center), + checkbox("Spin!", self.spin).on_toggle(Message::SpinToggled) ] .spacing(5) .align_items(Alignment::Center) @@ -141,6 +179,8 @@ impl Default for Image { width: 300.0, rotation: Rotation::default(), content_fit: ContentFit::default(), + spin: false, + last_tick: Instant::now(), } } } -- cgit From 15057a05c118dafcb8cf90d4119e66caaa6026c5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 09:11:46 +0200 Subject: Introduce `center` widget helper ... and also make `center_x` and `center_y` set `width` and `height` to `Length::Fill`, respectively. This targets the most common use case when centering things and removes a bunch of boilerplate as a result. --- examples/checkbox/src/main.rs | 11 ++--- examples/combo_box/src/main.rs | 9 +--- examples/component/src/main.rs | 8 ++-- examples/custom_quad/src/main.rs | 11 ++--- examples/custom_shader/src/main.rs | 9 +--- examples/custom_widget/src/main.rs | 11 ++--- examples/download_progress/src/main.rs | 12 ++--- examples/editor/src/main.rs | 2 +- examples/events/src/main.rs | 9 +--- examples/exit/src/main.rs | 12 ++--- examples/ferris/src/main.rs | 77 ++++++++++++++++----------------- examples/geometry/src/main.rs | 11 ++--- examples/layout/src/main.rs | 20 +++------ examples/loading_spinners/src/main.rs | 10 ++--- examples/loupe/src/main.rs | 10 ++--- examples/modal/src/main.rs | 45 +++++++------------ examples/multi_window/src/main.rs | 13 +++--- examples/pane_grid/src/main.rs | 7 +-- examples/pokedex/src/main.rs | 9 +--- examples/qr_code/src/main.rs | 14 ++---- examples/screenshot/src/main.rs | 21 ++------- examples/scrollable/src/main.rs | 2 +- examples/slider/src/main.rs | 16 +++---- examples/stopwatch/src/main.rs | 11 ++--- examples/styling/src/main.rs | 13 ++---- examples/svg/src/main.rs | 17 +++----- examples/system_information/src/main.rs | 9 +--- examples/toast/src/main.rs | 10 ++--- examples/todos/src/main.rs | 14 +++--- examples/tooltip/src/main.rs | 11 ++--- examples/tour/src/main.rs | 4 +- examples/url_handler/src/main.rs | 11 ++--- examples/websocket/src/main.rs | 10 +---- 33 files changed, 145 insertions(+), 314 deletions(-) (limited to 'examples') diff --git a/examples/checkbox/src/main.rs b/examples/checkbox/src/main.rs index 38949336..bec4a954 100644 --- a/examples/checkbox/src/main.rs +++ b/examples/checkbox/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::{checkbox, column, container, row, text}; -use iced::{Element, Font, Length}; +use iced::widget::{center, checkbox, column, row, text}; +use iced::{Element, Font}; const ICON_FONT: Font = Font::with_name("icons"); @@ -68,11 +68,6 @@ impl Example { let content = column![default_checkbox, checkboxes, custom_checkbox].spacing(20); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } } diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index 2feb4522..ff759ab4 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{ - column, combo_box, container, scrollable, text, vertical_space, + center, column, combo_box, scrollable, text, vertical_space, }; use iced::{Alignment, Element, Length}; @@ -68,12 +68,7 @@ impl Example { .align_items(Alignment::Center) .spacing(10); - container(scrollable(content)) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(scrollable(content)).into() } } diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index b2c71b3f..5625f12a 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::container; -use iced::{Element, Length}; +use iced::widget::center; +use iced::Element; use numeric_input::numeric_input; @@ -27,10 +27,8 @@ impl Component { } fn view(&self) -> Element { - container(numeric_input(self.value, Message::NumericInputChanged)) + center(numeric_input(self.value, Message::NumericInputChanged)) .padding(20) - .height(Length::Fill) - .center_y() .into() } } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index c093e240..b3eee218 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -81,8 +81,8 @@ mod quad { } } -use iced::widget::{column, container, slider, text}; -use iced::{Alignment, Color, Element, Length, Shadow, Vector}; +use iced::widget::{center, column, slider, text}; +use iced::{Alignment, Color, Element, Shadow, Vector}; pub fn main() -> iced::Result { iced::run("Custom Quad - Iced", Example::update, Example::view) @@ -187,12 +187,7 @@ impl Example { .max_width(500) .align_items(Alignment::Center); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } } diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index aa3dafe9..463b2df9 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -4,7 +4,7 @@ use scene::Scene; use iced::time::Instant; use iced::widget::shader::wgpu; -use iced::widget::{checkbox, column, container, row, shader, slider, text}; +use iced::widget::{center, checkbox, column, row, shader, slider, text}; use iced::window; use iced::{Alignment, Color, Element, Length, Subscription}; @@ -123,12 +123,7 @@ impl IcedCubes { let shader = shader(&self.scene).width(Length::Fill).height(Length::Fill); - container(column![shader, controls].align_items(Alignment::Center)) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(column![shader, controls].align_items(Alignment::Center)).into() } fn subscription(&self) -> Subscription { diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index aa49ebd0..261dcb81 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -82,8 +82,8 @@ mod circle { } use circle::circle; -use iced::widget::{column, container, slider, text}; -use iced::{Alignment, Element, Length}; +use iced::widget::{center, column, slider, text}; +use iced::{Alignment, Element}; pub fn main() -> iced::Result { iced::run("Custom Widget - Iced", Example::update, Example::view) @@ -122,12 +122,7 @@ impl Example { .max_width(500) .align_items(Alignment::Center); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } } diff --git a/examples/download_progress/src/main.rs b/examples/download_progress/src/main.rs index 9f4769e0..e031ac44 100644 --- a/examples/download_progress/src/main.rs +++ b/examples/download_progress/src/main.rs @@ -1,7 +1,7 @@ mod download; -use iced::widget::{button, column, container, progress_bar, text, Column}; -use iced::{Alignment, Element, Length, Subscription}; +use iced::widget::{button, center, column, progress_bar, text, Column}; +use iced::{Alignment, Element, Subscription}; pub fn main() -> iced::Result { iced::program("Download Progress - Iced", Example::update, Example::view) @@ -67,13 +67,7 @@ impl Example { .spacing(20) .align_items(Alignment::End); - container(downloads) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .padding(20) - .into() + center(downloads).padding(20).into() } } diff --git a/examples/editor/src/main.rs b/examples/editor/src/main.rs index ed16018a..af05031a 100644 --- a/examples/editor/src/main.rs +++ b/examples/editor/src/main.rs @@ -277,7 +277,7 @@ fn action<'a, Message: Clone + 'a>( label: &'a str, on_press: Option, ) -> Element<'a, Message> { - let action = button(container(content).width(30).center_x()); + let action = button(container(content).center_x().width(30)); if let Some(on_press) = on_press { tooltip( diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs index bf568c94..999ce8ef 100644 --- a/examples/events/src/main.rs +++ b/examples/events/src/main.rs @@ -1,6 +1,6 @@ use iced::alignment; use iced::event::{self, Event}; -use iced::widget::{button, checkbox, container, text, Column}; +use iced::widget::{button, center, checkbox, text, Column}; use iced::window; use iced::{Alignment, Command, Element, Length, Subscription}; @@ -84,11 +84,6 @@ impl Events { .push(toggle) .push(exit); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } } diff --git a/examples/exit/src/main.rs b/examples/exit/src/main.rs index 7bed272d..2de97e20 100644 --- a/examples/exit/src/main.rs +++ b/examples/exit/src/main.rs @@ -1,6 +1,6 @@ -use iced::widget::{button, column, container}; +use iced::widget::{button, center, column}; use iced::window; -use iced::{Alignment, Command, Element, Length}; +use iced::{Alignment, Command, Element}; pub fn main() -> iced::Result { iced::program("Exit - Iced", Exit::update, Exit::view).run() @@ -46,12 +46,6 @@ impl Exit { .spacing(10) .align_items(Alignment::Center); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .padding(20) - .center_x() - .center_y() - .into() + center(content).padding(20).into() } } diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index b7536740..13d746dd 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -1,6 +1,6 @@ use iced::time::Instant; use iced::widget::{ - checkbox, column, container, image, pick_list, row, slider, text, + center, checkbox, column, container, image, pick_list, row, slider, text, }; use iced::window; use iced::{ @@ -87,28 +87,22 @@ impl Image { } fn view(&self) -> Element { - let i_am_ferris = container( - column![ - "Hello!", - Element::from( - image(format!( - "{}/../tour/images/ferris.png", - env!("CARGO_MANIFEST_DIR") - )) - .width(self.width) - .content_fit(self.content_fit) - .rotation(self.rotation) - ) - .explain(Color::WHITE), - "I am Ferris!" - ] - .spacing(20) - .align_items(Alignment::Center), - ) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y(); + let i_am_ferris = column![ + "Hello!", + Element::from( + image(format!( + "{}/../tour/images/ferris.png", + env!("CARGO_MANIFEST_DIR") + )) + .width(self.width) + .content_fit(self.content_fit) + .rotation(self.rotation) + ) + .explain(Color::WHITE), + "I am Ferris!" + ] + .spacing(20) + .align_items(Alignment::Center); let sizing = row![ pick_list( @@ -126,13 +120,14 @@ impl Image { column![ slider(100.0..=500.0, self.width, Message::WidthChanged), text(format!("Width: {}px", self.width)) - .size(14) + .size(12) .line_height(1.0) ] - .spacing(5) + .spacing(2) .align_items(Alignment::Center) ] - .spacing(10); + .spacing(10) + .align_items(Alignment::End); let rotation = row![ pick_list( @@ -144,30 +139,34 @@ impl Image { Message::RotationStrategyChanged, ) .width(Length::Fill), - row![ - column![ + column![ + row![ slider( Degrees::RANGE, self.rotation.degrees(), Message::RotationChanged ), - text(format!( - "Rotation: {:.0}°", - f32::from(self.rotation.degrees()) - )) - .size(14) - .line_height(1.0) + checkbox("Spin!", self.spin) + .text_size(12) + .on_toggle(Message::SpinToggled) + .size(12) ] - .spacing(5) + .spacing(10) .align_items(Alignment::Center), - checkbox("Spin!", self.spin).on_toggle(Message::SpinToggled) + text(format!( + "Rotation: {:.0}°", + f32::from(self.rotation.degrees()) + )) + .size(12) + .line_height(1.0) ] - .spacing(5) + .spacing(2) .align_items(Alignment::Center) ] - .spacing(10); + .spacing(10) + .align_items(Alignment::End); - container(column![i_am_ferris, sizing, rotation].spacing(10)) + container(column![center(i_am_ferris), sizing, rotation].spacing(10)) .padding(10) .into() } diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 31b8a4ce..bf7801a9 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -153,7 +153,7 @@ mod rainbow { } use iced::widget::{column, container, scrollable}; -use iced::{Element, Length}; +use iced::Element; use rainbow::rainbow; pub fn main() -> iced::Result { @@ -176,12 +176,7 @@ fn view(_state: &()) -> Element<'_, ()> { .spacing(20) .max_width(500); - let scrollable = - scrollable(container(content).width(Length::Fill).center_x()); + let scrollable = scrollable(container(content).center_x()); - container(scrollable) - .width(Length::Fill) - .height(Length::Fill) - .center_y() - .into() + container(scrollable).center_y().into() } diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 66d79091..5f14c03b 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -1,8 +1,8 @@ use iced::keyboard; use iced::mouse; use iced::widget::{ - button, canvas, checkbox, column, container, horizontal_space, pick_list, - row, scrollable, text, + button, canvas, center, checkbox, column, container, horizontal_space, + pick_list, row, scrollable, text, }; use iced::{ color, Alignment, Element, Font, Length, Point, Rectangle, Renderer, @@ -76,7 +76,7 @@ impl Layout { .spacing(20) .align_items(Alignment::Center); - let example = container(if self.explain { + let example = center(if self.explain { self.example.view().explain(color!(0x0000ff)) } else { self.example.view() @@ -87,11 +87,7 @@ impl Layout { container::Style::default() .with_border(palette.background.strong.color, 4.0) }) - .padding(4) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y(); + .padding(4); let controls = row([ (!self.example.is_first()).then_some( @@ -195,12 +191,7 @@ impl Default for Example { } fn centered<'a>() -> Element<'a, Message> { - container(text("I am centered!").size(50)) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(text("I am centered!").size(50)).into() } fn column_<'a>() -> Element<'a, Message> { @@ -260,7 +251,6 @@ fn application<'a>() -> Element<'a, Message> { .align_items(Alignment::Center), ) .style(container::rounded_box) - .height(Length::Fill) .center_y(); let content = container( diff --git a/examples/loading_spinners/src/main.rs b/examples/loading_spinners/src/main.rs index eaa4d57e..e8d67ab5 100644 --- a/examples/loading_spinners/src/main.rs +++ b/examples/loading_spinners/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::{column, container, row, slider, text}; -use iced::{Element, Length}; +use iced::widget::{center, column, row, slider, text}; +use iced::Element; use std::time::Duration; @@ -73,7 +73,7 @@ impl LoadingSpinners { }) .spacing(20); - container( + center( column.push( row![ text("Cycle duration:"), @@ -87,10 +87,6 @@ impl LoadingSpinners { .spacing(20.0), ), ) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() .into() } } diff --git a/examples/loupe/src/main.rs b/examples/loupe/src/main.rs index 42b7f471..c4d3b449 100644 --- a/examples/loupe/src/main.rs +++ b/examples/loupe/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::{button, column, container, text}; -use iced::{Alignment, Element, Length}; +use iced::widget::{button, center, column, text}; +use iced::{Alignment, Element}; use loupe::loupe; @@ -31,7 +31,7 @@ impl Loupe { } fn view(&self) -> Element { - container(loupe( + center(loupe( 3.0, column![ button("Increment").on_press(Message::Increment), @@ -41,10 +41,6 @@ impl Loupe { .padding(20) .align_items(Alignment::Center), )) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() .into() } } diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index a345924d..a012c310 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -2,8 +2,8 @@ use iced::event::{self, Event}; use iced::keyboard; use iced::keyboard::key; use iced::widget::{ - self, button, column, container, horizontal_space, mouse_area, opaque, - pick_list, row, stack, text, text_input, + self, button, center, column, container, horizontal_space, mouse_area, + opaque, pick_list, row, stack, text, text_input, }; use iced::{Alignment, Color, Command, Element, Length, Subscription}; @@ -98,13 +98,7 @@ impl App { row![text("Top Left"), horizontal_space(), text("Top Right")] .align_items(Alignment::Start) .height(Length::Fill), - container( - button(text("Show Modal")).on_press(Message::ShowModal) - ) - .center_x() - .center_y() - .width(Length::Fill) - .height(Length::Fill), + center(button(text("Show Modal")).on_press(Message::ShowModal)), row![ text("Bottom Left"), horizontal_space(), @@ -115,9 +109,7 @@ impl App { ] .height(Length::Fill), ) - .padding(10) - .width(Length::Fill) - .height(Length::Fill); + .padding(10); if self.show_modal { let signup = container( @@ -210,25 +202,18 @@ where { stack![ base.into(), - mouse_area( - container(opaque(content)) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .style(|_theme| { - container::Style { - background: Some( - Color { - a: 0.8, - ..Color::BLACK - } - .into(), - ), - ..container::Style::default() + mouse_area(center(opaque(content)).style(|_theme| { + container::Style { + background: Some( + Color { + a: 0.8, + ..Color::BLACK } - }) - ) + .into(), + ), + ..container::Style::default() + } + })) .on_press(on_blur) ] .into() diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs index 5a5e70c1..74339e0c 100644 --- a/examples/multi_window/src/main.rs +++ b/examples/multi_window/src/main.rs @@ -1,7 +1,9 @@ use iced::event; use iced::executor; use iced::multi_window::{self, Application}; -use iced::widget::{button, column, container, scrollable, text, text_input}; +use iced::widget::{ + button, center, column, container, scrollable, text, text_input, +}; use iced::window; use iced::{ Alignment, Command, Element, Length, Point, Settings, Subscription, Theme, @@ -128,12 +130,7 @@ impl multi_window::Application for Example { fn view(&self, window: window::Id) -> Element { let content = self.windows.get(&window).unwrap().view(window); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } fn theme(&self, window: window::Id) -> Self::Theme { @@ -210,6 +207,6 @@ impl Window { .align_items(Alignment::Center), ); - container(content).width(200).center_x().into() + container(content).center_x().width(200).into() } } diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index 17112785..e74ea1ee 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -291,12 +291,7 @@ fn view_content<'a>( .spacing(10) .align_items(Alignment::Center); - container(scrollable(content)) - .width(Length::Fill) - .height(Length::Fill) - .padding(5) - .center_y() - .into() + container(scrollable(content)).center_y().padding(5).into() } fn view_controls<'a>( diff --git a/examples/pokedex/src/main.rs b/examples/pokedex/src/main.rs index 35f23236..be20094d 100644 --- a/examples/pokedex/src/main.rs +++ b/examples/pokedex/src/main.rs @@ -1,5 +1,5 @@ use iced::futures; -use iced::widget::{self, column, container, image, row, text}; +use iced::widget::{self, center, column, image, row, text}; use iced::{Alignment, Command, Element, Length}; pub fn main() -> iced::Result { @@ -83,12 +83,7 @@ impl Pokedex { .align_items(Alignment::End), }; - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } } diff --git a/examples/qr_code/src/main.rs b/examples/qr_code/src/main.rs index b93adf04..c6a90458 100644 --- a/examples/qr_code/src/main.rs +++ b/examples/qr_code/src/main.rs @@ -1,7 +1,5 @@ -use iced::widget::{ - column, container, pick_list, qr_code, row, text, text_input, -}; -use iced::{Alignment, Element, Length, Theme}; +use iced::widget::{center, column, pick_list, qr_code, row, text, text_input}; +use iced::{Alignment, Element, Theme}; pub fn main() -> iced::Result { iced::program( @@ -72,13 +70,7 @@ impl QRGenerator { .spacing(20) .align_items(Alignment::Center); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .padding(20) - .center_x() - .center_y() - .into() + center(content).padding(20).into() } fn theme(&self) -> Theme { diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index 5c175ccc..82495a1a 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -123,12 +123,10 @@ impl Example { }; let image = container(image) + .center_y() .padding(10) .style(container::rounded_box) - .width(Length::FillPortion(2)) - .height(Length::Fill) - .center_x() - .center_y(); + .width(Length::FillPortion(2)); let crop_origin_controls = row![ text("X:") @@ -213,12 +211,7 @@ impl Example { .spacing(40) }; - let side_content = container(controls) - .align_x(alignment::Horizontal::Center) - .width(Length::FillPortion(1)) - .height(Length::Fill) - .center_y() - .center_x(); + let side_content = container(controls).center_y(); let content = row![side_content, image] .spacing(10) @@ -226,13 +219,7 @@ impl Example { .height(Length::Fill) .align_items(Alignment::Center); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .padding(10) - .center_x() - .center_y() - .into() + container(content).padding(10).into() } fn subscription(&self) -> Subscription { diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index c02e754b..bbb6497f 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -327,7 +327,7 @@ impl ScrollableDemo { .spacing(10) .into(); - container(content).padding(20).center_x().center_y().into() + container(content).padding(20).into() } fn theme(&self) -> Theme { diff --git a/examples/slider/src/main.rs b/examples/slider/src/main.rs index b3a47614..5ffdc9c6 100644 --- a/examples/slider/src/main.rs +++ b/examples/slider/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::{column, container, slider, text, vertical_slider}; -use iced::{Element, Length}; +use iced::widget::{center, column, container, slider, text, vertical_slider}; +use iced::Element; pub fn main() -> iced::Result { iced::run("Slider - Iced", Slider::update, Slider::view) @@ -54,18 +54,14 @@ impl Slider { let text = text(self.value); - container( + center( column![ - container(v_slider).width(Length::Fill).center_x(), - container(h_slider).width(Length::Fill).center_x(), - container(text).width(Length::Fill).center_x(), + container(v_slider).center_x(), + container(h_slider).center_x(), + container(text).center_x() ] .spacing(25), ) - .height(Length::Fill) - .width(Length::Fill) - .center_x() - .center_y() .into() } } diff --git a/examples/stopwatch/src/main.rs b/examples/stopwatch/src/main.rs index b9eb19cf..bbe9d0ff 100644 --- a/examples/stopwatch/src/main.rs +++ b/examples/stopwatch/src/main.rs @@ -1,8 +1,8 @@ use iced::alignment; use iced::keyboard; use iced::time; -use iced::widget::{button, column, container, row, text}; -use iced::{Alignment, Element, Length, Subscription, Theme}; +use iced::widget::{button, center, column, row, text}; +use iced::{Alignment, Element, Subscription, Theme}; use std::time::{Duration, Instant}; @@ -128,12 +128,7 @@ impl Stopwatch { .align_items(Alignment::Center) .spacing(20); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } fn theme(&self) -> Theme { diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index 73268da0..57e8f47e 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -1,7 +1,7 @@ use iced::widget::{ - button, checkbox, column, container, horizontal_rule, pick_list, - progress_bar, row, scrollable, slider, text, text_input, toggler, - vertical_rule, vertical_space, + button, center, checkbox, column, horizontal_rule, pick_list, progress_bar, + row, scrollable, slider, text, text_input, toggler, vertical_rule, + vertical_space, }; use iced::{Alignment, Element, Length, Theme}; @@ -106,12 +106,7 @@ impl Styling { .padding(20) .max_width(600); - container(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content).into() } fn theme(&self) -> Theme { diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 0dcf9bc1..45b46716 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -1,4 +1,4 @@ -use iced::widget::{checkbox, column, container, svg}; +use iced::widget::{center, checkbox, column, container, svg}; use iced::{color, Element, Length}; pub fn main() -> iced::Result { @@ -44,19 +44,12 @@ impl Tiger { checkbox("Apply a color filter", self.apply_color_filter) .on_toggle(Message::ToggleColorFilter); - container( - column![ - svg, - container(apply_color_filter).width(Length::Fill).center_x() - ] - .spacing(20) - .height(Length::Fill), + center( + column![svg, container(apply_color_filter).center_x()] + .spacing(20) + .height(Length::Fill), ) - .width(Length::Fill) - .height(Length::Fill) .padding(20) - .center_x() - .center_y() .into() } } diff --git a/examples/system_information/src/main.rs b/examples/system_information/src/main.rs index a6ac27a6..89a8383a 100644 --- a/examples/system_information/src/main.rs +++ b/examples/system_information/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{button, column, container, text}; -use iced::{system, Command, Element, Length}; +use iced::{system, Command, Element}; pub fn main() -> iced::Result { iced::program("System Information - Iced", Example::update, Example::view) @@ -136,11 +136,6 @@ impl Example { } }; - container(content) - .center_x() - .center_y() - .width(Length::Fill) - .height(Length::Fill) - .into() + container(content).center().into() } } diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index 9968962c..0fcf08c4 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -2,7 +2,7 @@ use iced::event::{self, Event}; use iced::keyboard; use iced::keyboard::key; use iced::widget::{ - self, button, column, container, pick_list, row, slider, text, text_input, + self, button, center, column, pick_list, row, slider, text, text_input, }; use iced::{Alignment, Command, Element, Length, Subscription}; @@ -102,7 +102,7 @@ impl App { .then_some(Message::Add), ); - let content = container( + let content = center( column![ subtitle( "Title", @@ -146,11 +146,7 @@ impl App { ] .spacing(10) .max_width(200), - ) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y(); + ); toast::Manager::new(content, &self.toasts, Message::Close) .timeout(self.timeout_secs) diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 7768c1d5..8119bc91 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -1,8 +1,8 @@ use iced::alignment::{self, Alignment}; use iced::keyboard; use iced::widget::{ - self, button, checkbox, column, container, keyed_column, row, scrollable, - text, text_input, Text, + self, button, center, checkbox, column, container, keyed_column, row, + scrollable, text, text_input, Text, }; use iced::window; use iced::{Command, Element, Font, Length, Subscription}; @@ -238,7 +238,7 @@ impl Todos { .spacing(20) .max_width(800); - scrollable(container(content).padding(40).center_x()).into() + scrollable(container(content).center_x().padding(40)).into() } } } @@ -435,19 +435,16 @@ impl Filter { } fn loading_message<'a>() -> Element<'a, Message> { - container( + center( text("Loading...") .horizontal_alignment(alignment::Horizontal::Center) .size(50), ) - .width(Length::Fill) - .height(Length::Fill) - .center_y() .into() } fn empty_message(message: &str) -> Element<'_, Message> { - container( + center( text(message) .width(Length::Fill) .size(25) @@ -455,7 +452,6 @@ fn empty_message(message: &str) -> Element<'_, Message> { .color([0.7, 0.7, 0.7]), ) .height(200) - .center_y() .into() } diff --git a/examples/tooltip/src/main.rs b/examples/tooltip/src/main.rs index b6603068..f48f688a 100644 --- a/examples/tooltip/src/main.rs +++ b/examples/tooltip/src/main.rs @@ -1,6 +1,6 @@ use iced::widget::tooltip::Position; -use iced::widget::{button, container, tooltip}; -use iced::{Element, Length}; +use iced::widget::{button, center, container, tooltip}; +use iced::Element; pub fn main() -> iced::Result { iced::run("Tooltip - Iced", Tooltip::update, Tooltip::view) @@ -43,12 +43,7 @@ impl Tooltip { .gap(10) .style(container::rounded_box); - container(tooltip) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(tooltip).into() } } diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index e3a2ca87..bae6490d 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -76,11 +76,10 @@ impl Tour { } else { content }) - .width(Length::Fill) .center_x(), ); - container(scrollable).height(Length::Fill).center_y().into() + container(scrollable).center_y().into() } } @@ -670,7 +669,6 @@ fn ferris<'a>( .filter_method(filter_method) .width(width), ) - .width(Length::Fill) .center_x() } diff --git a/examples/url_handler/src/main.rs b/examples/url_handler/src/main.rs index df705b6c..800a188b 100644 --- a/examples/url_handler/src/main.rs +++ b/examples/url_handler/src/main.rs @@ -1,6 +1,6 @@ use iced::event::{self, Event}; -use iced::widget::{container, text}; -use iced::{Element, Length, Subscription}; +use iced::widget::{center, text}; +use iced::{Element, Subscription}; pub fn main() -> iced::Result { iced::program("URL Handler - Iced", App::update, App::view) @@ -44,11 +44,6 @@ impl App { None => text("No URL received yet!"), }; - container(content.size(48)) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() + center(content.size(48)).into() } } diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index b479fe89..e7ececf7 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -1,9 +1,7 @@ mod echo; use iced::alignment::{self, Alignment}; -use iced::widget::{ - button, column, container, row, scrollable, text, text_input, -}; +use iced::widget::{button, center, column, row, scrollable, text, text_input}; use iced::{color, Command, Element, Length, Subscription}; use once_cell::sync::Lazy; @@ -85,14 +83,10 @@ impl WebSocket { fn view(&self) -> Element { let message_log: Element<_> = if self.messages.is_empty() { - container( + center( text("Your messages will appear here...") .color(color!(0x888888)), ) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() .into() } else { scrollable( -- cgit From 4c658c41e9e5bf2c0c963ef49c1830257781b16e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 09:25:47 +0200 Subject: Auto-focus `text_input` in `websocket` example --- examples/websocket/src/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index e7ececf7..ba1e1029 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -1,7 +1,9 @@ mod echo; use iced::alignment::{self, Alignment}; -use iced::widget::{button, center, column, row, scrollable, text, text_input}; +use iced::widget::{ + self, button, center, column, row, scrollable, text, text_input, +}; use iced::{color, Command, Element, Length, Subscription}; use once_cell::sync::Lazy; @@ -29,7 +31,10 @@ enum Message { impl WebSocket { fn load() -> Command { - Command::perform(echo::server::run(), |_| Message::Server) + Command::batch([ + Command::perform(echo::server::run(), |_| Message::Server), + widget::focus_next(), + ]) } fn update(&mut self, message: Message) -> Command { -- cgit From fa9e1d96ea1924b51749b775ea0e67e69bc8a305 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 13:25:58 +0200 Subject: Introduce dynamic `opacity` support for `Image` and `Svg` --- examples/ferris/src/main.rs | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'examples') diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index 13d746dd..1d0e9181 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -17,6 +17,7 @@ pub fn main() -> iced::Result { struct Image { width: f32, + opacity: f32, rotation: Rotation, content_fit: ContentFit, spin: bool, @@ -26,6 +27,7 @@ struct Image { #[derive(Debug, Clone, Copy)] enum Message { WidthChanged(f32), + OpacityChanged(f32), RotationStrategyChanged(RotationStrategy), RotationChanged(Degrees), ContentFitChanged(ContentFit), @@ -39,6 +41,9 @@ impl Image { Message::WidthChanged(width) => { self.width = width; } + Message::OpacityChanged(opacity) => { + self.opacity = opacity; + } Message::RotationStrategyChanged(strategy) => { self.rotation = match strategy { RotationStrategy::Floating => { @@ -97,6 +102,7 @@ impl Image { .width(self.width) .content_fit(self.content_fit) .rotation(self.rotation) + .opacity(self.opacity) ) .explain(Color::WHITE), "I am Ferris!" @@ -117,14 +123,15 @@ impl Image { Message::ContentFitChanged ) .width(Length::Fill), - column![ + with_value( slider(100.0..=500.0, self.width, Message::WidthChanged), - text(format!("Width: {}px", self.width)) - .size(12) - .line_height(1.0) - ] - .spacing(2) - .align_items(Alignment::Center) + format!("Width: {}px", self.width) + ), + with_value( + slider(0.0..=1.0, self.opacity, Message::OpacityChanged) + .step(0.01), + format!("Opacity: {:.2}", self.opacity) + ) ] .spacing(10) .align_items(Alignment::End); @@ -139,7 +146,7 @@ impl Image { Message::RotationStrategyChanged, ) .width(Length::Fill), - column![ + with_value( row![ slider( Degrees::RANGE, @@ -153,15 +160,8 @@ impl Image { ] .spacing(10) .align_items(Alignment::Center), - text(format!( - "Rotation: {:.0}°", - f32::from(self.rotation.degrees()) - )) - .size(12) - .line_height(1.0) - ] - .spacing(2) - .align_items(Alignment::Center) + format!("Rotation: {:.0}°", f32::from(self.rotation.degrees())) + ) ] .spacing(10) .align_items(Alignment::End); @@ -176,6 +176,7 @@ impl Default for Image { fn default() -> Self { Self { width: 300.0, + opacity: 1.0, rotation: Rotation::default(), content_fit: ContentFit::default(), spin: false, @@ -198,3 +199,13 @@ impl std::fmt::Display for RotationStrategy { }) } } + +fn with_value<'a>( + control: impl Into>, + value: String, +) -> Element<'a, Message> { + column![control.into(), text(value).size(12).line_height(1.0)] + .spacing(2) + .align_items(Alignment::Center) + .into() +} -- cgit From afb4cb99b92a196bf4dd15a09a8f9bd191293fdd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 May 2024 13:32:51 +0200 Subject: Improve layout of `ferris` example :crab: --- examples/ferris/src/main.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'examples') diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index 1d0e9181..0400c376 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -110,7 +110,7 @@ impl Image { .spacing(20) .align_items(Alignment::Center); - let sizing = row![ + let fit = row![ pick_list( [ ContentFit::Contain, @@ -123,20 +123,6 @@ impl Image { Message::ContentFitChanged ) .width(Length::Fill), - with_value( - slider(100.0..=500.0, self.width, Message::WidthChanged), - format!("Width: {}px", self.width) - ), - with_value( - slider(0.0..=1.0, self.opacity, Message::OpacityChanged) - .step(0.01), - format!("Opacity: {:.2}", self.opacity) - ) - ] - .spacing(10) - .align_items(Alignment::End); - - let rotation = row![ pick_list( [RotationStrategy::Floating, RotationStrategy::Solid], Some(match self.rotation { @@ -146,6 +132,20 @@ impl Image { Message::RotationStrategyChanged, ) .width(Length::Fill), + ] + .spacing(10) + .align_items(Alignment::End); + + let properties = row![ + with_value( + slider(100.0..=500.0, self.width, Message::WidthChanged), + format!("Width: {}px", self.width) + ), + with_value( + slider(0.0..=1.0, self.opacity, Message::OpacityChanged) + .step(0.01), + format!("Opacity: {:.2}", self.opacity) + ), with_value( row![ slider( @@ -166,7 +166,7 @@ impl Image { .spacing(10) .align_items(Alignment::End); - container(column![center(i_am_ferris), sizing, rotation].spacing(10)) + container(column![fit, center(i_am_ferris), properties].spacing(10)) .padding(10) .into() } -- cgit From 547446f0de076149a4c61e6a4179308b266fd9fd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 6 May 2024 12:14:42 +0200 Subject: Fix windows fighting over shared `image::Cache` Image caches are local to each window now. --- examples/integration/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index c4b57ecf..c2833210 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -157,7 +157,7 @@ pub fn main() -> Result<(), Box> { let mut debug = Debug::new(); let mut engine = Engine::new(&adapter, &device, &queue, format, None); let mut renderer = - Renderer::new(&engine, Font::default(), Pixels::from(16)); + Renderer::new(&device, &engine, Font::default(), Pixels::from(16)); let mut state = program::State::new( controls, -- cgit From 2645524f88414393d8b3ca9c6fe801b32b5ebd33 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 7 May 2024 15:50:18 +0200 Subject: Update `winit` to `0.30` --- examples/integration/README.md | 19 +- examples/integration/index.html | 21 -- examples/integration/src/main.rs | 577 +++++++++++++++++++++------------------ 3 files changed, 308 insertions(+), 309 deletions(-) delete mode 100644 examples/integration/index.html (limited to 'examples') diff --git a/examples/integration/README.md b/examples/integration/README.md index aa3a6e94..bac0640c 100644 --- a/examples/integration/README.md +++ b/examples/integration/README.md @@ -10,25 +10,8 @@ The __[`main`]__ file contains all the code of the example. You can run it with `cargo run`: ``` -cargo run --package integration_wgpu +cargo run --package integration ``` -### How to run this example with WebGL backend -NOTE: Currently, WebGL backend is still experimental, so expect bugs. - -```sh -# 0. Install prerequisites -cargo install wasm-bindgen-cli https -# 1. cd to the current folder -# 2. Compile wasm module -cargo build -p integration_wgpu --target wasm32-unknown-unknown -# 3. Invoke wasm-bindgen -wasm-bindgen ../../target/wasm32-unknown-unknown/debug/integration_wgpu.wasm --out-dir . --target web --no-typescript -# 4. run http server -http -# 5. Open 127.0.0.1:8000 in browser -``` - - [`main`]: src/main.rs [`wgpu`]: https://github.com/gfx-rs/wgpu diff --git a/examples/integration/index.html b/examples/integration/index.html deleted file mode 100644 index 920bc4a0..00000000 --- a/examples/integration/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Iced - wgpu + WebGL integration - - -

integration_wgpu

- - - - - diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index c2833210..e1c7d62f 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -18,305 +18,342 @@ use iced_winit::winit; use iced_winit::Clipboard; use winit::{ - event::{Event, WindowEvent}, + event::WindowEvent, event_loop::{ControlFlow, EventLoop}, keyboard::ModifiersState, }; use std::sync::Arc; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen::JsCast; -#[cfg(target_arch = "wasm32")] -use web_sys::HtmlCanvasElement; -#[cfg(target_arch = "wasm32")] -use winit::platform::web::WindowBuilderExtWebSys; - -pub fn main() -> Result<(), Box> { - #[cfg(target_arch = "wasm32")] - let canvas_element = { - console_log::init().expect("Initialize logger"); - - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - - web_sys::window() - .and_then(|win| win.document()) - .and_then(|doc| doc.get_element_by_id("iced_canvas")) - .and_then(|element| element.dyn_into::().ok()) - .expect("Get canvas element") - }; - - #[cfg(not(target_arch = "wasm32"))] +pub fn main() -> Result<(), winit::error::EventLoopError> { tracing_subscriber::fmt::init(); // Initialize winit let event_loop = EventLoop::new()?; - #[cfg(target_arch = "wasm32")] - let window = winit::window::WindowBuilder::new() - .with_canvas(Some(canvas_element)) - .build(&event_loop)?; - - #[cfg(not(target_arch = "wasm32"))] - let window = winit::window::Window::new(&event_loop)?; - - let window = Arc::new(window); - - let physical_size = window.inner_size(); - let mut viewport = Viewport::with_physical_size( - Size::new(physical_size.width, physical_size.height), - window.scale_factor(), - ); - let mut cursor_position = None; - let mut modifiers = ModifiersState::default(); - let mut clipboard = Clipboard::connect(&window); - - // Initialize wgpu - #[cfg(target_arch = "wasm32")] - let default_backend = wgpu::Backends::GL; - #[cfg(not(target_arch = "wasm32"))] - let default_backend = wgpu::Backends::PRIMARY; - - let backend = - wgpu::util::backend_bits_from_env().unwrap_or(default_backend); - - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: backend, - ..Default::default() - }); - let surface = instance.create_surface(window.clone())?; - - let (format, adapter, device, queue) = - futures::futures::executor::block_on(async { - let adapter = wgpu::util::initialize_adapter_from_env_or_default( - &instance, - Some(&surface), - ) - .await - .expect("Create adapter"); - - let adapter_features = adapter.features(); - - #[cfg(target_arch = "wasm32")] - let needed_limits = wgpu::Limits::downlevel_webgl2_defaults() - .using_resolution(adapter.limits()); - - #[cfg(not(target_arch = "wasm32"))] - let needed_limits = wgpu::Limits::default(); - - let capabilities = surface.get_capabilities(&adapter); - - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: None, - required_features: adapter_features - & wgpu::Features::default(), - required_limits: needed_limits, + #[allow(clippy::large_enum_variant)] + enum Runner { + Loading, + Ready { + window: Arc, + device: wgpu::Device, + queue: wgpu::Queue, + surface: wgpu::Surface<'static>, + format: wgpu::TextureFormat, + engine: Engine, + renderer: Renderer, + scene: Scene, + state: program::State, + cursor_position: Option>, + clipboard: Clipboard, + viewport: Viewport, + modifiers: ModifiersState, + resized: bool, + debug: Debug, + }, + } + + impl winit::application::ApplicationHandler for Runner { + fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + if let Self::Loading = self { + let window = Arc::new( + event_loop + .create_window( + winit::window::WindowAttributes::default(), + ) + .expect("Create window"), + ); + + let physical_size = window.inner_size(); + let viewport = Viewport::with_physical_size( + Size::new(physical_size.width, physical_size.height), + window.scale_factor(), + ); + let clipboard = Clipboard::connect(&window); + + let backend = + wgpu::util::backend_bits_from_env().unwrap_or_default(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: backend, + ..Default::default() + }); + let surface = instance + .create_surface(window.clone()) + .expect("Create window surface"); + + let (format, adapter, device, queue) = + futures::futures::executor::block_on(async { + let adapter = + wgpu::util::initialize_adapter_from_env_or_default( + &instance, + Some(&surface), + ) + .await + .expect("Create adapter"); + + let adapter_features = adapter.features(); + + let capabilities = surface.get_capabilities(&adapter); + + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + required_features: adapter_features + & wgpu::Features::default(), + required_limits: wgpu::Limits::default(), + }, + None, + ) + .await + .expect("Request device"); + + ( + capabilities + .formats + .iter() + .copied() + .find(wgpu::TextureFormat::is_srgb) + .or_else(|| { + capabilities.formats.first().copied() + }) + .expect("Get preferred format"), + adapter, + device, + queue, + ) + }); + + surface.configure( + &device, + &wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format, + width: physical_size.width, + height: physical_size.height, + present_mode: wgpu::PresentMode::AutoVsync, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![], + desired_maximum_frame_latency: 2, }, - None, - ) - .await - .expect("Request device"); - - ( - capabilities - .formats - .iter() - .copied() - .find(wgpu::TextureFormat::is_srgb) - .or_else(|| capabilities.formats.first().copied()) - .expect("Get preferred format"), - adapter, + ); + + // Initialize scene and GUI controls + let scene = Scene::new(&device, format); + let controls = Controls::new(); + + // Initialize iced + let mut debug = Debug::new(); + let engine = + Engine::new(&adapter, &device, &queue, format, None); + let mut renderer = Renderer::new( + &device, + &engine, + Font::default(), + Pixels::from(16), + ); + + let state = program::State::new( + controls, + viewport.logical_size(), + &mut renderer, + &mut debug, + ); + + // You should change this if you want to render continuously + event_loop.set_control_flow(ControlFlow::Wait); + + *self = Self::Ready { + window, + device, + queue, + surface, + format, + engine, + renderer, + scene, + state, + cursor_position: None, + modifiers: ModifiersState::default(), + clipboard, + viewport, + resized: false, + debug, + }; + } + } + + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + _window_id: winit::window::WindowId, + event: WindowEvent, + ) { + let Self::Ready { + window, device, queue, - ) - }); - - surface.configure( - &device, - &wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format, - width: physical_size.width, - height: physical_size.height, - present_mode: wgpu::PresentMode::AutoVsync, - alpha_mode: wgpu::CompositeAlphaMode::Auto, - view_formats: vec![], - desired_maximum_frame_latency: 2, - }, - ); - - let mut resized = false; - - // Initialize scene and GUI controls - let scene = Scene::new(&device, format); - let controls = Controls::new(); - - // Initialize iced - let mut debug = Debug::new(); - let mut engine = Engine::new(&adapter, &device, &queue, format, None); - let mut renderer = - Renderer::new(&device, &engine, Font::default(), Pixels::from(16)); - - let mut state = program::State::new( - controls, - viewport.logical_size(), - &mut renderer, - &mut debug, - ); - - // Run event loop - event_loop.run(move |event, window_target| { - // You should change this if you want to render continuously - window_target.set_control_flow(ControlFlow::Wait); - - match event { - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - if resized { - let size = window.inner_size(); - - viewport = Viewport::with_physical_size( - Size::new(size.width, size.height), - window.scale_factor(), - ); - - surface.configure( - &device, - &wgpu::SurfaceConfiguration { - format, - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - width: size.width, - height: size.height, - present_mode: wgpu::PresentMode::AutoVsync, - alpha_mode: wgpu::CompositeAlphaMode::Auto, - view_formats: vec![], - desired_maximum_frame_latency: 2, - }, - ); - - resized = false; - } - - match surface.get_current_texture() { - Ok(frame) => { - let mut encoder = device.create_command_encoder( - &wgpu::CommandEncoderDescriptor { label: None }, + surface, + format, + engine, + renderer, + scene, + state, + viewport, + cursor_position, + modifiers, + clipboard, + resized, + debug, + } = self + else { + return; + }; + + match event { + WindowEvent::RedrawRequested => { + if *resized { + let size = window.inner_size(); + + *viewport = Viewport::with_physical_size( + Size::new(size.width, size.height), + window.scale_factor(), ); - let program = state.program(); - - let view = frame.texture.create_view( - &wgpu::TextureViewDescriptor::default(), + surface.configure( + device, + &wgpu::SurfaceConfiguration { + format: *format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + width: size.width, + height: size.height, + present_mode: wgpu::PresentMode::AutoVsync, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![], + desired_maximum_frame_latency: 2, + }, ); - { - // We clear the frame - let mut render_pass = Scene::clear( - &view, - &mut encoder, - program.background_color(), + *resized = false; + } + + match surface.get_current_texture() { + Ok(frame) => { + let mut encoder = device.create_command_encoder( + &wgpu::CommandEncoderDescriptor { label: None }, ); - // Draw the scene - scene.draw(&mut render_pass); - } + let program = state.program(); - // And then iced on top - renderer.present( - &mut engine, - &device, - &queue, - &mut encoder, - None, - frame.texture.format(), - &view, - &viewport, - &debug.overlay(), - ); + let view = frame.texture.create_view( + &wgpu::TextureViewDescriptor::default(), + ); + + { + // We clear the frame + let mut render_pass = Scene::clear( + &view, + &mut encoder, + program.background_color(), + ); + + // Draw the scene + scene.draw(&mut render_pass); + } + + // And then iced on top + renderer.present( + engine, + device, + queue, + &mut encoder, + None, + frame.texture.format(), + &view, + viewport, + &debug.overlay(), + ); - // Then we submit the work - queue.submit(Some(encoder.finish())); - frame.present(); + // Then we submit the work + engine.submit(queue, encoder); + frame.present(); - // Update the mouse cursor - 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." - ) - } - _ => { - // Try rendering again next frame. - window.request_redraw(); + // Update the mouse cursor + window.set_cursor( + iced_winit::conversion::mouse_interaction( + state.mouse_interaction(), + ), + ); } - }, - } - } - Event::WindowEvent { event, .. } => { - match event { - WindowEvent::CursorMoved { position, .. } => { - cursor_position = Some(position); - } - WindowEvent::ModifiersChanged(new_modifiers) => { - modifiers = new_modifiers.state(); - } - WindowEvent::Resized(_) => { - resized = true; - } - WindowEvent::CloseRequested => { - window_target.exit(); + Err(error) => match error { + wgpu::SurfaceError::OutOfMemory => { + panic!( + "Swapchain error: {error}. \ + Rendering cannot continue." + ) + } + _ => { + // Try rendering again next frame. + window.request_redraw(); + } + }, } - _ => {} } - - // Map window event to iced event - if let Some(event) = iced_winit::conversion::window_event( - window::Id::MAIN, - event, - window.scale_factor(), - modifiers, - ) { - state.queue_event(event); + WindowEvent::CursorMoved { position, .. } => { + *cursor_position = Some(position); + } + WindowEvent::ModifiersChanged(new_modifiers) => { + *modifiers = new_modifiers.state(); } + WindowEvent::Resized(_) => { + *resized = true; + } + WindowEvent::CloseRequested => { + event_loop.exit(); + } + _ => {} } - _ => {} - } - // If there are events pending - if !state.is_queue_empty() { - // We update iced - let _ = state.update( - viewport.logical_size(), - 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, - }, - &mut clipboard, - &mut debug, - ); - - // and request a redraw - window.request_redraw(); + // Map window event to iced event + if let Some(event) = iced_winit::conversion::window_event( + window::Id::MAIN, + event, + window.scale_factor(), + *modifiers, + ) { + state.queue_event(event); + } + + // If there are events pending + if !state.is_queue_empty() { + // We update iced + let _ = state.update( + viewport.logical_size(), + cursor_position + .map(|p| { + conversion::cursor_position( + p, + viewport.scale_factor(), + ) + }) + .map(mouse::Cursor::Available) + .unwrap_or(mouse::Cursor::Unavailable), + renderer, + &Theme::Dark, + &renderer::Style { + text_color: Color::WHITE, + }, + clipboard, + debug, + ); + + // and request a redraw + window.request_redraw(); + } } - })?; + } - Ok(()) + let mut runner = Runner::Loading; + event_loop.run_app(&mut runner) } -- cgit From 05f69f495e9b52e9a7d7bada420558d4c4f6730c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 13 May 2024 17:56:02 +0200 Subject: Ask for explicit `Length` in `center_*` methods --- examples/editor/src/main.rs | 2 +- examples/geometry/src/main.rs | 6 +++--- examples/layout/src/main.rs | 2 +- examples/multi_window/src/main.rs | 2 +- examples/pane_grid/src/main.rs | 5 ++++- examples/screenshot/src/main.rs | 7 +++---- examples/slider/src/main.rs | 8 ++++---- examples/svg/src/main.rs | 2 +- examples/system_information/src/main.rs | 4 ++-- examples/todos/src/main.rs | 5 ++++- examples/tour/src/main.rs | 6 +++--- 11 files changed, 27 insertions(+), 22 deletions(-) (limited to 'examples') diff --git a/examples/editor/src/main.rs b/examples/editor/src/main.rs index af05031a..c20a7d67 100644 --- a/examples/editor/src/main.rs +++ b/examples/editor/src/main.rs @@ -277,7 +277,7 @@ fn action<'a, Message: Clone + 'a>( label: &'a str, on_press: Option, ) -> Element<'a, Message> { - let action = button(container(content).center_x().width(30)); + let action = button(container(content).center_x(30)); if let Some(on_press) = on_press { tooltip( diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index bf7801a9..3c7969c5 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -153,7 +153,7 @@ mod rainbow { } use iced::widget::{column, container, scrollable}; -use iced::Element; +use iced::{Element, Length}; use rainbow::rainbow; pub fn main() -> iced::Result { @@ -176,7 +176,7 @@ fn view(_state: &()) -> Element<'_, ()> { .spacing(20) .max_width(500); - let scrollable = scrollable(container(content).center_x()); + let scrollable = scrollable(container(content).center_x(Length::Fill)); - container(scrollable).center_y().into() + container(scrollable).center_y(Length::Fill).into() } diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 5f14c03b..c40ac820 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -251,7 +251,7 @@ fn application<'a>() -> Element<'a, Message> { .align_items(Alignment::Center), ) .style(container::rounded_box) - .center_y(); + .center_y(Length::Fill); let content = container( scrollable( diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs index 74339e0c..31c2e4f6 100644 --- a/examples/multi_window/src/main.rs +++ b/examples/multi_window/src/main.rs @@ -207,6 +207,6 @@ impl Window { .align_items(Alignment::Center), ); - container(content).center_x().width(200).into() + container(content).center_x(200).into() } } diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index e74ea1ee..0def1c2b 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -291,7 +291,10 @@ fn view_content<'a>( .spacing(10) .align_items(Alignment::Center); - container(scrollable(content)).center_y().padding(5).into() + container(scrollable(content)) + .center_y(Length::Fill) + .padding(5) + .into() } fn view_controls<'a>( diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index 82495a1a..bd670322 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -123,10 +123,9 @@ impl Example { }; let image = container(image) - .center_y() + .center_y(Length::FillPortion(2)) .padding(10) - .style(container::rounded_box) - .width(Length::FillPortion(2)); + .style(container::rounded_box); let crop_origin_controls = row![ text("X:") @@ -211,7 +210,7 @@ impl Example { .spacing(40) }; - let side_content = container(controls).center_y(); + let side_content = container(controls).center_y(Length::Fill); let content = row![side_content, image] .spacing(10) diff --git a/examples/slider/src/main.rs b/examples/slider/src/main.rs index 5ffdc9c6..0b4c29aa 100644 --- a/examples/slider/src/main.rs +++ b/examples/slider/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{center, column, container, slider, text, vertical_slider}; -use iced::Element; +use iced::{Element, Length}; pub fn main() -> iced::Result { iced::run("Slider - Iced", Slider::update, Slider::view) @@ -56,9 +56,9 @@ impl Slider { center( column![ - container(v_slider).center_x(), - container(h_slider).center_x(), - container(text).center_x() + container(v_slider).center_x(Length::Fill), + container(h_slider).center_x(Length::Fill), + container(text).center_x(Length::Fill) ] .spacing(25), ) diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 45b46716..e071c3af 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -45,7 +45,7 @@ impl Tiger { .on_toggle(Message::ToggleColorFilter); center( - column![svg, container(apply_color_filter).center_x()] + column![svg, container(apply_color_filter).center_x(Length::Fill)] .spacing(20) .height(Length::Fill), ) diff --git a/examples/system_information/src/main.rs b/examples/system_information/src/main.rs index 89a8383a..66bc4979 100644 --- a/examples/system_information/src/main.rs +++ b/examples/system_information/src/main.rs @@ -1,4 +1,4 @@ -use iced::widget::{button, column, container, text}; +use iced::widget::{button, center, column, text}; use iced::{system, Command, Element}; pub fn main() -> iced::Result { @@ -136,6 +136,6 @@ impl Example { } }; - container(content).center().into() + center(content).into() } } diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 8119bc91..e7e05b29 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -238,7 +238,10 @@ impl Todos { .spacing(20) .max_width(800); - scrollable(container(content).center_x().padding(40)).into() + scrollable( + container(content).center_x(Length::Fill).padding(40), + ) + .into() } } } diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index bae6490d..59107258 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -76,10 +76,10 @@ impl Tour { } else { content }) - .center_x(), + .center_x(Length::Fill), ); - container(scrollable).center_y().into() + container(scrollable).center_y(Length::Fill).into() } } @@ -669,7 +669,7 @@ fn ferris<'a>( .filter_method(filter_method) .width(width), ) - .center_x() + .center_x(Length::Fill) } fn padded_button(label: &str) -> Button<'_, Message> { -- cgit From d265cc133efbe02cab890260dbce16768f3d06dd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 May 2024 11:29:41 +0200 Subject: Simplify `clock` example a bit --- examples/clock/src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'examples') diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index 3ffc9f07..7c4685c4 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,5 +1,6 @@ use iced::alignment; use iced::mouse; +use iced::time; use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; use iced::{ @@ -7,9 +8,6 @@ use iced::{ Theme, Vector, }; -use chrono as time; -use time::Timelike; - pub fn main() -> iced::Result { tracing_subscriber::fmt::init(); @@ -21,13 +19,13 @@ pub fn main() -> iced::Result { } struct Clock { - now: time::DateTime, + now: chrono::DateTime, clock: Cache, } #[derive(Debug, Clone, Copy)] enum Message { - Tick(time::DateTime), + Tick(chrono::DateTime), } impl Clock { @@ -57,8 +55,8 @@ impl Clock { } fn subscription(&self) -> Subscription { - iced::time::every(std::time::Duration::from_millis(500)) - .map(|_| Message::Tick(time::offset::Local::now())) + time::every(time::Duration::from_millis(500)) + .map(|_| Message::Tick(chrono::offset::Local::now())) } fn theme(&self) -> Theme { @@ -70,7 +68,7 @@ impl Clock { impl Default for Clock { fn default() -> Self { Self { - now: time::offset::Local::now(), + now: chrono::offset::Local::now(), clock: Cache::default(), } } @@ -87,6 +85,8 @@ impl canvas::Program for Clock { bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { + use chrono::Timelike; + let clock = self.clock.draw(renderer, bounds.size(), |frame| { let palette = theme.extended_palette(); @@ -125,17 +125,17 @@ impl canvas::Program for Clock { frame.translate(Vector::new(center.x, center.y)); frame.with_save(|frame| { - frame.rotate(hand_rotation(self.now.hour() as u8, 12)); + frame.rotate(hand_rotation(self.now.hour(), 12)); frame.stroke(&short_hand, wide_stroke()); }); frame.with_save(|frame| { - frame.rotate(hand_rotation(self.now.minute() as u8, 60)); + frame.rotate(hand_rotation(self.now.minute(), 60)); frame.stroke(&long_hand, wide_stroke()); }); frame.with_save(|frame| { - let rotation = hand_rotation(self.now.second() as u8, 60); + let rotation = hand_rotation(self.now.second(), 60); frame.rotate(rotation); frame.stroke(&long_hand, thin_stroke()); @@ -167,7 +167,7 @@ impl canvas::Program for Clock { } } -fn hand_rotation(n: u8, total: u8) -> Degrees { +fn hand_rotation(n: u32, total: u32) -> Degrees { let turns = n as f32 / total as f32; Degrees(360.0 * turns) -- cgit From 4936efc3751b769984bff4344a9fbb198a7c1ea2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 18 May 2024 11:32:26 +0200 Subject: Remove redundant default `chrono` feature in `clock` example --- examples/clock/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/clock/Cargo.toml b/examples/clock/Cargo.toml index 2fddc7da..bc6c202b 100644 --- a/examples/clock/Cargo.toml +++ b/examples/clock/Cargo.toml @@ -8,5 +8,5 @@ publish = false [dependencies] iced.workspace = true iced.features = ["canvas", "tokio", "debug"] -chrono = { version = "0.4", features = [ "clock" ] } +chrono = "0.4" tracing-subscriber = "0.3" -- cgit From d92e0f7bba8959384467048c7eca84b4b8a7195f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 22 May 2024 12:29:31 +0200 Subject: Fix compilation of `integration` example in `release` mode Fixes #2447. --- examples/integration/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'examples') diff --git a/examples/integration/Cargo.toml b/examples/integration/Cargo.toml index a4a961f8..7f8feb3f 100644 --- a/examples/integration/Cargo.toml +++ b/examples/integration/Cargo.toml @@ -8,7 +8,9 @@ publish = false [dependencies] iced_winit.workspace = true iced_wgpu.workspace = true + iced_widget.workspace = true +iced_widget.features = ["wgpu"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tracing-subscriber = "0.3" -- cgit