summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/arc/src/main.rs14
-rw-r--r--examples/cached/Cargo.toml10
-rw-r--r--examples/cached/src/main.rs139
-rw-r--r--examples/clock/src/main.rs54
-rw-r--r--examples/geometry/Cargo.toml11
-rw-r--r--examples/geometry/README.md18
-rw-r--r--examples/geometry/src/main.rs217
-rw-r--r--examples/lazy/Cargo.toml10
-rw-r--r--examples/lazy/src/main.rs139
-rw-r--r--examples/modern_art/Cargo.toml10
-rw-r--r--examples/modern_art/src/main.rs140
-rw-r--r--examples/multitouch/src/main.rs5
-rw-r--r--examples/scrollable/src/main.rs23
-rw-r--r--examples/solar_system/src/main.rs45
-rw-r--r--examples/styling/src/main.rs57
15 files changed, 569 insertions, 323 deletions
diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs
index 0c619dc9..7b6ea0e1 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::executor;
use iced::widget::canvas::{
- self, Cache, Canvas, Cursor, Geometry, Path, Stroke,
+ self, stroke, Cache, Canvas, Cursor, Geometry, Path, Stroke,
};
use iced::{
Application, Command, Element, Length, Point, Rectangle, Settings,
@@ -52,11 +52,6 @@ impl Application for Arc {
Command::none()
}
- fn subscription(&self) -> Subscription<Message> {
- iced::time::every(std::time::Duration::from_millis(10))
- .map(|_| Message::Tick)
- }
-
fn view(&self) -> Element<Message> {
Canvas::new(self)
.width(Length::Fill)
@@ -67,6 +62,11 @@ impl Application for Arc {
fn theme(&self) -> Theme {
Theme::Dark
}
+
+ fn subscription(&self) -> Subscription<Message> {
+ iced::time::every(std::time::Duration::from_millis(10))
+ .map(|_| Message::Tick)
+ }
}
impl<Message> canvas::Program<Message> for Arc {
@@ -114,7 +114,7 @@ impl<Message> canvas::Program<Message> for Arc {
frame.stroke(
&path,
Stroke {
- color: palette.text,
+ style: stroke::Style::Solid(palette.text),
width: 10.0,
..Stroke::default()
},
diff --git a/examples/cached/Cargo.toml b/examples/cached/Cargo.toml
new file mode 100644
index 00000000..2c7edde2
--- /dev/null
+++ b/examples/cached/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "cached"
+version = "0.1.0"
+authors = ["Nick Senger <dev@nsenger.com>"]
+edition = "2021"
+publish = false
+
+[dependencies]
+iced = { path = "../..", features = ["debug"] }
+iced_lazy = { path = "../../lazy" }
diff --git a/examples/cached/src/main.rs b/examples/cached/src/main.rs
new file mode 100644
index 00000000..8845b874
--- /dev/null
+++ b/examples/cached/src/main.rs
@@ -0,0 +1,139 @@
+use iced::theme;
+use iced::widget::{
+ button, column, horizontal_space, row, scrollable, text, text_input,
+};
+use iced::{Element, Length, Sandbox, Settings};
+use iced_lazy::lazy;
+
+use std::collections::HashSet;
+
+pub fn main() -> iced::Result {
+ App::run(Settings::default())
+}
+
+struct App {
+ options: HashSet<String>,
+ input: String,
+ order: Order,
+}
+
+impl Default for App {
+ fn default() -> Self {
+ Self {
+ options: ["Foo", "Bar", "Baz", "Qux", "Corge", "Waldo", "Fred"]
+ .into_iter()
+ .map(ToString::to_string)
+ .collect(),
+ input: Default::default(),
+ order: Order::Ascending,
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+enum Message {
+ InputChanged(String),
+ ToggleOrder,
+ DeleteOption(String),
+ AddOption(String),
+}
+
+impl Sandbox for App {
+ type Message = Message;
+
+ fn new() -> Self {
+ Self::default()
+ }
+
+ fn title(&self) -> String {
+ String::from("Cached - Iced")
+ }
+
+ fn update(&mut self, message: Message) {
+ match message {
+ Message::InputChanged(input) => {
+ self.input = input;
+ }
+ Message::ToggleOrder => {
+ self.order = match self.order {
+ Order::Ascending => Order::Descending,
+ Order::Descending => Order::Ascending,
+ }
+ }
+ Message::AddOption(option) => {
+ self.options.insert(option);
+ self.input.clear();
+ }
+ Message::DeleteOption(option) => {
+ self.options.remove(&option);
+ }
+ }
+ }
+
+ fn view(&self) -> Element<Message> {
+ let options = lazy((&self.order, self.options.len()), || {
+ let mut options: Vec<_> = self.options.iter().collect();
+
+ options.sort_by(|a, b| match self.order {
+ Order::Ascending => a.to_lowercase().cmp(&b.to_lowercase()),
+ Order::Descending => b.to_lowercase().cmp(&a.to_lowercase()),
+ });
+
+ column(
+ options
+ .into_iter()
+ .map(|option| {
+ row![
+ text(option),
+ horizontal_space(Length::Fill),
+ button("Delete")
+ .on_press(Message::DeleteOption(
+ option.to_string(),
+ ),)
+ .style(theme::Button::Destructive)
+ ]
+ .into()
+ })
+ .collect(),
+ )
+ .spacing(10)
+ });
+
+ column![
+ scrollable(options).height(Length::Fill),
+ row![
+ text_input(
+ "Add a new option",
+ &self.input,
+ Message::InputChanged,
+ )
+ .on_submit(Message::AddOption(self.input.clone())),
+ button(text(format!("Toggle Order ({})", self.order)))
+ .on_press(Message::ToggleOrder)
+ ]
+ .spacing(10)
+ ]
+ .spacing(20)
+ .padding(20)
+ .into()
+ }
+}
+
+#[derive(Debug, Hash)]
+enum Order {
+ Ascending,
+ Descending,
+}
+
+impl std::fmt::Display for Order {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Ascending => "Ascending",
+ Self::Descending => "Descending",
+ }
+ )
+ }
+}
diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs
index 8818fb54..a389c54f 100644
--- a/examples/clock/src/main.rs
+++ b/examples/clock/src/main.rs
@@ -1,5 +1,7 @@
use iced::executor;
-use iced::widget::canvas::{Cache, Cursor, Geometry, LineCap, Path, Stroke};
+use iced::widget::canvas::{
+ stroke, Cache, Cursor, Geometry, LineCap, Path, Stroke,
+};
use iced::widget::{canvas, container};
use iced::{
Application, Color, Command, Element, Length, Point, Rectangle, Settings,
@@ -24,9 +26,9 @@ enum Message {
}
impl Application for Clock {
+ type Executor = executor::Default;
type Message = Message;
type Theme = Theme;
- type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
@@ -59,15 +61,6 @@ impl Application for Clock {
Command::none()
}
- fn subscription(&self) -> Subscription<Message> {
- iced::time::every(std::time::Duration::from_millis(500)).map(|_| {
- Message::Tick(
- time::OffsetDateTime::now_local()
- .unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
- )
- })
- }
-
fn view(&self) -> Element<Message> {
let canvas = canvas(self as &Self)
.width(Length::Fill)
@@ -79,6 +72,15 @@ impl Application for Clock {
.padding(20)
.into()
}
+
+ fn subscription(&self) -> Subscription<Message> {
+ iced::time::every(std::time::Duration::from_millis(500)).map(|_| {
+ Message::Tick(
+ time::OffsetDateTime::now_local()
+ .unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
+ )
+ })
+ }
}
impl<Message> canvas::Program<Message> for Clock {
@@ -104,33 +106,41 @@ impl<Message> canvas::Program<Message> for Clock {
let long_hand =
Path::line(Point::ORIGIN, Point::new(0.0, -0.8 * radius));
- let thin_stroke = Stroke {
- width: radius / 100.0,
- color: Color::WHITE,
- line_cap: LineCap::Round,
- ..Stroke::default()
+ let width = radius / 100.0;
+
+ let thin_stroke = || -> Stroke {
+ Stroke {
+ width,
+ style: stroke::Style::Solid(Color::WHITE),
+ line_cap: LineCap::Round,
+ ..Stroke::default()
+ }
};
- let wide_stroke = Stroke {
- width: thin_stroke.width * 3.0,
- ..thin_stroke
+ let wide_stroke = || -> Stroke {
+ Stroke {
+ width: width * 3.0,
+ style: stroke::Style::Solid(Color::WHITE),
+ line_cap: LineCap::Round,
+ ..Stroke::default()
+ }
};
frame.translate(Vector::new(center.x, center.y));
frame.with_save(|frame| {
frame.rotate(hand_rotation(self.now.hour(), 12));
- frame.stroke(&short_hand, wide_stroke);
+ frame.stroke(&short_hand, wide_stroke());
});
frame.with_save(|frame| {
frame.rotate(hand_rotation(self.now.minute(), 60));
- frame.stroke(&long_hand, wide_stroke);
+ frame.stroke(&long_hand, wide_stroke());
});
frame.with_save(|frame| {
frame.rotate(hand_rotation(self.now.second(), 60));
- frame.stroke(&long_hand, thin_stroke);
+ frame.stroke(&long_hand, thin_stroke());
})
});
diff --git a/examples/geometry/Cargo.toml b/examples/geometry/Cargo.toml
deleted file mode 100644
index 22ede0e0..00000000
--- a/examples/geometry/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "geometry"
-version = "0.1.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-publish = false
-
-[dependencies]
-iced = { path = "../.." }
-iced_native = { path = "../../native" }
-iced_graphics = { path = "../../graphics" }
diff --git a/examples/geometry/README.md b/examples/geometry/README.md
deleted file mode 100644
index 4d5c81cb..00000000
--- a/examples/geometry/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-## Geometry
-
-A custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../../wgpu).
-
-The __[`main`]__ file contains all the code of the example.
-
-<div align="center">
- <a href="https://gfycat.com/activeunfitkangaroo">
- <img src="https://thumbs.gfycat.com/ActiveUnfitKangaroo-small.gif">
- </a>
-</div>
-
-You can run it with `cargo run`:
-```
-cargo run --package geometry
-```
-
-[`main`]: src/main.rs
diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs
deleted file mode 100644
index d8b99ab3..00000000
--- a/examples/geometry/src/main.rs
+++ /dev/null
@@ -1,217 +0,0 @@
-//! This example showcases a simple native custom widget that renders using
-//! arbitrary low-level geometry.
-mod rainbow {
- // For now, to implement a custom native widget you will need to add
- // `iced_native` and `iced_wgpu` to your dependencies.
- //
- // Then, you simply need to define your widget type and implement the
- // `iced_native::Widget` trait with the `iced_wgpu::Renderer`.
- //
- // Of course, you can choose to make the implementation renderer-agnostic,
- // if you wish to, by creating your own `Renderer` trait, which could be
- // implemented by `iced_wgpu` and other renderers.
- use iced_graphics::renderer::{self, Renderer};
- use iced_graphics::{Backend, Primitive};
-
- use iced_native::widget::{self, Widget};
- use iced_native::{
- layout, Element, Layout, Length, Point, Rectangle, Size, Vector,
- };
-
- #[derive(Default)]
- pub struct Rainbow;
-
- impl Rainbow {
- pub fn new() -> Self {
- Self
- }
- }
-
- pub fn rainbow() -> Rainbow {
- Rainbow
- }
-
- impl<Message, B, T> Widget<Message, Renderer<B, T>> for Rainbow
- where
- B: Backend,
- {
- fn width(&self) -> Length {
- Length::Fill
- }
-
- fn height(&self) -> Length {
- Length::Shrink
- }
-
- fn layout(
- &self,
- _renderer: &Renderer<B, T>,
- limits: &layout::Limits,
- ) -> layout::Node {
- let size = limits.width(Length::Fill).resolve(Size::ZERO);
-
- layout::Node::new(Size::new(size.width, size.width))
- }
-
- fn draw(
- &self,
- _tree: &widget::Tree,
- renderer: &mut Renderer<B, T>,
- _theme: &T,
- _style: &renderer::Style,
- layout: Layout<'_>,
- cursor_position: Point,
- _viewport: &Rectangle,
- ) {
- use iced_graphics::triangle::{Mesh2D, Vertex2D};
- use iced_native::Renderer as _;
-
- let b = layout.bounds();
-
- // R O Y G B I V
- let color_r = [1.0, 0.0, 0.0, 1.0];
- let color_o = [1.0, 0.5, 0.0, 1.0];
- let color_y = [1.0, 1.0, 0.0, 1.0];
- let color_g = [0.0, 1.0, 0.0, 1.0];
- let color_gb = [0.0, 1.0, 0.5, 1.0];
- let color_b = [0.0, 0.2, 1.0, 1.0];
- let color_i = [0.5, 0.0, 1.0, 1.0];
- 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]
- } else {
- [b.width / 2.0, b.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 mesh = Primitive::Mesh2D {
- size: b.size(),
- buffers: Mesh2D {
- vertices: vec![
- Vertex2D {
- position: posn_center,
- color: [1.0, 1.0, 1.0, 1.0],
- },
- Vertex2D {
- position: posn_tl,
- color: color_r,
- },
- Vertex2D {
- position: posn_t,
- color: color_o,
- },
- Vertex2D {
- position: posn_tr,
- color: color_y,
- },
- Vertex2D {
- position: posn_r,
- color: color_g,
- },
- Vertex2D {
- position: posn_br,
- color: color_gb,
- },
- Vertex2D {
- position: posn_b,
- color: color_b,
- },
- Vertex2D {
- position: posn_bl,
- color: color_i,
- },
- Vertex2D {
- position: posn_l,
- color: color_v,
- },
- ],
- indices: vec![
- 0, 1, 2, // TL
- 0, 2, 3, // T
- 0, 3, 4, // TR
- 0, 4, 5, // R
- 0, 5, 6, // BR
- 0, 6, 7, // B
- 0, 7, 8, // BL
- 0, 8, 1, // L
- ],
- },
- };
-
- renderer.with_translation(Vector::new(b.x, b.y), |renderer| {
- renderer.draw_primitive(mesh);
- });
- }
- }
-
- impl<'a, Message, B, T> From<Rainbow> for Element<'a, Message, Renderer<B, T>>
- where
- B: Backend,
- {
- fn from(rainbow: Rainbow) -> Self {
- Self::new(rainbow)
- }
- }
-}
-
-use iced::widget::{column, container, scrollable};
-use iced::{Alignment, Element, Length, Sandbox, Settings};
-use rainbow::rainbow;
-
-pub fn main() -> iced::Result {
- Example::run(Settings::default())
-}
-
-struct Example;
-
-impl Sandbox for Example {
- type Message = ();
-
- fn new() -> Self {
- Example
- }
-
- fn title(&self) -> String {
- String::from("Custom 2D geometry - Iced")
- }
-
- fn update(&mut self, _: ()) {}
-
- fn view(&self) -> Element<()> {
- let content = column![
- rainbow(),
- "In this example we draw a custom widget Rainbow, using \
- the Mesh2D primitive. This primitive supplies a list of \
- triangles, expressed as vertices and indices.",
- "Move your cursor over it, and see the center vertex \
- follow you!",
- "Every Vertex2D defines its own color. You could use the \
- Mesh2D primitive to render virtually any two-dimensional \
- geometry for your widget.",
- ]
- .padding(20)
- .spacing(20)
- .max_width(500)
- .align_items(Alignment::Start);
-
- let scrollable =
- scrollable(container(content).width(Length::Fill).center_x());
-
- container(scrollable)
- .width(Length::Fill)
- .height(Length::Fill)
- .center_y()
- .into()
- }
-}
diff --git a/examples/lazy/Cargo.toml b/examples/lazy/Cargo.toml
new file mode 100644
index 00000000..79255c25
--- /dev/null
+++ b/examples/lazy/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "lazy"
+version = "0.1.0"
+authors = ["Nick Senger <dev@nsenger.com>"]
+edition = "2021"
+publish = false
+
+[dependencies]
+iced = { path = "../..", features = ["debug"] }
+iced_lazy = { path = "../../lazy" }
diff --git a/examples/lazy/src/main.rs b/examples/lazy/src/main.rs
new file mode 100644
index 00000000..8845b874
--- /dev/null
+++ b/examples/lazy/src/main.rs
@@ -0,0 +1,139 @@
+use iced::theme;
+use iced::widget::{
+ button, column, horizontal_space, row, scrollable, text, text_input,
+};
+use iced::{Element, Length, Sandbox, Settings};
+use iced_lazy::lazy;
+
+use std::collections::HashSet;
+
+pub fn main() -> iced::Result {
+ App::run(Settings::default())
+}
+
+struct App {
+ options: HashSet<String>,
+ input: String,
+ order: Order,
+}
+
+impl Default for App {
+ fn default() -> Self {
+ Self {
+ options: ["Foo", "Bar", "Baz", "Qux", "Corge", "Waldo", "Fred"]
+ .into_iter()
+ .map(ToString::to_string)
+ .collect(),
+ input: Default::default(),
+ order: Order::Ascending,
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+enum Message {
+ InputChanged(String),
+ ToggleOrder,
+ DeleteOption(String),
+ AddOption(String),
+}
+
+impl Sandbox for App {
+ type Message = Message;
+
+ fn new() -> Self {
+ Self::default()
+ }
+
+ fn title(&self) -> String {
+ String::from("Cached - Iced")
+ }
+
+ fn update(&mut self, message: Message) {
+ match message {
+ Message::InputChanged(input) => {
+ self.input = input;
+ }
+ Message::ToggleOrder => {
+ self.order = match self.order {
+ Order::Ascending => Order::Descending,
+ Order::Descending => Order::Ascending,
+ }
+ }
+ Message::AddOption(option) => {
+ self.options.insert(option);
+ self.input.clear();
+ }
+ Message::DeleteOption(option) => {
+ self.options.remove(&option);
+ }
+ }
+ }
+
+ fn view(&self) -> Element<Message> {
+ let options = lazy((&self.order, self.options.len()), || {
+ let mut options: Vec<_> = self.options.iter().collect();
+
+ options.sort_by(|a, b| match self.order {
+ Order::Ascending => a.to_lowercase().cmp(&b.to_lowercase()),
+ Order::Descending => b.to_lowercase().cmp(&a.to_lowercase()),
+ });
+
+ column(
+ options
+ .into_iter()
+ .map(|option| {
+ row![
+ text(option),
+ horizontal_space(Length::Fill),
+ button("Delete")
+ .on_press(Message::DeleteOption(
+ option.to_string(),
+ ),)
+ .style(theme::Button::Destructive)
+ ]
+ .into()
+ })
+ .collect(),
+ )
+ .spacing(10)
+ });
+
+ column![
+ scrollable(options).height(Length::Fill),
+ row![
+ text_input(
+ "Add a new option",
+ &self.input,
+ Message::InputChanged,
+ )
+ .on_submit(Message::AddOption(self.input.clone())),
+ button(text(format!("Toggle Order ({})", self.order)))
+ .on_press(Message::ToggleOrder)
+ ]
+ .spacing(10)
+ ]
+ .spacing(20)
+ .padding(20)
+ .into()
+ }
+}
+
+#[derive(Debug, Hash)]
+enum Order {
+ Ascending,
+ Descending,
+}
+
+impl std::fmt::Display for Order {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Ascending => "Ascending",
+ Self::Descending => "Descending",
+ }
+ )
+ }
+}
diff --git a/examples/modern_art/Cargo.toml b/examples/modern_art/Cargo.toml
new file mode 100644
index 00000000..a48361ae
--- /dev/null
+++ b/examples/modern_art/Cargo.toml
@@ -0,0 +1,10 @@
+[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"
diff --git a/examples/modern_art/src/main.rs b/examples/modern_art/src/main.rs
new file mode 100644
index 00000000..0dd21c74
--- /dev/null
+++ b/examples/modern_art/src/main.rs
@@ -0,0 +1,140 @@
+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 {
+ 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> for ModernArt {
+ type State = ();
+
+ fn draw(
+ &self,
+ _state: &Self::State,
+ _theme: &Theme,
+ bounds: Rectangle,
+ _cursor: Cursor,
+ ) -> Vec<Geometry> {
+ let geometry = self.cache.draw(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 0345ceb7..f5faae0f 100644
--- a/examples/multitouch/src/main.rs
+++ b/examples/multitouch/src/main.rs
@@ -2,7 +2,8 @@
//! a circle around each fingertip. This only works on touch-enabled
//! computers like Microsoft Surface.
use iced::widget::canvas::event;
-use iced::widget::canvas::{self, Canvas, Cursor, Geometry, Stroke};
+use iced::widget::canvas::stroke::{self, Stroke};
+use iced::widget::canvas::{self, Canvas, Cursor, Geometry};
use iced::{
executor, touch, window, Application, Color, Command, Element, Length,
Point, Rectangle, Settings, Subscription, Theme,
@@ -186,7 +187,7 @@ impl canvas::Program<Message> for State {
frame.stroke(
&path,
Stroke {
- color: Color::BLACK,
+ style: stroke::Style::Solid(Color::BLACK),
width: 3.0,
..Stroke::default()
},
diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs
index b7b3dedc..6eba34e2 100644
--- a/examples/scrollable/src/main.rs
+++ b/examples/scrollable/src/main.rs
@@ -14,9 +14,15 @@ struct ScrollableDemo {
variants: Vec<Variant>,
}
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+enum ThemeType {
+ Light,
+ Dark,
+}
+
#[derive(Debug, Clone)]
enum Message {
- ThemeChanged(Theme),
+ ThemeChanged(ThemeType),
ScrollToTop(usize),
ScrollToBottom(usize),
Scrolled(usize, f32),
@@ -45,7 +51,10 @@ impl Application for ScrollableDemo {
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::ThemeChanged(theme) => {
- self.theme = theme;
+ self.theme = match theme {
+ ThemeType::Light => Theme::Light,
+ ThemeType::Dark => Theme::Dark,
+ };
Command::none()
}
@@ -78,17 +87,15 @@ impl Application for ScrollableDemo {
}
fn view(&self) -> Element<Message> {
- let ScrollableDemo {
- theme, variants, ..
- } = self;
+ let ScrollableDemo { variants, .. } = self;
- let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
+ let choose_theme = [ThemeType::Light, ThemeType::Dark].iter().fold(
column!["Choose a theme:"].spacing(10),
|column, option| {
column.push(radio(
format!("{:?}", option),
*option,
- Some(*theme),
+ Some(*option),
Message::ThemeChanged,
))
},
@@ -198,7 +205,7 @@ impl Application for ScrollableDemo {
}
fn theme(&self) -> Theme {
- self.theme
+ self.theme.clone()
}
}
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index c59d73a8..56787a99 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -11,7 +11,9 @@ use iced::executor;
use iced::theme::{self, Theme};
use iced::time;
use iced::widget::canvas;
-use iced::widget::canvas::{Cursor, Path, Stroke};
+use iced::widget::canvas::gradient::{self, Gradient};
+use iced::widget::canvas::stroke::{self, Stroke};
+use iced::widget::canvas::{Cursor, Path};
use iced::window;
use iced::{
Application, Color, Command, Element, Length, Point, Rectangle, Settings,
@@ -37,9 +39,9 @@ enum Message {
}
impl Application for SolarSystem {
+ type Executor = executor::Default;
type Message = Message;
type Theme = Theme;
- type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
@@ -65,10 +67,6 @@ impl Application for SolarSystem {
Command::none()
}
- fn subscription(&self) -> Subscription<Message> {
- time::every(std::time::Duration::from_millis(10)).map(Message::Tick)
- }
-
fn view(&self) -> Element<Message> {
canvas(&self.state)
.width(Length::Fill)
@@ -86,6 +84,10 @@ impl Application for SolarSystem {
text_color: Color::WHITE,
})
}
+
+ fn subscription(&self) -> Subscription<Message> {
+ time::every(time::Duration::from_millis(10)).map(Message::Tick)
+ }
}
#[derive(Debug)]
@@ -178,8 +180,10 @@ impl<Message> canvas::Program<Message> for State {
frame.stroke(
&orbit,
Stroke {
+ style: stroke::Style::Solid(Color::from_rgba8(
+ 0, 153, 255, 0.1,
+ )),
width: 1.0,
- color: Color::from_rgba8(0, 153, 255, 0.1),
line_dash: canvas::LineDash {
offset: 0,
segments: &[3.0, 6.0],
@@ -198,15 +202,18 @@ impl<Message> canvas::Program<Message> for State {
frame.translate(Vector::new(Self::ORBIT_RADIUS, 0.0));
let earth = Path::circle(Point::ORIGIN, Self::EARTH_RADIUS);
- let shadow = Path::rectangle(
- Point::new(0.0, -Self::EARTH_RADIUS),
- Size::new(
- Self::EARTH_RADIUS * 4.0,
- Self::EARTH_RADIUS * 2.0,
- ),
- );
- frame.fill(&earth, Color::from_rgb8(0x6B, 0x93, 0xD6));
+ 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");
+
+ frame.fill(&earth, earth_fill);
frame.with_save(|frame| {
frame.rotate(rotation * 10.0);
@@ -215,14 +222,6 @@ impl<Message> canvas::Program<Message> for State {
let moon = Path::circle(Point::ORIGIN, Self::MOON_RADIUS);
frame.fill(&moon, Color::WHITE);
});
-
- frame.fill(
- &shadow,
- Color {
- a: 0.7,
- ..Color::BLACK
- },
- );
});
});
diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs
index cda53e87..e16860ad 100644
--- a/examples/styling/src/main.rs
+++ b/examples/styling/src/main.rs
@@ -1,9 +1,10 @@
+use iced::theme::{self, Theme};
use iced::widget::{
button, checkbox, column, container, horizontal_rule, progress_bar, radio,
row, scrollable, slider, text, text_input, toggler, vertical_rule,
vertical_space,
};
-use iced::{Alignment, Element, Length, Sandbox, Settings, Theme};
+use iced::{Alignment, Color, Element, Length, Sandbox, Settings};
pub fn main() -> iced::Result {
Styling::run(Settings::default())
@@ -18,9 +19,16 @@ struct Styling {
toggler_value: bool,
}
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+enum ThemeType {
+ Light,
+ Dark,
+ Custom,
+}
+
#[derive(Debug, Clone)]
enum Message {
- ThemeChanged(Theme),
+ ThemeChanged(ThemeType),
InputChanged(String),
ButtonPressed,
SliderChanged(f32),
@@ -41,7 +49,19 @@ impl Sandbox for Styling {
fn update(&mut self, message: Message) {
match message {
- Message::ThemeChanged(theme) => self.theme = theme,
+ Message::ThemeChanged(theme) => {
+ self.theme = match theme {
+ ThemeType::Light => Theme::Light,
+ ThemeType::Dark => Theme::Dark,
+ ThemeType::Custom => Theme::custom(theme::Palette {
+ background: Color::from_rgb(1.0, 0.9, 1.0),
+ text: Color::BLACK,
+ primary: Color::from_rgb(0.5, 0.5, 0.0),
+ success: Color::from_rgb(0.0, 1.0, 0.0),
+ danger: Color::from_rgb(1.0, 0.0, 0.0),
+ }),
+ }
+ }
Message::InputChanged(value) => self.input_value = value,
Message::ButtonPressed => {}
Message::SliderChanged(value) => self.slider_value = value,
@@ -51,17 +71,24 @@ impl Sandbox for Styling {
}
fn view(&self) -> Element<Message> {
- let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
- column![text("Choose a theme:")].spacing(10),
- |column, theme| {
- column.push(radio(
- format!("{:?}", theme),
- *theme,
- Some(self.theme),
- Message::ThemeChanged,
- ))
- },
- );
+ let choose_theme =
+ [ThemeType::Light, ThemeType::Dark, ThemeType::Custom]
+ .iter()
+ .fold(
+ column![text("Choose a theme:")].spacing(10),
+ |column, theme| {
+ column.push(radio(
+ format!("{:?}", theme),
+ *theme,
+ Some(match self.theme {
+ Theme::Light => ThemeType::Light,
+ Theme::Dark => ThemeType::Dark,
+ Theme::Custom { .. } => ThemeType::Custom,
+ }),
+ Message::ThemeChanged,
+ ))
+ },
+ );
let text_input = text_input(
"Type something...",
@@ -132,6 +159,6 @@ impl Sandbox for Styling {
}
fn theme(&self) -> Theme {
- self.theme
+ self.theme.clone()
}
}