diff options
Diffstat (limited to 'examples')
34 files changed, 307 insertions, 130 deletions
diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs index 18873259..88544caa 100644 --- a/examples/arc/src/main.rs +++ b/examples/arc/src/main.rs @@ -4,6 +4,7 @@ use iced::mouse; use iced::widget::canvas::{ self, stroke, Cache, Canvas, Geometry, Path, Stroke, }; +use iced::window; use iced::{Element, Fill, Point, Rectangle, Renderer, Subscription, Theme}; pub fn main() -> iced::Result { @@ -34,8 +35,7 @@ impl Arc { } fn subscription(&self) -> Subscription<Message> { - iced::time::every(std::time::Duration::from_millis(10)) - .map(|_| Message::Tick) + window::frames().map(|_| Message::Tick) } } diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index e8f0efc9..4d438bd9 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::widget::{button, container, horizontal_space, hover}; -use iced::{Element, Fill, Theme}; +use iced::widget::{button, container, horizontal_space, hover, right}; +use iced::{Element, Theme}; pub fn main() -> iced::Result { iced::application("Bezier Tool - Iced", Example::update, Example::view) @@ -41,13 +41,12 @@ impl Example { if self.curves.is_empty() { container(horizontal_space()) } else { - container( + right( button("Clear") .style(button::danger) .on_press(Message::Clear), ) .padding(10) - .align_right(Fill) }, )) .padding(20) diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs index ef3064c7..0810594f 100644 --- a/examples/clock/src/main.rs +++ b/examples/clock/src/main.rs @@ -1,11 +1,11 @@ -use iced::alignment; use iced::mouse; -use iced::time; +use iced::time::{self, milliseconds}; use iced::widget::canvas::{stroke, Cache, Geometry, LineCap, Path, Stroke}; use iced::widget::{canvas, container}; +use iced::{alignment, Radians}; use iced::{ - Degrees, Element, Fill, Font, Point, Rectangle, Renderer, Subscription, - Theme, Vector, + Degrees, Element, Fill, Font, Point, Rectangle, Renderer, Size, + Subscription, Theme, Vector, }; pub fn main() -> iced::Result { @@ -49,7 +49,7 @@ impl Clock { } fn subscription(&self) -> Subscription<Message> { - time::every(time::Duration::from_millis(500)) + time::every(milliseconds(500)) .map(|_| Message::Tick(chrono::offset::Local::now())) } @@ -117,9 +117,14 @@ impl<Message> canvas::Program<Message> for Clock { }; frame.translate(Vector::new(center.x, center.y)); + let minutes_portion = + Radians::from(hand_rotation(self.now.minute(), 60)) / 12.0; + let hour_hand_angle = + Radians::from(hand_rotation(self.now.hour(), 12)) + + minutes_portion; frame.with_save(|frame| { - frame.rotate(hand_rotation(self.now.hour(), 12)); + frame.rotate(hour_hand_angle); frame.stroke(&short_hand, wide_stroke()); }); @@ -155,6 +160,42 @@ impl<Message> canvas::Program<Message> for Clock { ..canvas::Text::default() }); }); + + // Draw clock numbers + for hour in 1..=12 { + let angle = Radians::from(hand_rotation(hour, 12)) + - Radians::from(Degrees(90.0)); + let x = radius * angle.0.cos(); + let y = radius * angle.0.sin(); + + frame.fill_text(canvas::Text { + content: format!("{}", hour), + size: (radius / 5.0).into(), + position: Point::new(x * 0.82, y * 0.82), + color: palette.secondary.strong.text, + horizontal_alignment: alignment::Horizontal::Center, + vertical_alignment: alignment::Vertical::Center, + font: Font::MONOSPACE, + ..canvas::Text::default() + }); + } + + // Draw ticks + for tick in 0..60 { + let angle = hand_rotation(tick, 60); + let width = if tick % 5 == 0 { 3.0 } else { 1.0 }; + + frame.with_save(|frame| { + frame.rotate(angle); + frame.fill( + &Path::rectangle( + Point::new(0.0, radius - 15.0), + Size::new(width, 7.0), + ), + palette.secondary.strong.text, + ); + }); + } }); vec![clock] diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index 7f21003b..1a86b168 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -89,6 +89,7 @@ impl ColorPalette { primary: *self.theme.lower.first().unwrap(), text: *self.theme.higher.last().unwrap(), success: *self.theme.lower.last().unwrap(), + warning: *self.theme.higher.last().unwrap(), danger: *self.theme.higher.last().unwrap(), }, ) diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index 22f86064..02eac329 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -10,4 +10,7 @@ iced.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] iced.workspace = true -iced.features = ["webgl"] +iced.features = ["webgl", "fira-sans"] + +[dev-dependencies] +iced_test.workspace = true diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index 81684c1c..18bb8cfe 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -38,3 +38,31 @@ impl Counter { .align_x(Center) } } + +#[cfg(test)] +mod tests { + use super::*; + use iced_test::selector::text; + use iced_test::{simulator, Error}; + + #[test] + fn it_counts() -> Result<(), Error> { + let mut counter = Counter { value: 0 }; + let mut ui = simulator(counter.view()); + + let _ = ui.click(text("Increment"))?; + let _ = ui.click(text("Increment"))?; + let _ = ui.click(text("Decrement"))?; + + for message in ui.into_messages() { + counter.update(message); + } + + assert_eq!(counter.value, 1); + + let mut ui = simulator(counter.view()); + assert!(ui.find(text("1")).is_ok(), "Counter should display 1!"); + + Ok(()) + } +} diff --git a/examples/editor/src/main.rs b/examples/editor/src/main.rs index d55f9bdf..7032324a 100644 --- a/examples/editor/src/main.rs +++ b/examples/editor/src/main.rs @@ -1,8 +1,8 @@ use iced::highlighter; use iced::keyboard; use iced::widget::{ - self, button, column, container, horizontal_space, pick_list, row, text, - text_editor, toggler, tooltip, + self, button, center_x, column, container, horizontal_space, pick_list, + row, text, text_editor, toggler, tooltip, }; use iced::{Center, Element, Fill, Font, Task, Theme}; @@ -288,7 +288,7 @@ fn action<'a, Message: Clone + 'a>( label: &'a str, on_press: Option<Message>, ) -> Element<'a, Message> { - let action = button(container(content).center_x(30)); + let action = button(center_x(content).width(30)); if let Some(on_press) = on_press { tooltip( diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index 7a7224d5..1008e477 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -5,12 +5,11 @@ mod preset; use grid::Grid; use preset::Preset; -use iced::time; +use iced::time::{self, milliseconds}; use iced::widget::{ button, checkbox, column, container, pick_list, row, slider, text, }; use iced::{Center, Element, Fill, Subscription, Task, Theme}; -use std::time::Duration; pub fn main() -> iced::Result { tracing_subscriber::fmt::init(); @@ -112,7 +111,7 @@ impl GameOfLife { fn subscription(&self) -> Subscription<Message> { if self.is_playing { - time::every(Duration::from_millis(1000 / self.speed as u64)) + time::every(milliseconds(1000 / self.speed as u64)) .map(|_| Message::Tick) } else { Subscription::none() @@ -191,6 +190,7 @@ mod grid { use crate::Preset; use iced::alignment; use iced::mouse; + use iced::time::{Duration, Instant}; use iced::touch; use iced::widget::canvas; use iced::widget::canvas::{ @@ -202,7 +202,6 @@ mod grid { use rustc_hash::{FxHashMap, FxHashSet}; use std::future::Future; use std::ops::RangeInclusive; - use std::time::{Duration, Instant}; pub struct Grid { state: State, diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index d53ae6a5..44214c63 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -152,8 +152,8 @@ mod rainbow { } } -use iced::widget::{column, container, scrollable}; -use iced::{Element, Length}; +use iced::widget::{center_x, center_y, column, scrollable}; +use iced::Element; 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(Length::Fill)); + let scrollable = scrollable(center_x(content)); - container(scrollable).center_y(Length::Fill).into() + center_y(scrollable).into() } diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs index b2de069f..910ea9fc 100644 --- a/examples/gradient/src/main.rs +++ b/examples/gradient/src/main.rs @@ -1,5 +1,5 @@ -use iced::application; use iced::gradient; +use iced::theme; use iced::widget::{ checkbox, column, container, horizontal_space, row, slider, text, }; @@ -95,16 +95,14 @@ impl Gradient { .into() } - fn style(&self, theme: &Theme) -> application::Appearance { - use application::DefaultStyle; - + fn style(&self, theme: &Theme) -> theme::Style { if self.transparent { - application::Appearance { + theme::Style { background_color: Color::TRANSPARENT, text_color: theme.palette().text, } } else { - Theme::default_style(theme) + theme::default(theme) } } } diff --git a/examples/integration/src/controls.rs b/examples/integration/src/controls.rs index 0b11a323..b92e4987 100644 --- a/examples/integration/src/controls.rs +++ b/examples/integration/src/controls.rs @@ -1,6 +1,6 @@ use iced_wgpu::Renderer; -use iced_widget::{column, container, row, slider, text, text_input}; -use iced_winit::core::{Color, Element, Length::*, Theme}; +use iced_widget::{bottom, column, row, slider, text, text_input}; +use iced_winit::core::{Color, Element, Theme}; use iced_winit::runtime::{Program, Task}; pub struct Controls { @@ -74,18 +74,17 @@ impl Program for Controls { .width(500) .spacing(20); - container( + bottom( column![ text("Background color").color(Color::WHITE), text!("{background_color:?}").size(14).color(Color::WHITE), - text_input("Placeholder", &self.input) - .on_input(Message::InputChanged), sliders, + text_input("Type something...", &self.input) + .on_input(Message::InputChanged), ] .spacing(10), ) .padding(10) - .align_bottom(Fill) .into() } } diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index e83a1f7d..b298dce4 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -2,9 +2,9 @@ use iced::border; use iced::keyboard; use iced::mouse; use iced::widget::{ - button, canvas, center, checkbox, column, container, horizontal_rule, - horizontal_space, pick_list, pin, row, scrollable, stack, text, - vertical_rule, + button, canvas, center, center_y, checkbox, column, container, + horizontal_rule, horizontal_space, pick_list, pin, row, scrollable, stack, + text, vertical_rule, }; use iced::{ color, Center, Element, Fill, Font, Length, Point, Rectangle, Renderer, @@ -253,15 +253,14 @@ fn application<'a>() -> Element<'a, Message> { .border(border::color(palette.background.strong.color).width(1)) }); - let sidebar = container( + let sidebar = center_y( column!["Sidebar!", square(50), square(50)] .spacing(40) .padding(10) .width(200) .align_x(Center), ) - .style(container::rounded_box) - .center_y(Fill); + .style(container::rounded_box); let content = container( scrollable( diff --git a/examples/loading_spinners/Cargo.toml b/examples/loading_spinners/Cargo.toml index a32da386..abd28aec 100644 --- a/examples/loading_spinners/Cargo.toml +++ b/examples/loading_spinners/Cargo.toml @@ -10,4 +10,3 @@ iced.workspace = true iced.features = ["advanced", "canvas"] lyon_algorithms = "1.0" -once_cell.workspace = true
\ No newline at end of file diff --git a/examples/loading_spinners/src/easing.rs b/examples/loading_spinners/src/easing.rs index 45089ef6..8caf282d 100644 --- a/examples/loading_spinners/src/easing.rs +++ b/examples/loading_spinners/src/easing.rs @@ -2,40 +2,41 @@ use iced::Point; use lyon_algorithms::measure::PathMeasurements; use lyon_algorithms::path::{builder::NoAttributes, path::BuilderImpl, Path}; -use once_cell::sync::Lazy; -pub static EMPHASIZED: Lazy<Easing> = Lazy::new(|| { +use std::sync::LazyLock; + +pub static EMPHASIZED: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.05, 0.0], [0.133333, 0.06], [0.166666, 0.4]) .cubic_bezier_to([0.208333, 0.82], [0.25, 1.0], [1.0, 1.0]) .build() }); -pub static EMPHASIZED_DECELERATE: Lazy<Easing> = Lazy::new(|| { +pub static EMPHASIZED_DECELERATE: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.05, 0.7], [0.1, 1.0], [1.0, 1.0]) .build() }); -pub static EMPHASIZED_ACCELERATE: Lazy<Easing> = Lazy::new(|| { +pub static EMPHASIZED_ACCELERATE: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.3, 0.0], [0.8, 0.15], [1.0, 1.0]) .build() }); -pub static STANDARD: Lazy<Easing> = Lazy::new(|| { +pub static STANDARD: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.2, 0.0], [0.0, 1.0], [1.0, 1.0]) .build() }); -pub static STANDARD_DECELERATE: Lazy<Easing> = Lazy::new(|| { +pub static STANDARD_DECELERATE: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.0, 0.0], [0.0, 1.0], [1.0, 1.0]) .build() }); -pub static STANDARD_ACCELERATE: Lazy<Easing> = Lazy::new(|| { +pub static STANDARD_ACCELERATE: LazyLock<Easing> = LazyLock::new(|| { Easing::builder() .cubic_bezier_to([0.3, 0.0], [1.0, 1.0], [1.0, 1.0]) .build() diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs index b43a627a..f9021c8d 100644 --- a/examples/multi_window/src/main.rs +++ b/examples/multi_window/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{ - button, center, column, container, horizontal_space, scrollable, text, + button, center, center_x, column, horizontal_space, scrollable, text, text_input, }; use iced::window; @@ -193,6 +193,6 @@ impl Window { .align_x(Center), ); - container(content).center_x(200).into() + center_x(content).width(200).into() } } diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index 67f4d27f..17ba5804 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -1,7 +1,7 @@ use iced::keyboard; use iced::widget::pane_grid::{self, PaneGrid}; use iced::widget::{ - button, column, container, responsive, row, scrollable, text, + button, center_y, column, container, responsive, row, scrollable, text, }; use iced::{Center, Color, Element, Fill, Size, Subscription}; @@ -196,11 +196,7 @@ impl Example { .on_drag(Message::Dragged) .on_resize(10, Message::Resized); - container(pane_grid) - .width(Fill) - .height(Fill) - .padding(10) - .into() + container(pane_grid).padding(10).into() } } @@ -295,10 +291,7 @@ fn view_content<'a>( .spacing(10) .align_x(Center); - container(scrollable(content)) - .center_y(Fill) - .padding(5) - .into() + center_y(scrollable(content)).padding(5).into() } fn view_controls<'a>( diff --git a/examples/progress_bar/src/main.rs b/examples/progress_bar/src/main.rs index 67da62f2..e431a404 100644 --- a/examples/progress_bar/src/main.rs +++ b/examples/progress_bar/src/main.rs @@ -1,4 +1,7 @@ -use iced::widget::{column, progress_bar, slider}; +use iced::widget::{ + center, center_x, checkbox, column, progress_bar, row, slider, + vertical_slider, +}; use iced::Element; pub fn main() -> iced::Result { @@ -8,25 +11,58 @@ pub fn main() -> iced::Result { #[derive(Default)] struct Progress { value: f32, + is_vertical: bool, } #[derive(Debug, Clone, Copy)] enum Message { SliderChanged(f32), + ToggleVertical(bool), } impl Progress { fn update(&mut self, message: Message) { match message { Message::SliderChanged(x) => self.value = x, + Message::ToggleVertical(is_vertical) => { + self.is_vertical = is_vertical + } } } fn view(&self) -> Element<Message> { + let bar = progress_bar(0.0..=100.0, self.value); + column![ - progress_bar(0.0..=100.0, self.value), - slider(0.0..=100.0, self.value, Message::SliderChanged).step(0.01) + if self.is_vertical { + center( + row![ + bar.vertical(), + vertical_slider( + 0.0..=100.0, + self.value, + Message::SliderChanged + ) + .step(0.01) + ] + .spacing(20), + ) + } else { + center( + column![ + bar, + slider(0.0..=100.0, self.value, Message::SliderChanged) + .step(0.01) + ] + .spacing(20), + ) + }, + center_x( + checkbox("Vertical", self.is_vertical) + .on_toggle(Message::ToggleVertical) + ), ] + .spacing(20) .padding(20) .into() } diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index 5c105f6c..7766542d 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -1,5 +1,7 @@ use iced::keyboard; -use iced::widget::{button, column, container, image, row, text, text_input}; +use iced::widget::{ + button, center_y, column, container, image, row, text, text_input, +}; use iced::window; use iced::window::screenshot::{self, Screenshot}; use iced::{ @@ -131,8 +133,8 @@ impl Example { text("Press the button to take a screenshot!").into() }; - let image = container(image) - .center_y(FillPortion(2)) + let image = center_y(image) + .height(FillPortion(2)) .padding(10) .style(container::rounded_box); @@ -211,7 +213,7 @@ impl Example { .spacing(40) }; - let side_content = container(controls).center_y(Fill); + let side_content = center_y(controls); let content = row![side_content, image] .spacing(10) diff --git a/examples/scrollable/Cargo.toml b/examples/scrollable/Cargo.toml index f8c735c0..ba291520 100644 --- a/examples/scrollable/Cargo.toml +++ b/examples/scrollable/Cargo.toml @@ -8,5 +8,3 @@ publish = false [dependencies] iced.workspace = true iced.features = ["debug"] - -once_cell.workspace = true diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index de4f2f9a..6359fb5a 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -4,9 +4,10 @@ use iced::widget::{ }; use iced::{Border, Center, Color, Element, Fill, Task, Theme}; -use once_cell::sync::Lazy; +use std::sync::LazyLock; -static SCROLLABLE_ID: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique); +static SCROLLABLE_ID: LazyLock<scrollable::Id> = + LazyLock::new(scrollable::Id::unique); pub fn main() -> iced::Result { iced::application( diff --git a/examples/stopwatch/src/main.rs b/examples/stopwatch/src/main.rs index 0d824d36..a814da55 100644 --- a/examples/stopwatch/src/main.rs +++ b/examples/stopwatch/src/main.rs @@ -1,10 +1,8 @@ use iced::keyboard; -use iced::time; +use iced::time::{self, milliseconds, Duration, Instant}; use iced::widget::{button, center, column, row, text}; use iced::{Center, Element, Subscription, Theme}; -use std::time::{Duration, Instant}; - pub fn main() -> iced::Result { iced::application("Stopwatch - Iced", Stopwatch::update, Stopwatch::view) .subscription(Stopwatch::subscription) @@ -63,7 +61,7 @@ impl Stopwatch { let tick = match self.state { State::Idle => Subscription::none(), State::Ticking { .. } => { - time::every(Duration::from_millis(10)).map(Message::Tick) + time::every(milliseconds(10)).map(Message::Tick) } }; diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index 534f5e32..594be4a7 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -1,12 +1,14 @@ +use iced::keyboard; use iced::widget::{ button, center, checkbox, column, horizontal_rule, pick_list, progress_bar, row, scrollable, slider, text, text_input, toggler, vertical_rule, vertical_space, }; -use iced::{Center, Element, Fill, Theme}; +use iced::{Center, Element, Fill, Subscription, Theme}; pub fn main() -> iced::Result { iced::application("Styling - Iced", Styling::update, Styling::view) + .subscription(Styling::subscription) .theme(Styling::theme) .run() } @@ -28,6 +30,8 @@ enum Message { SliderChanged(f32), CheckboxToggled(bool), TogglerToggled(bool), + PreviousTheme, + NextTheme, } impl Styling { @@ -41,6 +45,23 @@ impl Styling { Message::SliderChanged(value) => self.slider_value = value, Message::CheckboxToggled(value) => self.checkbox_value = value, Message::TogglerToggled(value) => self.toggler_value = value, + Message::PreviousTheme | Message::NextTheme => { + if let Some(current) = Theme::ALL + .iter() + .position(|candidate| &self.theme == candidate) + { + self.theme = if matches!(message, Message::NextTheme) { + Theme::ALL[(current + 1) % Theme::ALL.len()].clone() + } else if current == 0 { + Theme::ALL + .last() + .expect("Theme::ALL must not be empty") + .clone() + } else { + Theme::ALL[current - 1].clone() + }; + } + } } } @@ -57,9 +78,16 @@ impl Styling { .padding(10) .size(20); - let button = button("Submit") - .padding(10) - .on_press(Message::ButtonPressed); + let styled_button = |label| { + button(text(label).width(Fill).center()) + .padding(10) + .on_press(Message::ButtonPressed) + }; + + let primary = styled_button("Primary"); + let success = styled_button("Success").style(button::success); + let warning = styled_button("Warning").style(button::warning); + let danger = styled_button("Danger").style(button::danger); let slider = slider(0.0..=100.0, self.slider_value, Message::SliderChanged); @@ -85,7 +113,10 @@ impl Styling { let content = column![ choose_theme, horizontal_rule(38), - row![text_input, button].spacing(10).align_y(Center), + text_input, + row![primary, success, warning, danger] + .spacing(10) + .align_y(Center), slider, progress_bar, row![ @@ -104,6 +135,19 @@ impl Styling { center(content).into() } + fn subscription(&self) -> Subscription<Message> { + keyboard::on_key_press(|key, _modifiers| match key { + keyboard::Key::Named( + keyboard::key::Named::ArrowUp | keyboard::key::Named::ArrowLeft, + ) => Some(Message::PreviousTheme), + keyboard::Key::Named( + keyboard::key::Named::ArrowDown + | keyboard::key::Named::ArrowRight, + ) => Some(Message::NextTheme), + _ => None, + }) + } + fn theme(&self) -> Theme { self.theme.clone() } diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 02cb85cc..c4be8fb8 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -1,4 +1,4 @@ -use iced::widget::{center, checkbox, column, container, svg}; +use iced::widget::{center, center_x, checkbox, column, svg}; use iced::{color, Element, Fill}; pub fn main() -> iced::Result { @@ -46,12 +46,8 @@ impl Tiger { checkbox("Apply a color filter", self.apply_color_filter) .on_toggle(Message::ToggleColorFilter); - center( - column![svg, container(apply_color_filter).center_x(Fill)] - .spacing(20) - .height(Fill), - ) - .padding(20) - .into() + center(column![svg, center_x(apply_color_filter)].spacing(20)) + .padding(20) + .into() } } diff --git a/examples/the_matrix/src/main.rs b/examples/the_matrix/src/main.rs index 0ed52dda..315e9ee5 100644 --- a/examples/the_matrix/src/main.rs +++ b/examples/the_matrix/src/main.rs @@ -1,5 +1,5 @@ use iced::mouse; -use iced::time::{self, Instant}; +use iced::time::{self, milliseconds, Instant}; use iced::widget::canvas; use iced::{ Color, Element, Fill, Font, Point, Rectangle, Renderer, Subscription, Theme, @@ -36,11 +36,11 @@ impl TheMatrix { } fn view(&self) -> Element<Message> { - canvas(self as &Self).width(Fill).height(Fill).into() + canvas(self).width(Fill).height(Fill).into() } fn subscription(&self) -> Subscription<Message> { - time::every(std::time::Duration::from_millis(50)).map(Message::Tick) + time::every(milliseconds(50)).map(Message::Tick) } } diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index a1b5886f..2ae9bfe2 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -162,7 +162,6 @@ impl Default for App { mod toast { use std::fmt; - use std::time::{Duration, Instant}; use iced::advanced::layout::{self, Layout}; use iced::advanced::overlay; @@ -171,6 +170,7 @@ mod toast { use iced::advanced::{Clipboard, Shell, Widget}; use iced::mouse; use iced::theme; + use iced::time::{self, Duration, Instant}; use iced::widget::{ button, column, container, horizontal_rule, horizontal_space, row, text, }; @@ -502,9 +502,8 @@ mod toast { self.instants.iter_mut().enumerate().for_each( |(index, maybe_instant)| { if let Some(instant) = maybe_instant.as_mut() { - let remaining = - Duration::from_secs(self.timeout_secs) - .saturating_sub(instant.elapsed()); + let remaining = time::seconds(self.timeout_secs) + .saturating_sub(instant.elapsed()); if remaining == Duration::ZERO { maybe_instant.take(); diff --git a/examples/todos/Cargo.toml b/examples/todos/Cargo.toml index 0d72be86..16f4fdd2 100644 --- a/examples/todos/Cargo.toml +++ b/examples/todos/Cargo.toml @@ -20,12 +20,15 @@ tracing-subscriber = "0.3" [target.'cfg(target_arch = "wasm32")'.dependencies] iced.workspace = true -iced.features = ["debug", "webgl"] +iced.features = ["debug", "webgl", "fira-sans"] uuid = { version = "1.0", features = ["js"] } web-sys = { workspace = true, features = ["Window", "Storage"] } wasm-timer.workspace = true +[dev-dependencies] +iced_test.workspace = true + [package.metadata.deb] assets = [ ["target/release-opt/todos", "usr/bin/iced-todos", "755"], diff --git a/examples/todos/snapshots/creates_a_new_task.sha256 b/examples/todos/snapshots/creates_a_new_task.sha256 new file mode 100644 index 00000000..193132c5 --- /dev/null +++ b/examples/todos/snapshots/creates_a_new_task.sha256 @@ -0,0 +1 @@ +3160686067cb7c738802009cdf2f3c5f5a5bd8c89ada70517388b7adbe64c313
\ No newline at end of file diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 25e3ead2..7759552c 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -1,6 +1,6 @@ use iced::keyboard; use iced::widget::{ - self, button, center, checkbox, column, container, keyed_column, row, + self, button, center, center_x, checkbox, column, keyed_column, row, scrollable, text, text_input, Text, }; use iced::window; @@ -15,7 +15,7 @@ pub fn main() -> iced::Result { iced::application(Todos::title, Todos::update, Todos::view) .subscription(Todos::subscription) - .font(include_bytes!("../fonts/icons.ttf").as_slice()) + .font(Todos::ICON_FONT) .window_size((500.0, 800.0)) .run_with(Todos::new) } @@ -48,6 +48,8 @@ enum Message { } impl Todos { + const ICON_FONT: &'static [u8] = include_bytes!("../fonts/icons.ttf"); + fn new() -> (Self, Command<Message>) { ( Self::Loading, @@ -147,9 +149,7 @@ impl Todos { } } Message::ToggleFullscreen(mode) => window::get_latest() - .and_then(move |window| { - window::change_mode(window, mode) - }), + .and_then(move |window| window::set_mode(window, mode)), Message::Loaded(_) => Command::none(), }; @@ -237,7 +237,7 @@ impl Todos { .spacing(20) .max_width(800); - scrollable(container(content).center_x(Fill).padding(40)).into() + scrollable(center_x(content).padding(40)).into() } } } @@ -449,11 +449,10 @@ fn empty_message(message: &str) -> Element<'_, Message> { } // Fonts -const ICONS: Font = Font::with_name("Iced-Todos-Icons"); fn icon(unicode: char) -> Text<'static> { text(unicode.to_string()) - .font(ICONS) + .font(Font::with_name("Iced-Todos-Icons")) .width(20) .align_x(Center) } @@ -584,3 +583,49 @@ impl SavedState { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + use iced::{Settings, Theme}; + use iced_test::selector::text; + use iced_test::{Error, Simulator}; + + fn simulator(todos: &Todos) -> Simulator<Message> { + Simulator::with_settings( + Settings { + fonts: vec![Todos::ICON_FONT.into()], + ..Settings::default() + }, + todos.view(), + ) + } + + #[test] + fn it_creates_a_new_task() -> Result<(), Error> { + let (mut todos, _command) = Todos::new(); + let _command = todos.update(Message::Loaded(Err(LoadError::File))); + + let mut ui = simulator(&todos); + let _input = ui.click("new-task")?; + + let _ = ui.typewrite("Create the universe"); + let _ = ui.tap_key(keyboard::key::Named::Enter); + + for message in ui.into_messages() { + let _command = todos.update(message); + } + + let mut ui = simulator(&todos); + let _ = ui.find(text("Create the universe"))?; + + let snapshot = ui.snapshot(&Theme::Dark)?; + assert!( + snapshot.matches_hash("snapshots/creates_a_new_task")?, + "snapshots should match!" + ); + + Ok(()) + } +} diff --git a/examples/tour/Cargo.toml b/examples/tour/Cargo.toml index 9e984ad1..719d355f 100644 --- a/examples/tour/Cargo.toml +++ b/examples/tour/Cargo.toml @@ -14,7 +14,7 @@ tracing-subscriber = "0.3" [target.'cfg(target_arch = "wasm32")'.dependencies] iced.workspace = true -iced.features = ["image", "debug", "webgl"] +iced.features = ["image", "debug", "webgl", "fira-sans"] console_error_panic_hook = "0.1" console_log = "1.0" diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index d8c0b29a..32720c47 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -1,6 +1,6 @@ use iced::widget::{ - button, checkbox, column, container, horizontal_space, image, radio, row, - scrollable, slider, text, text_input, toggler, vertical_space, + button, center_x, center_y, checkbox, column, horizontal_space, image, + radio, row, scrollable, slider, text, text_input, toggler, vertical_space, }; use iced::widget::{Button, Column, Container, Slider}; use iced::{Center, Color, Element, Fill, Font, Pixels}; @@ -166,16 +166,13 @@ impl Tour { .padding(20) .into(); - let scrollable = scrollable( - container(if self.debug { - content.explain(Color::BLACK) - } else { - content - }) - .center_x(Fill), - ); + let scrollable = scrollable(center_x(if self.debug { + content.explain(Color::BLACK) + } else { + content + })); - container(scrollable).center_y(Fill).into() + center_y(scrollable).into() } fn can_continue(&self) -> bool { @@ -543,7 +540,7 @@ fn ferris<'a>( width: u16, filter_method: image::FilterMethod, ) -> Container<'a, Message> { - container( + center_x( // This should go away once we unify resource loading on native // platforms if cfg!(target_arch = "wasm32") { @@ -554,7 +551,6 @@ fn ferris<'a>( .filter_method(filter_method) .width(width), ) - .center_x(Fill) } fn padded_button<Message: Clone>(label: &str) -> Button<'_, Message> { diff --git a/examples/visible_bounds/Cargo.toml b/examples/visible_bounds/Cargo.toml index 37594b84..1193334d 100644 --- a/examples/visible_bounds/Cargo.toml +++ b/examples/visible_bounds/Cargo.toml @@ -8,5 +8,3 @@ publish = false [dependencies] iced.workspace = true iced.features = ["debug"] - -once_cell.workspace = true diff --git a/examples/visible_bounds/src/main.rs b/examples/visible_bounds/src/main.rs index 77fec65e..f8f9f420 100644 --- a/examples/visible_bounds/src/main.rs +++ b/examples/visible_bounds/src/main.rs @@ -157,9 +157,9 @@ impl Example { } } -use once_cell::sync::Lazy; +use std::sync::LazyLock; -static OUTER_CONTAINER: Lazy<container::Id> = - Lazy::new(|| container::Id::new("outer")); -static INNER_CONTAINER: Lazy<container::Id> = - Lazy::new(|| container::Id::new("inner")); +static OUTER_CONTAINER: LazyLock<container::Id> = + LazyLock::new(|| container::Id::new("outer")); +static INNER_CONTAINER: LazyLock<container::Id> = + LazyLock::new(|| container::Id::new("inner")); diff --git a/examples/websocket/Cargo.toml b/examples/websocket/Cargo.toml index c7075fb3..787dbbe1 100644 --- a/examples/websocket/Cargo.toml +++ b/examples/websocket/Cargo.toml @@ -9,7 +9,6 @@ publish = false iced.workspace = true iced.features = ["debug", "tokio"] -once_cell.workspace = true warp = "0.3" [dependencies.async-tungstenite] diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index 8b1efb41..ae658471 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -4,7 +4,7 @@ use iced::widget::{ self, button, center, column, row, scrollable, text, text_input, }; use iced::{color, Center, Element, Fill, Subscription, Task}; -use once_cell::sync::Lazy; +use std::sync::LazyLock; pub fn main() -> iced::Result { iced::application("WebSocket - Iced", WebSocket::update, WebSocket::view) @@ -138,4 +138,5 @@ enum State { Connected(echo::Connection), } -static MESSAGE_LOG: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique); +static MESSAGE_LOG: LazyLock<scrollable::Id> = + LazyLock::new(scrollable::Id::unique); |