summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Bingus <shankern@protonmail.com>2023-07-12 19:21:05 -0700
committerLibravatar Bingus <shankern@protonmail.com>2023-07-21 13:53:38 -0700
commitd53ccc857da4d4cda769904342aeb5a82a64f146 (patch)
tree7de16b72e0e054d10380586ba5b79a7181478aa7 /src
parent633f405f3f78bc7f82d2b2061491b0e011137451 (diff)
downloadiced-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.rs96
-rw-r--r--src/settings.rs2
-rw-r--r--src/window.rs4
-rw-r--r--src/window/icon.rs63
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),
+}