diff options
author | 2023-07-12 19:21:05 -0700 | |
---|---|---|
committer | 2023-07-21 13:53:38 -0700 | |
commit | d53ccc857da4d4cda769904342aeb5a82a64f146 (patch) | |
tree | 7de16b72e0e054d10380586ba5b79a7181478aa7 /src | |
parent | 633f405f3f78bc7f82d2b2061491b0e011137451 (diff) | |
download | iced-d53ccc857da4d4cda769904342aeb5a82a64f146.tar.gz iced-d53ccc857da4d4cda769904342aeb5a82a64f146.tar.bz2 iced-d53ccc857da4d4cda769904342aeb5a82a64f146.zip |
refactored window storage;
new helper window events (Destroyed, Created);
clippy + fmt;
Diffstat (limited to 'src')
-rw-r--r-- | src/multi_window/application.rs | 96 | ||||
-rw-r--r-- | src/settings.rs | 2 | ||||
-rw-r--r-- | src/window.rs | 4 | ||||
-rw-r--r-- | src/window/icon.rs | 63 |
4 files changed, 106 insertions, 59 deletions
diff --git a/src/multi_window/application.rs b/src/multi_window/application.rs index 9974128c..0486159e 100644 --- a/src/multi_window/application.rs +++ b/src/multi_window/application.rs @@ -1,30 +1,37 @@ use crate::window; use crate::{Command, Element, Executor, Settings, Subscription}; -pub use iced_native::application::{Appearance, StyleSheet}; +pub use crate::style::application::{Appearance, StyleSheet}; /// An interactive cross-platform multi-window application. /// /// This trait is the main entrypoint of Iced. Once implemented, you can run /// your GUI application by simply calling [`run`](#method.run). /// +/// - On native platforms, it will run in its own windows. +/// - On the web, it will take control of the `<title>` and the `<body>` of the +/// document and display only the contents of the `window::Id::MAIN` window. +/// /// An [`Application`] can execute asynchronous actions by returning a -/// [`Command`] in some of its methods. For example, to spawn a new window, you -/// can use the `iced_winit::window::spawn()` [`Command`]. +/// [`Command`] in some of its methods. If you do not intend to perform any +/// background work in your program, the [`Sandbox`] trait offers a simplified +/// interface. /// /// When using an [`Application`] with the `debug` feature enabled, a debug view /// can be toggled by pressing `F12`. /// +/// # Examples +/// See the `examples/multi-window` example to see this multi-window `Application` trait in action. +/// /// ## A simple "Hello, world!" /// /// If you just want to get started, here is a simple [`Application`] that /// says "Hello, world!": /// /// ```no_run -/// use iced::executor; -/// use iced::multi_window::Application; -/// use iced::window; +/// use iced::{executor, window}; /// use iced::{Command, Element, Settings, Theme}; +/// use iced::multi_window::{self, Application}; /// /// pub fn main() -> iced::Result { /// Hello::run(Settings::default()) @@ -32,17 +39,17 @@ pub use iced_native::application::{Appearance, StyleSheet}; /// /// struct Hello; /// -/// impl Application for Hello { +/// impl multi_window::Application for Hello { /// type Executor = executor::Default; +/// type Flags = (); /// type Message = (); /// type Theme = Theme; -/// type Flags = (); /// /// fn new(_flags: ()) -> (Hello, Command<Self::Message>) { /// (Hello, Command::none()) /// } /// -/// fn title(&self, window: window::Id) -> String { +/// fn title(&self, _window: window::Id) -> String { /// String::from("A cool application") /// } /// @@ -50,13 +57,9 @@ pub use iced_native::application::{Appearance, StyleSheet}; /// Command::none() /// } /// -/// fn view(&self, window: window::Id) -> Element<Self::Message> { +/// fn view(&self, _window: window::Id) -> Element<Self::Message> { /// "Hello, world!".into() /// } -/// -/// fn close_requested(&self, window: window::Id) -> Self::Message { -/// () -/// } /// } /// ``` pub trait Application: Sized { @@ -89,10 +92,10 @@ pub trait Application: Sized { /// [`run`]: Self::run fn new(flags: Self::Flags) -> (Self, Command<Self::Message>); - /// Returns the current title of the [`Application`]. + /// Returns the current title of the `window` of the [`Application`]. /// /// This title can be dynamic! The runtime will automatically update the - /// title of your application when necessary. + /// title of your window when necessary. fn title(&self, window: window::Id) -> String; /// Handles a __message__ and updates the state of the [`Application`]. @@ -104,7 +107,15 @@ pub trait Application: Sized { /// Any [`Command`] returned will be executed immediately in the background. fn update(&mut self, message: Self::Message) -> Command<Self::Message>; - /// Returns the current [`Theme`] of the [`Application`]. + /// Returns the widgets to display in the `window` of the [`Application`]. + /// + /// These widgets can produce __messages__ based on user interaction. + fn view( + &self, + window: window::Id, + ) -> Element<'_, Self::Message, crate::Renderer<Self::Theme>>; + + /// Returns the current [`Theme`] of the `window` of the [`Application`]. /// /// [`Theme`]: Self::Theme #[allow(unused_variables)] @@ -112,9 +123,8 @@ pub trait Application: Sized { Self::Theme::default() } - /// Returns the current [`Style`] of the [`Theme`]. + /// Returns the current `Style` of the [`Theme`]. /// - /// [`Style`]: <Self::Theme as StyleSheet>::Style /// [`Theme`]: Self::Theme fn style(&self) -> <Self::Theme as StyleSheet>::Style { <Self::Theme as StyleSheet>::Style::default() @@ -132,14 +142,6 @@ pub trait Application: Sized { Subscription::none() } - /// Returns the widgets to display in the [`Application`]. - /// - /// These widgets can produce __messages__ based on user interaction. - fn view( - &self, - window: window::Id, - ) -> Element<'_, Self::Message, crate::Renderer<Self::Theme>>; - /// Returns the scale factor of the `window` of the [`Application`]. /// /// It can be used to dynamically control the size of the UI at runtime @@ -154,18 +156,7 @@ pub trait Application: Sized { 1.0 } - /// Returns whether the [`Application`] should be terminated. - /// - /// By default, it returns `false`. - fn should_exit(&self) -> bool { - false - } - - /// Returns the `Self::Message` that should be processed when a `window` is requested to - /// be closed. - fn close_requested(&self, window: window::Id) -> Self::Message; - - /// Runs the [`Application`]. + /// Runs the multi-window [`Application`]. /// /// On native platforms, this method will take control of the current thread /// until the [`Application`] exits. @@ -182,30 +173,28 @@ pub trait Application: Sized { let renderer_settings = crate::renderer::Settings { default_font: settings.default_font, default_text_size: settings.default_text_size, - text_multithreading: settings.text_multithreading, antialiasing: if settings.antialiasing { - Some(crate::renderer::settings::Antialiasing::MSAAx4) + Some(crate::graphics::Antialiasing::MSAAx4) } else { None }, - ..crate::renderer::Settings::from_env() + ..crate::renderer::Settings::default() }; - Ok(crate::runtime::multi_window::run::< + Ok(crate::shell::multi_window::run::< Instance<Self>, Self::Executor, - crate::renderer::window::Compositor<Self::Theme>, + crate::renderer::Compositor<Self::Theme>, >(settings.into(), renderer_settings)?) } } struct Instance<A: Application>(A); -impl<A> crate::runtime::multi_window::Application for Instance<A> +impl<A> crate::runtime::multi_window::Program for Instance<A> where A: Application, { - type Flags = A::Flags; type Renderer = crate::Renderer<A::Theme>; type Message = A::Message; @@ -219,6 +208,13 @@ where ) -> Element<'_, Self::Message, Self::Renderer> { self.0.view(window) } +} + +impl<A> crate::shell::multi_window::Application for Instance<A> +where + A: Application, +{ + type Flags = A::Flags; fn new(flags: Self::Flags) -> (Self, Command<A::Message>) { let (app, command) = A::new(flags); @@ -245,12 +241,4 @@ where fn scale_factor(&self, window: window::Id) -> f64 { self.0.scale_factor(window) } - - fn should_exit(&self) -> bool { - self.0.should_exit() - } - - fn close_requested(&self, window: window::Id) -> Self::Message { - self.0.close_requested(window) - } } diff --git a/src/settings.rs b/src/settings.rs index 0dd46584..4ce2d135 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -91,7 +91,7 @@ impl<Flags> From<Settings<Flags>> for iced_winit::Settings<Flags> { fn from(settings: Settings<Flags>) -> iced_winit::Settings<Flags> { iced_winit::Settings { id: settings.id, - window: settings.window.into(), + window: settings.window, flags: settings.flags, exit_on_close_request: settings.exit_on_close_request, } diff --git a/src/window.rs b/src/window.rs index e4601575..9f96da52 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,12 +1,8 @@ //! Configure the window of your application in native platforms. -mod position; -mod settings; pub mod icon; pub use icon::Icon; -pub use position::Position; -pub use settings::{PlatformSpecific, Settings}; pub use crate::core::window::*; pub use crate::runtime::window::*; diff --git a/src/window/icon.rs b/src/window/icon.rs new file mode 100644 index 00000000..0fe010ca --- /dev/null +++ b/src/window/icon.rs @@ -0,0 +1,63 @@ +//! Attach an icon to the window of your application. +pub use crate::core::window::icon::*; + +use crate::core::window::icon; + +use std::io; + +#[cfg(feature = "image")] +use std::path::Path; + +/// Creates an icon from an image file. +/// +/// This will return an error in case the file is missing at run-time. You may prefer [`Self::from_file_data`] instead. +#[cfg(feature = "image")] +pub fn from_file<P: AsRef<Path>>(icon_path: P) -> Result<Icon, Error> { + let icon = image_rs::io::Reader::open(icon_path)?.decode()?.to_rgba8(); + + Ok(icon::from_rgba(icon.to_vec(), icon.width(), icon.height())?) +} + +/// Creates an icon from the content of an image file. +/// +/// This content can be included in your application at compile-time, e.g. using the `include_bytes!` macro. +/// You can pass an explicit file format. Otherwise, the file format will be guessed at runtime. +#[cfg(feature = "image")] +pub fn from_file_data( + data: &[u8], + explicit_format: Option<image_rs::ImageFormat>, +) -> Result<Icon, Error> { + let mut icon = image_rs::io::Reader::new(std::io::Cursor::new(data)); + let icon_with_format = match explicit_format { + Some(format) => { + icon.set_format(format); + icon + } + None => icon.with_guessed_format()?, + }; + + let pixels = icon_with_format.decode()?.to_rgba8(); + + Ok(icon::from_rgba( + pixels.to_vec(), + pixels.width(), + pixels.height(), + )?) +} + +/// An error produced when creating an [`Icon`]. +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// The [`Icon`] is not valid. + #[error("The icon is invalid: {0}")] + InvalidError(#[from] icon::Error), + + /// The underlying OS failed to create the icon. + #[error("The underlying OS failted to create the window icon: {0}")] + OsError(#[from] io::Error), + + /// The `image` crate reported an error. + #[cfg(feature = "image")] + #[error("Unable to create icon from a file: {0}")] + ImageError(#[from] image_rs::error::ImageError), +} |