summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/gradient/src/main.rs16
-rw-r--r--examples/solar_system/src/main.rs15
-rw-r--r--src/application.rs28
-rw-r--r--src/multi_window.rs256
-rw-r--r--src/multi_window/application.rs246
-rw-r--r--src/sandbox.rs12
-rw-r--r--style/src/application.rs23
-rw-r--r--style/src/lib.rs1
-rw-r--r--style/src/theme.rs45
-rw-r--r--winit/src/application.rs72
-rw-r--r--winit/src/application/state.rs10
-rw-r--r--winit/src/multi_window.rs21
-rw-r--r--winit/src/multi_window/state.rs16
-rw-r--r--winit/src/multi_window/window_manager.rs13
14 files changed, 382 insertions, 392 deletions
diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs
index 3334bde9..6d3ff125 100644
--- a/examples/gradient/src/main.rs
+++ b/examples/gradient/src/main.rs
@@ -1,11 +1,11 @@
use iced::application;
-use iced::theme::{self, Theme};
use iced::widget::{
checkbox, column, container, horizontal_space, row, slider, text, themer,
};
use iced::{gradient, window};
use iced::{
Alignment, Background, Color, Element, Length, Radians, Sandbox, Settings,
+ Theme,
};
pub fn main() -> iced::Result {
@@ -115,16 +115,14 @@ impl Sandbox for Gradient {
.into()
}
- fn style(&self) -> theme::Application {
+ fn style(&self, theme: &Theme) -> application::Appearance {
if self.transparent {
- theme::Application::custom(|theme: &Theme| {
- application::Appearance {
- background_color: Color::TRANSPARENT,
- text_color: theme.palette().text,
- }
- })
+ application::Appearance {
+ background_color: Color::TRANSPARENT,
+ text_color: theme.palette().text,
+ }
} else {
- theme::Application::Default
+ application::default(theme)
}
}
}
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index a58ca683..4cc625da 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -9,7 +9,6 @@
use iced::application;
use iced::executor;
use iced::mouse;
-use iced::theme::{self, Theme};
use iced::widget::canvas;
use iced::widget::canvas::gradient;
use iced::widget::canvas::stroke::{self, Stroke};
@@ -17,7 +16,7 @@ use iced::widget::canvas::Path;
use iced::window;
use iced::{
Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
- Settings, Size, Subscription, Vector,
+ Settings, Size, Subscription, Theme, Vector,
};
use std::time::Instant;
@@ -80,15 +79,11 @@ impl Application for SolarSystem {
Theme::Dark
}
- fn style(&self) -> theme::Application {
- fn dark_background(_theme: &Theme) -> application::Appearance {
- application::Appearance {
- background_color: Color::BLACK,
- text_color: Color::WHITE,
- }
+ fn style(&self, _theme: &Theme) -> application::Appearance {
+ application::Appearance {
+ background_color: Color::BLACK,
+ text_color: Color::WHITE,
}
-
- theme::Application::custom(dark_background)
}
fn subscription(&self) -> Subscription<Message> {
diff --git a/src/application.rs b/src/application.rs
index 3d89c758..3247a97d 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -1,7 +1,9 @@
//! Build interactive cross-platform applications.
use crate::{Command, Element, Executor, Settings, Subscription};
-pub use crate::style::application::{Appearance, StyleSheet};
+use crate::shell::application;
+
+pub use application::{default, Appearance, Style};
/// An interactive cross-platform application.
///
@@ -91,7 +93,10 @@ pub use crate::style::application::{Appearance, StyleSheet};
/// }
/// }
/// ```
-pub trait Application: Sized {
+pub trait Application: Sized
+where
+ Style<Self::Theme>: Default,
+{
/// The [`Executor`] that will run commands and subscriptions.
///
/// The [default executor] can be a good starting point!
@@ -104,7 +109,7 @@ pub trait Application: Sized {
type Message: std::fmt::Debug + Send;
/// The theme of your [`Application`].
- type Theme: Default + StyleSheet;
+ type Theme: Default;
/// The data needed to initialize your [`Application`].
type Flags;
@@ -151,8 +156,8 @@ pub trait Application: Sized {
/// Returns the current `Style` of the [`Theme`].
///
/// [`Theme`]: Self::Theme
- fn style(&self) -> <Self::Theme as StyleSheet>::Style {
- <Self::Theme as StyleSheet>::Style::default()
+ fn style(&self, theme: &Self::Theme) -> Appearance {
+ Style::default().resolve(theme)
}
/// Returns the event [`Subscription`] for the current state of the
@@ -213,11 +218,15 @@ pub trait Application: Sized {
}
}
-struct Instance<A: Application>(A);
+struct Instance<A>(A)
+where
+ A: Application,
+ application::Style<A::Theme>: Default;
impl<A> crate::runtime::Program for Instance<A>
where
A: Application,
+ application::Style<A::Theme>: Default,
{
type Message = A::Message;
type Theme = A::Theme;
@@ -232,9 +241,10 @@ where
}
}
-impl<A> crate::shell::Application for Instance<A>
+impl<A> application::Application for Instance<A>
where
A: Application,
+ application::Style<A::Theme>: Default,
{
type Flags = A::Flags;
@@ -252,8 +262,8 @@ where
self.0.theme()
}
- fn style(&self) -> <A::Theme as StyleSheet>::Style {
- self.0.style()
+ fn style(&self, theme: &A::Theme) -> Appearance {
+ self.0.style(theme)
}
fn subscription(&self) -> Subscription<Self::Message> {
diff --git a/src/multi_window.rs b/src/multi_window.rs
index 5b7a00b4..bd57a746 100644
--- a/src/multi_window.rs
+++ b/src/multi_window.rs
@@ -1,4 +1,256 @@
//! Leverage multi-window support in your application.
-mod application;
+use crate::window;
+use crate::{Command, Element, Executor, Settings, Subscription};
-pub use application::Application;
+pub use crate::application::{default, Appearance, Style};
+
+/// 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. 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, window};
+/// use iced::{Command, Element, Settings, Theme};
+/// use iced::multi_window::{self, Application};
+///
+/// pub fn main() -> iced::Result {
+/// Hello::run(Settings::default())
+/// }
+///
+/// struct Hello;
+///
+/// impl multi_window::Application for Hello {
+/// type Executor = executor::Default;
+/// type Flags = ();
+/// type Message = ();
+/// type Theme = Theme;
+///
+/// fn new(_flags: ()) -> (Hello, Command<Self::Message>) {
+/// (Hello, Command::none())
+/// }
+///
+/// fn title(&self, _window: window::Id) -> String {
+/// String::from("A cool application")
+/// }
+///
+/// fn update(&mut self, _message: Self::Message) -> Command<Self::Message> {
+/// Command::none()
+/// }
+///
+/// fn view(&self, _window: window::Id) -> Element<Self::Message> {
+/// "Hello, world!".into()
+/// }
+/// }
+/// ```
+///
+/// [`Sandbox`]: crate::Sandbox
+pub trait Application: Sized
+where
+ Style<Self::Theme>: Default,
+{
+ /// The [`Executor`] that will run commands and subscriptions.
+ ///
+ /// The [default executor] can be a good starting point!
+ ///
+ /// [`Executor`]: Self::Executor
+ /// [default executor]: crate::executor::Default
+ type Executor: Executor;
+
+ /// The type of __messages__ your [`Application`] will produce.
+ type Message: std::fmt::Debug + Send;
+
+ /// The theme of your [`Application`].
+ type Theme: Default;
+
+ /// The data needed to initialize your [`Application`].
+ type Flags;
+
+ /// Initializes the [`Application`] with the flags provided to
+ /// [`run`] as part of the [`Settings`].
+ ///
+ /// Here is where you should return the initial state of your app.
+ ///
+ /// Additionally, you can return a [`Command`] if you need to perform some
+ /// async action in the background on startup. This is useful if you want to
+ /// load state from a file, perform an initial HTTP request, etc.
+ ///
+ /// [`run`]: Self::run
+ fn new(flags: Self::Flags) -> (Self, Command<Self::Message>);
+
+ /// Returns the current title of the `window` of the [`Application`].
+ ///
+ /// This title can be dynamic! The runtime will automatically update the
+ /// title of your window when necessary.
+ fn title(&self, window: window::Id) -> String;
+
+ /// Handles a __message__ and updates the state of the [`Application`].
+ ///
+ /// This is where you define your __update logic__. All the __messages__,
+ /// produced by either user interactions or commands, will be handled by
+ /// this method.
+ ///
+ /// Any [`Command`] returned will be executed immediately in the background.
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
+
+ /// 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, Self::Theme, crate::Renderer>;
+
+ /// Returns the current [`Theme`] of the `window` of the [`Application`].
+ ///
+ /// [`Theme`]: Self::Theme
+ #[allow(unused_variables)]
+ fn theme(&self, window: window::Id) -> Self::Theme {
+ Self::Theme::default()
+ }
+
+ /// Returns the current `Style` of the [`Theme`].
+ ///
+ /// [`Theme`]: Self::Theme
+ fn style(&self, theme: &Self::Theme) -> Appearance {
+ Style::default().resolve(theme)
+ }
+
+ /// Returns the event [`Subscription`] for the current state of the
+ /// application.
+ ///
+ /// A [`Subscription`] will be kept alive as long as you keep returning it,
+ /// and the __messages__ produced will be handled by
+ /// [`update`](#tymethod.update).
+ ///
+ /// By default, this method returns an empty [`Subscription`].
+ fn subscription(&self) -> Subscription<Self::Message> {
+ Subscription::none()
+ }
+
+ /// Returns the scale factor of the `window` of the [`Application`].
+ ///
+ /// It can be used to dynamically control the size of the UI at runtime
+ /// (i.e. zooming).
+ ///
+ /// For instance, a scale factor of `2.0` will make widgets twice as big,
+ /// while a scale factor of `0.5` will shrink them to half their size.
+ ///
+ /// By default, it returns `1.0`.
+ #[allow(unused_variables)]
+ fn scale_factor(&self, window: window::Id) -> f64 {
+ 1.0
+ }
+
+ /// Runs the multi-window [`Application`].
+ ///
+ /// On native platforms, this method will take control of the current thread
+ /// until the [`Application`] exits.
+ ///
+ /// On the web platform, this method __will NOT return__ unless there is an
+ /// [`Error`] during startup.
+ ///
+ /// [`Error`]: crate::Error
+ fn run(settings: Settings<Self::Flags>) -> crate::Result
+ where
+ Self: 'static,
+ {
+ #[allow(clippy::needless_update)]
+ let renderer_settings = crate::renderer::Settings {
+ default_font: settings.default_font,
+ default_text_size: settings.default_text_size,
+ antialiasing: if settings.antialiasing {
+ Some(crate::graphics::Antialiasing::MSAAx4)
+ } else {
+ None
+ },
+ ..crate::renderer::Settings::default()
+ };
+
+ Ok(crate::shell::multi_window::run::<
+ Instance<Self>,
+ Self::Executor,
+ crate::renderer::Compositor,
+ >(settings.into(), renderer_settings)?)
+ }
+}
+
+struct Instance<A>(A)
+where
+ A: Application,
+ Style<A::Theme>: Default;
+
+impl<A> crate::runtime::multi_window::Program for Instance<A>
+where
+ A: Application,
+ Style<A::Theme>: Default,
+{
+ type Message = A::Message;
+ type Theme = A::Theme;
+ type Renderer = crate::Renderer;
+
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
+ self.0.update(message)
+ }
+
+ fn view(
+ &self,
+ window: window::Id,
+ ) -> Element<'_, Self::Message, Self::Theme, Self::Renderer> {
+ self.0.view(window)
+ }
+}
+
+impl<A> crate::shell::multi_window::Application for Instance<A>
+where
+ A: Application,
+ Style<A::Theme>: Default,
+{
+ type Flags = A::Flags;
+
+ fn new(flags: Self::Flags) -> (Self, Command<A::Message>) {
+ let (app, command) = A::new(flags);
+
+ (Instance(app), command)
+ }
+
+ fn title(&self, window: window::Id) -> String {
+ self.0.title(window)
+ }
+
+ fn theme(&self, window: window::Id) -> A::Theme {
+ self.0.theme(window)
+ }
+
+ fn style(&self, theme: &Self::Theme) -> Appearance {
+ self.0.style(theme)
+ }
+
+ fn subscription(&self) -> Subscription<Self::Message> {
+ self.0.subscription()
+ }
+
+ fn scale_factor(&self, window: window::Id) -> f64 {
+ self.0.scale_factor(window)
+ }
+}
diff --git a/src/multi_window/application.rs b/src/multi_window/application.rs
deleted file mode 100644
index ac625281..00000000
--- a/src/multi_window/application.rs
+++ /dev/null
@@ -1,246 +0,0 @@
-use crate::style::application::StyleSheet;
-use crate::window;
-use crate::{Command, Element, Executor, Settings, Subscription};
-
-/// 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. 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, window};
-/// use iced::{Command, Element, Settings, Theme};
-/// use iced::multi_window::{self, Application};
-///
-/// pub fn main() -> iced::Result {
-/// Hello::run(Settings::default())
-/// }
-///
-/// struct Hello;
-///
-/// impl multi_window::Application for Hello {
-/// type Executor = executor::Default;
-/// type Flags = ();
-/// type Message = ();
-/// type Theme = Theme;
-///
-/// fn new(_flags: ()) -> (Hello, Command<Self::Message>) {
-/// (Hello, Command::none())
-/// }
-///
-/// fn title(&self, _window: window::Id) -> String {
-/// String::from("A cool application")
-/// }
-///
-/// fn update(&mut self, _message: Self::Message) -> Command<Self::Message> {
-/// Command::none()
-/// }
-///
-/// fn view(&self, _window: window::Id) -> Element<Self::Message> {
-/// "Hello, world!".into()
-/// }
-/// }
-/// ```
-///
-/// [`Sandbox`]: crate::Sandbox
-pub trait Application: Sized {
- /// The [`Executor`] that will run commands and subscriptions.
- ///
- /// The [default executor] can be a good starting point!
- ///
- /// [`Executor`]: Self::Executor
- /// [default executor]: crate::executor::Default
- type Executor: Executor;
-
- /// The type of __messages__ your [`Application`] will produce.
- type Message: std::fmt::Debug + Send;
-
- /// The theme of your [`Application`].
- type Theme: Default + StyleSheet;
-
- /// The data needed to initialize your [`Application`].
- type Flags;
-
- /// Initializes the [`Application`] with the flags provided to
- /// [`run`] as part of the [`Settings`].
- ///
- /// Here is where you should return the initial state of your app.
- ///
- /// Additionally, you can return a [`Command`] if you need to perform some
- /// async action in the background on startup. This is useful if you want to
- /// load state from a file, perform an initial HTTP request, etc.
- ///
- /// [`run`]: Self::run
- fn new(flags: Self::Flags) -> (Self, Command<Self::Message>);
-
- /// Returns the current title of the `window` of the [`Application`].
- ///
- /// This title can be dynamic! The runtime will automatically update the
- /// title of your window when necessary.
- fn title(&self, window: window::Id) -> String;
-
- /// Handles a __message__ and updates the state of the [`Application`].
- ///
- /// This is where you define your __update logic__. All the __messages__,
- /// produced by either user interactions or commands, will be handled by
- /// this method.
- ///
- /// Any [`Command`] returned will be executed immediately in the background.
- fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
-
- /// 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, Self::Theme, crate::Renderer>;
-
- /// Returns the current [`Theme`] of the `window` of the [`Application`].
- ///
- /// [`Theme`]: Self::Theme
- #[allow(unused_variables)]
- fn theme(&self, window: window::Id) -> Self::Theme {
- Self::Theme::default()
- }
-
- /// Returns the current `Style` of the [`Theme`].
- ///
- /// [`Theme`]: Self::Theme
- fn style(&self) -> <Self::Theme as StyleSheet>::Style {
- <Self::Theme as StyleSheet>::Style::default()
- }
-
- /// Returns the event [`Subscription`] for the current state of the
- /// application.
- ///
- /// A [`Subscription`] will be kept alive as long as you keep returning it,
- /// and the __messages__ produced will be handled by
- /// [`update`](#tymethod.update).
- ///
- /// By default, this method returns an empty [`Subscription`].
- fn subscription(&self) -> Subscription<Self::Message> {
- Subscription::none()
- }
-
- /// Returns the scale factor of the `window` of the [`Application`].
- ///
- /// It can be used to dynamically control the size of the UI at runtime
- /// (i.e. zooming).
- ///
- /// For instance, a scale factor of `2.0` will make widgets twice as big,
- /// while a scale factor of `0.5` will shrink them to half their size.
- ///
- /// By default, it returns `1.0`.
- #[allow(unused_variables)]
- fn scale_factor(&self, window: window::Id) -> f64 {
- 1.0
- }
-
- /// Runs the multi-window [`Application`].
- ///
- /// On native platforms, this method will take control of the current thread
- /// until the [`Application`] exits.
- ///
- /// On the web platform, this method __will NOT return__ unless there is an
- /// [`Error`] during startup.
- ///
- /// [`Error`]: crate::Error
- fn run(settings: Settings<Self::Flags>) -> crate::Result
- where
- Self: 'static,
- {
- #[allow(clippy::needless_update)]
- let renderer_settings = crate::renderer::Settings {
- default_font: settings.default_font,
- default_text_size: settings.default_text_size,
- antialiasing: if settings.antialiasing {
- Some(crate::graphics::Antialiasing::MSAAx4)
- } else {
- None
- },
- ..crate::renderer::Settings::default()
- };
-
- Ok(crate::shell::multi_window::run::<
- Instance<Self>,
- Self::Executor,
- crate::renderer::Compositor,
- >(settings.into(), renderer_settings)?)
- }
-}
-
-struct Instance<A: Application>(A);
-
-impl<A> crate::runtime::multi_window::Program for Instance<A>
-where
- A: Application,
-{
- type Message = A::Message;
- type Theme = A::Theme;
- type Renderer = crate::Renderer;
-
- fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
- self.0.update(message)
- }
-
- fn view(
- &self,
- window: window::Id,
- ) -> Element<'_, Self::Message, Self::Theme, 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);
-
- (Instance(app), command)
- }
-
- fn title(&self, window: window::Id) -> String {
- self.0.title(window)
- }
-
- fn theme(&self, window: window::Id) -> A::Theme {
- self.0.theme(window)
- }
-
- fn style(&self) -> <A::Theme as StyleSheet>::Style {
- self.0.style()
- }
-
- fn subscription(&self) -> Subscription<Self::Message> {
- self.0.subscription()
- }
-
- fn scale_factor(&self, window: window::Id) -> f64 {
- self.0.scale_factor(window)
- }
-}
diff --git a/src/sandbox.rs b/src/sandbox.rs
index 28461929..815652ae 100644
--- a/src/sandbox.rs
+++ b/src/sandbox.rs
@@ -1,5 +1,5 @@
-use crate::theme::{self, Theme};
-use crate::{Application, Command, Element, Error, Settings, Subscription};
+use crate::application::{self, Application};
+use crate::{Command, Element, Error, Settings, Subscription, Theme};
/// A sandboxed [`Application`].
///
@@ -123,8 +123,8 @@ pub trait Sandbox {
/// Returns the current style variant of [`theme::Application`].
///
/// By default, it returns [`theme::Application::default`].
- fn style(&self) -> theme::Application {
- theme::Application::default()
+ fn style(&self, theme: &Theme) -> application::Appearance {
+ crate::shell::application::default(theme)
}
/// Returns the scale factor of the [`Sandbox`].
@@ -185,8 +185,8 @@ where
T::theme(self)
}
- fn style(&self) -> theme::Application {
- T::style(self)
+ fn style(&self, theme: &Theme) -> application::Appearance {
+ T::style(self, theme)
}
fn subscription(&self) -> Subscription<T::Message> {
diff --git a/style/src/application.rs b/style/src/application.rs
deleted file mode 100644
index e9a1f4ff..00000000
--- a/style/src/application.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//! Change the appearance of an application.
-use iced_core::Color;
-
-/// A set of rules that dictate the style of an application.
-pub trait StyleSheet {
- /// The supported style of the [`StyleSheet`].
- type Style: Default;
-
- /// Returns the [`Appearance`] of the application for the provided [`Style`].
- ///
- /// [`Style`]: Self::Style
- fn appearance(&self, style: &Self::Style) -> Appearance;
-}
-
-/// The appearance of an application.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub struct Appearance {
- /// The background [`Color`] of the application.
- pub background_color: Color,
-
- /// The default text [`Color`] of the application.
- pub text_color: Color,
-}
diff --git a/style/src/lib.rs b/style/src/lib.rs
index 1aea2d80..bc0e37e9 100644
--- a/style/src/lib.rs
+++ b/style/src/lib.rs
@@ -16,7 +16,6 @@
)]
pub use iced_core as core;
-pub mod application;
pub mod theme;
pub use theme::Theme;
diff --git a/style/src/theme.rs b/style/src/theme.rs
index 41e76d99..21ba2a37 100644
--- a/style/src/theme.rs
+++ b/style/src/theme.rs
@@ -3,8 +3,6 @@ pub mod palette;
pub use palette::Palette;
-use crate::application;
-
use std::fmt;
use std::sync::Arc;
@@ -221,46 +219,3 @@ impl fmt::Display for Custom {
write!(f, "{}", self.name)
}
}
-
-/// The style of an application.
-#[derive(Default)]
-pub enum Application {
- /// The default style.
- #[default]
- Default,
- /// A custom style.
- Custom(Box<dyn application::StyleSheet<Style = Theme>>),
-}
-
-impl Application {
- /// Creates a custom [`Application`] style.
- pub fn custom(
- custom: impl application::StyleSheet<Style = Theme> + 'static,
- ) -> Self {
- Self::Custom(Box::new(custom))
- }
-}
-
-impl application::StyleSheet for Theme {
- type Style = Application;
-
- fn appearance(&self, style: &Self::Style) -> application::Appearance {
- let palette = self.extended_palette();
-
- match style {
- Application::Default => application::Appearance {
- background_color: palette.background.base.color,
- text_color: palette.background.base.text,
- },
- Application::Custom(custom) => custom.appearance(self),
- }
- }
-}
-
-impl<T: Fn(&Theme) -> application::Appearance> application::StyleSheet for T {
- type Style = Theme;
-
- fn appearance(&self, style: &Self::Style) -> application::Appearance {
- (self)(style)
- }
-}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 05a4f070..fbca6ee4 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -10,7 +10,7 @@ use crate::core::renderer;
use crate::core::time::Instant;
use crate::core::widget::operation;
use crate::core::window;
-use crate::core::{Event, Point, Size};
+use crate::core::{Color, Event, Point, Size};
use crate::futures::futures;
use crate::futures::{Executor, Runtime, Subscription};
use crate::graphics::compositor::{self, Compositor};
@@ -18,7 +18,7 @@ use crate::runtime::clipboard;
use crate::runtime::program::Program;
use crate::runtime::user_interface::{self, UserInterface};
use crate::runtime::{Command, Debug};
-use crate::style::application::{Appearance, StyleSheet};
+use crate::style::Theme;
use crate::{Clipboard, Error, Proxy, Settings};
use futures::channel::mpsc;
@@ -39,7 +39,7 @@ use std::sync::Arc;
/// can be toggled by pressing `F12`.
pub trait Application: Program
where
- Self::Theme: StyleSheet,
+ Style<Self::Theme>: Default,
{
/// The data needed to initialize your [`Application`].
type Flags;
@@ -64,8 +64,8 @@ where
fn theme(&self) -> Self::Theme;
/// Returns the `Style` variation of the `Theme`.
- fn style(&self) -> <Self::Theme as StyleSheet>::Style {
- Default::default()
+ fn style(&self, theme: &Self::Theme) -> Appearance {
+ Style::default().resolve(theme)
}
/// Returns the event `Subscription` for the current state of the
@@ -95,6 +95,58 @@ where
}
}
+/// The appearance of an application.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct Appearance {
+ /// The background [`Color`] of the application.
+ pub background_color: Color,
+
+ /// The default text [`Color`] of the application.
+ pub text_color: Color,
+}
+
+/// The style of an [`Application`].
+#[derive(Debug, PartialEq, Eq)]
+pub struct Style<Theme>(pub fn(&Theme) -> Appearance);
+
+impl<Theme> Style<Theme> {
+ /// Resolves the [`Style`] with the given `Theme` to produce
+ /// an [`Appearance`].
+ pub fn resolve(self, theme: &Theme) -> Appearance {
+ (self.0)(theme)
+ }
+}
+
+impl<Theme> Clone for Style<Theme> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<Theme> Copy for Style<Theme> {}
+
+impl<Theme> From<fn(&Theme) -> Appearance> for Style<Theme> {
+ fn from(f: fn(&Theme) -> Appearance) -> Self {
+ Style(f)
+ }
+}
+
+impl Default for Style<Theme> {
+ fn default() -> Self {
+ Style(default)
+ }
+}
+
+/// The default style of an [`Application`].
+pub fn default(theme: &Theme) -> Appearance {
+ let palette = theme.extended_palette();
+
+ Appearance {
+ background_color: palette.background.base.color,
+ text_color: palette.background.base.text,
+ }
+}
+
/// Runs an [`Application`] with an executor, compositor, and the provided
/// settings.
pub fn run<A, E, C>(
@@ -105,7 +157,7 @@ where
A: Application + 'static,
E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use futures::task;
use futures::Future;
@@ -289,7 +341,7 @@ async fn run_instance<A, E, C>(
A: Application + 'static,
E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use futures::stream::StreamExt;
use winit::event;
@@ -612,7 +664,7 @@ pub fn build_user_interface<'a, A: Application>(
debug: &mut Debug,
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
where
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
debug.view_started();
let view = application.view();
@@ -643,7 +695,7 @@ pub fn update<A: Application, C, E: Executor>(
window: &winit::window::Window,
) where
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
for message in messages.drain(..) {
debug.log_message(&message);
@@ -694,7 +746,7 @@ pub fn run_command<A, C, E>(
A: Application,
E: Executor,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use crate::runtime::command;
use crate::runtime::system;
diff --git a/winit/src/application/state.rs b/winit/src/application/state.rs
index c17a3bcc..b3bdb3a3 100644
--- a/winit/src/application/state.rs
+++ b/winit/src/application/state.rs
@@ -1,4 +1,4 @@
-use crate::application::{self, StyleSheet as _};
+use crate::application;
use crate::conversion;
use crate::core::mouse;
use crate::core::{Color, Size};
@@ -14,7 +14,7 @@ use winit::window::Window;
#[allow(missing_debug_implementations)]
pub struct State<A: Application>
where
- A::Theme: application::StyleSheet,
+ application::Style<A::Theme>: Default,
{
title: String,
scale_factor: f64,
@@ -29,14 +29,14 @@ where
impl<A: Application> State<A>
where
- A::Theme: application::StyleSheet,
+ application::Style<A::Theme>: Default,
{
/// Creates a new [`State`] for the provided [`Application`] and window.
pub fn new(application: &A, window: &Window) -> Self {
let title = application.title();
let scale_factor = application.scale_factor();
let theme = application.theme();
- let appearance = theme.appearance(&application.style());
+ let appearance = application.style(&theme);
let viewport = {
let physical_size = window.inner_size();
@@ -216,6 +216,6 @@ where
// Update theme and appearance
self.theme = application.theme();
- self.appearance = self.theme.appearance(&application.style());
+ self.appearance = application.style(&self.theme);
}
}
diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs
index 03066d6c..19951ed3 100644
--- a/winit/src/multi_window.rs
+++ b/winit/src/multi_window.rs
@@ -20,9 +20,10 @@ use crate::runtime::command::{self, Command};
use crate::runtime::multi_window::Program;
use crate::runtime::user_interface::{self, UserInterface};
use crate::runtime::Debug;
-use crate::style::application::StyleSheet;
use crate::{Clipboard, Error, Proxy, Settings};
+pub use crate::application::{default, Appearance, Style};
+
use std::collections::HashMap;
use std::mem::ManuallyDrop;
use std::sync::Arc;
@@ -41,7 +42,7 @@ use std::time::Instant;
/// can be toggled by pressing `F12`.
pub trait Application: Program
where
- Self::Theme: StyleSheet,
+ Style<Self::Theme>: Default,
{
/// The data needed to initialize your [`Application`].
type Flags;
@@ -66,8 +67,8 @@ where
fn theme(&self, window: window::Id) -> Self::Theme;
/// Returns the `Style` variation of the `Theme`.
- fn style(&self) -> <Self::Theme as StyleSheet>::Style {
- Default::default()
+ fn style(&self, theme: &Self::Theme) -> Appearance {
+ Style::default().resolve(theme)
}
/// Returns the event `Subscription` for the current state of the
@@ -108,7 +109,7 @@ where
A: Application + 'static,
E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use winit::event_loop::EventLoopBuilder;
@@ -349,7 +350,7 @@ async fn run_instance<A, E, C>(
A: Application + 'static,
E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use winit::event;
use winit::event_loop::ControlFlow;
@@ -819,7 +820,7 @@ fn build_user_interface<'a, A: Application>(
id: window::Id,
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
where
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
debug.view_started();
let view = application.view(id);
@@ -847,7 +848,7 @@ fn update<A: Application, C, E: Executor>(
ui_caches: &mut HashMap<window::Id, user_interface::Cache>,
) where
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
for message in messages.drain(..) {
debug.log_message(&message);
@@ -890,7 +891,7 @@ fn run_command<A, C, E>(
A: Application,
E: Executor,
C: Compositor<Renderer = A::Renderer> + 'static,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
use crate::runtime::clipboard;
use crate::runtime::system;
@@ -1216,8 +1217,8 @@ pub fn build_user_interfaces<'a, A: Application, C: Compositor>(
mut cached_user_interfaces: HashMap<window::Id, user_interface::Cache>,
) -> HashMap<window::Id, UserInterface<'a, A::Message, A::Theme, A::Renderer>>
where
- A::Theme: StyleSheet,
C: Compositor<Renderer = A::Renderer>,
+ Style<A::Theme>: Default,
{
cached_user_interfaces
.drain()
diff --git a/winit/src/multi_window/state.rs b/winit/src/multi_window/state.rs
index 2e97a13d..8a332176 100644
--- a/winit/src/multi_window/state.rs
+++ b/winit/src/multi_window/state.rs
@@ -2,18 +2,16 @@ use crate::conversion;
use crate::core::{mouse, window};
use crate::core::{Color, Size};
use crate::graphics::Viewport;
-use crate::multi_window::Application;
-use crate::style::application;
+use crate::multi_window::{self, Application};
use std::fmt::{Debug, Formatter};
-use iced_style::application::StyleSheet;
use winit::event::{Touch, WindowEvent};
use winit::window::Window;
/// The state of a multi-windowed [`Application`].
pub struct State<A: Application>
where
- A::Theme: application::StyleSheet,
+ multi_window::Style<A::Theme>: Default,
{
title: String,
scale_factor: f64,
@@ -22,12 +20,12 @@ where
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::keyboard::ModifiersState,
theme: A::Theme,
- appearance: application::Appearance,
+ appearance: multi_window::Appearance,
}
impl<A: Application> Debug for State<A>
where
- A::Theme: application::StyleSheet,
+ multi_window::Style<A::Theme>: Default,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("multi_window::State")
@@ -43,7 +41,7 @@ where
impl<A: Application> State<A>
where
- A::Theme: application::StyleSheet,
+ multi_window::Style<A::Theme>: Default,
{
/// Creates a new [`State`] for the provided [`Application`]'s `window`.
pub fn new(
@@ -54,7 +52,7 @@ where
let title = application.title(window_id);
let scale_factor = application.scale_factor(window_id);
let theme = application.theme(window_id);
- let appearance = theme.appearance(&application.style());
+ let appearance = application.style(&theme);
let viewport = {
let physical_size = window.inner_size();
@@ -236,6 +234,6 @@ where
// Update theme and appearance
self.theme = application.theme(window_id);
- self.appearance = self.theme.appearance(&application.style());
+ self.appearance = application.style(&self.theme);
}
}
diff --git a/winit/src/multi_window/window_manager.rs b/winit/src/multi_window/window_manager.rs
index 23f3c0ba..2800e923 100644
--- a/winit/src/multi_window/window_manager.rs
+++ b/winit/src/multi_window/window_manager.rs
@@ -2,8 +2,7 @@ use crate::core::mouse;
use crate::core::window::Id;
use crate::core::{Point, Size};
use crate::graphics::Compositor;
-use crate::multi_window::{Application, State};
-use crate::style::application::StyleSheet;
+use crate::multi_window::{Application, State, Style};
use std::collections::BTreeMap;
use std::sync::Arc;
@@ -12,8 +11,8 @@ use winit::monitor::MonitorHandle;
#[allow(missing_debug_implementations)]
pub struct WindowManager<A: Application, C: Compositor>
where
- A::Theme: StyleSheet,
C: Compositor<Renderer = A::Renderer>,
+ Style<A::Theme>: Default,
{
aliases: BTreeMap<winit::window::WindowId, Id>,
entries: BTreeMap<Id, Window<A, C>>,
@@ -23,7 +22,7 @@ impl<A, C> WindowManager<A, C>
where
A: Application,
C: Compositor<Renderer = A::Renderer>,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
pub fn new() -> Self {
Self {
@@ -109,7 +108,7 @@ impl<A, C> Default for WindowManager<A, C>
where
A: Application,
C: Compositor<Renderer = A::Renderer>,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
fn default() -> Self {
Self::new()
@@ -121,7 +120,7 @@ pub struct Window<A, C>
where
A: Application,
C: Compositor<Renderer = A::Renderer>,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
pub raw: Arc<winit::window::Window>,
pub state: State<A>,
@@ -136,7 +135,7 @@ impl<A, C> Window<A, C>
where
A: Application,
C: Compositor<Renderer = A::Renderer>,
- A::Theme: StyleSheet,
+ Style<A::Theme>: Default,
{
pub fn position(&self) -> Option<Point> {
self.raw