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