Simplify theming for Application
This commit is contained in:
parent
34e7c6593a
commit
7c4bf70023
14 changed files with 382 additions and 392 deletions
|
|
@ -1,11 +1,11 @@
|
||||||
use iced::application;
|
use iced::application;
|
||||||
use iced::theme::{self, Theme};
|
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
checkbox, column, container, horizontal_space, row, slider, text, themer,
|
checkbox, column, container, horizontal_space, row, slider, text, themer,
|
||||||
};
|
};
|
||||||
use iced::{gradient, window};
|
use iced::{gradient, window};
|
||||||
use iced::{
|
use iced::{
|
||||||
Alignment, Background, Color, Element, Length, Radians, Sandbox, Settings,
|
Alignment, Background, Color, Element, Length, Radians, Sandbox, Settings,
|
||||||
|
Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
|
|
@ -115,16 +115,14 @@ impl Sandbox for Gradient {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self) -> theme::Application {
|
fn style(&self, theme: &Theme) -> application::Appearance {
|
||||||
if self.transparent {
|
if self.transparent {
|
||||||
theme::Application::custom(|theme: &Theme| {
|
|
||||||
application::Appearance {
|
application::Appearance {
|
||||||
background_color: Color::TRANSPARENT,
|
background_color: Color::TRANSPARENT,
|
||||||
text_color: theme.palette().text,
|
text_color: theme.palette().text,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
theme::Application::Default
|
application::default(theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
use iced::application;
|
use iced::application;
|
||||||
use iced::executor;
|
use iced::executor;
|
||||||
use iced::mouse;
|
use iced::mouse;
|
||||||
use iced::theme::{self, Theme};
|
|
||||||
use iced::widget::canvas;
|
use iced::widget::canvas;
|
||||||
use iced::widget::canvas::gradient;
|
use iced::widget::canvas::gradient;
|
||||||
use iced::widget::canvas::stroke::{self, Stroke};
|
use iced::widget::canvas::stroke::{self, Stroke};
|
||||||
|
|
@ -17,7 +16,7 @@ use iced::widget::canvas::Path;
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{
|
use iced::{
|
||||||
Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
|
Application, Color, Command, Element, Length, Point, Rectangle, Renderer,
|
||||||
Settings, Size, Subscription, Vector,
|
Settings, Size, Subscription, Theme, Vector,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
@ -80,17 +79,13 @@ impl Application for SolarSystem {
|
||||||
Theme::Dark
|
Theme::Dark
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self) -> theme::Application {
|
fn style(&self, _theme: &Theme) -> application::Appearance {
|
||||||
fn dark_background(_theme: &Theme) -> application::Appearance {
|
|
||||||
application::Appearance {
|
application::Appearance {
|
||||||
background_color: Color::BLACK,
|
background_color: Color::BLACK,
|
||||||
text_color: Color::WHITE,
|
text_color: Color::WHITE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
theme::Application::custom(dark_background)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
window::frames().map(Message::Tick)
|
window::frames().map(Message::Tick)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
//! Build interactive cross-platform applications.
|
//! Build interactive cross-platform applications.
|
||||||
use crate::{Command, Element, Executor, Settings, Subscription};
|
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.
|
/// 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 [`Executor`] that will run commands and subscriptions.
|
||||||
///
|
///
|
||||||
/// The [default executor] can be a good starting point!
|
/// The [default executor] can be a good starting point!
|
||||||
|
|
@ -104,7 +109,7 @@ pub trait Application: Sized {
|
||||||
type Message: std::fmt::Debug + Send;
|
type Message: std::fmt::Debug + Send;
|
||||||
|
|
||||||
/// The theme of your [`Application`].
|
/// The theme of your [`Application`].
|
||||||
type Theme: Default + StyleSheet;
|
type Theme: Default;
|
||||||
|
|
||||||
/// The data needed to initialize your [`Application`].
|
/// The data needed to initialize your [`Application`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
@ -151,8 +156,8 @@ pub trait Application: Sized {
|
||||||
/// Returns the current `Style` of the [`Theme`].
|
/// Returns the current `Style` of the [`Theme`].
|
||||||
///
|
///
|
||||||
/// [`Theme`]: Self::Theme
|
/// [`Theme`]: Self::Theme
|
||||||
fn style(&self) -> <Self::Theme as StyleSheet>::Style {
|
fn style(&self, theme: &Self::Theme) -> Appearance {
|
||||||
<Self::Theme as StyleSheet>::Style::default()
|
Style::default().resolve(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the event [`Subscription`] for the current state of the
|
/// 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>
|
impl<A> crate::runtime::Program for Instance<A>
|
||||||
where
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
|
application::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
type Message = A::Message;
|
type Message = A::Message;
|
||||||
type Theme = A::Theme;
|
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
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
|
application::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
type Flags = A::Flags;
|
type Flags = A::Flags;
|
||||||
|
|
||||||
|
|
@ -252,8 +262,8 @@ where
|
||||||
self.0.theme()
|
self.0.theme()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self) -> <A::Theme as StyleSheet>::Style {
|
fn style(&self, theme: &A::Theme) -> Appearance {
|
||||||
self.0.style()
|
self.0.style(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
fn subscription(&self) -> Subscription<Self::Message> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,256 @@
|
||||||
//! Leverage multi-window support in your application.
|
//! 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::theme::{self, Theme};
|
use crate::application::{self, Application};
|
||||||
use crate::{Application, Command, Element, Error, Settings, Subscription};
|
use crate::{Command, Element, Error, Settings, Subscription, Theme};
|
||||||
|
|
||||||
/// A sandboxed [`Application`].
|
/// A sandboxed [`Application`].
|
||||||
///
|
///
|
||||||
|
|
@ -123,8 +123,8 @@ pub trait Sandbox {
|
||||||
/// Returns the current style variant of [`theme::Application`].
|
/// Returns the current style variant of [`theme::Application`].
|
||||||
///
|
///
|
||||||
/// By default, it returns [`theme::Application::default`].
|
/// By default, it returns [`theme::Application::default`].
|
||||||
fn style(&self) -> theme::Application {
|
fn style(&self, theme: &Theme) -> application::Appearance {
|
||||||
theme::Application::default()
|
crate::shell::application::default(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the scale factor of the [`Sandbox`].
|
/// Returns the scale factor of the [`Sandbox`].
|
||||||
|
|
@ -185,8 +185,8 @@ where
|
||||||
T::theme(self)
|
T::theme(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self) -> theme::Application {
|
fn style(&self, theme: &Theme) -> application::Appearance {
|
||||||
T::style(self)
|
T::style(self, theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<T::Message> {
|
fn subscription(&self) -> Subscription<T::Message> {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
}
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
)]
|
)]
|
||||||
pub use iced_core as core;
|
pub use iced_core as core;
|
||||||
|
|
||||||
pub mod application;
|
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
pub use theme::Theme;
|
pub use theme::Theme;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ pub mod palette;
|
||||||
|
|
||||||
pub use palette::Palette;
|
pub use palette::Palette;
|
||||||
|
|
||||||
use crate::application;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -221,46 +219,3 @@ impl fmt::Display for Custom {
|
||||||
write!(f, "{}", self.name)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::core::renderer;
|
||||||
use crate::core::time::Instant;
|
use crate::core::time::Instant;
|
||||||
use crate::core::widget::operation;
|
use crate::core::widget::operation;
|
||||||
use crate::core::window;
|
use crate::core::window;
|
||||||
use crate::core::{Event, Point, Size};
|
use crate::core::{Color, Event, Point, Size};
|
||||||
use crate::futures::futures;
|
use crate::futures::futures;
|
||||||
use crate::futures::{Executor, Runtime, Subscription};
|
use crate::futures::{Executor, Runtime, Subscription};
|
||||||
use crate::graphics::compositor::{self, Compositor};
|
use crate::graphics::compositor::{self, Compositor};
|
||||||
|
|
@ -18,7 +18,7 @@ use crate::runtime::clipboard;
|
||||||
use crate::runtime::program::Program;
|
use crate::runtime::program::Program;
|
||||||
use crate::runtime::user_interface::{self, UserInterface};
|
use crate::runtime::user_interface::{self, UserInterface};
|
||||||
use crate::runtime::{Command, Debug};
|
use crate::runtime::{Command, Debug};
|
||||||
use crate::style::application::{Appearance, StyleSheet};
|
use crate::style::Theme;
|
||||||
use crate::{Clipboard, Error, Proxy, Settings};
|
use crate::{Clipboard, Error, Proxy, Settings};
|
||||||
|
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
|
|
@ -39,7 +39,7 @@ use std::sync::Arc;
|
||||||
/// can be toggled by pressing `F12`.
|
/// can be toggled by pressing `F12`.
|
||||||
pub trait Application: Program
|
pub trait Application: Program
|
||||||
where
|
where
|
||||||
Self::Theme: StyleSheet,
|
Style<Self::Theme>: Default,
|
||||||
{
|
{
|
||||||
/// The data needed to initialize your [`Application`].
|
/// The data needed to initialize your [`Application`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
@ -64,8 +64,8 @@ where
|
||||||
fn theme(&self) -> Self::Theme;
|
fn theme(&self) -> Self::Theme;
|
||||||
|
|
||||||
/// Returns the `Style` variation of the `Theme`.
|
/// Returns the `Style` variation of the `Theme`.
|
||||||
fn style(&self) -> <Self::Theme as StyleSheet>::Style {
|
fn style(&self, theme: &Self::Theme) -> Appearance {
|
||||||
Default::default()
|
Style::default().resolve(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the event `Subscription` for the current state of the
|
/// 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
|
/// Runs an [`Application`] with an executor, compositor, and the provided
|
||||||
/// settings.
|
/// settings.
|
||||||
pub fn run<A, E, C>(
|
pub fn run<A, E, C>(
|
||||||
|
|
@ -105,7 +157,7 @@ where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use futures::task;
|
use futures::task;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
|
@ -289,7 +341,7 @@ async fn run_instance<A, E, C>(
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use winit::event;
|
use winit::event;
|
||||||
|
|
@ -612,7 +664,7 @@ pub fn build_user_interface<'a, A: Application>(
|
||||||
debug: &mut Debug,
|
debug: &mut Debug,
|
||||||
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
||||||
where
|
where
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
debug.view_started();
|
debug.view_started();
|
||||||
let view = application.view();
|
let view = application.view();
|
||||||
|
|
@ -643,7 +695,7 @@ pub fn update<A: Application, C, E: Executor>(
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
) where
|
) where
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
debug.log_message(&message);
|
debug.log_message(&message);
|
||||||
|
|
@ -694,7 +746,7 @@ pub fn run_command<A, C, E>(
|
||||||
A: Application,
|
A: Application,
|
||||||
E: Executor,
|
E: Executor,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use crate::runtime::command;
|
use crate::runtime::command;
|
||||||
use crate::runtime::system;
|
use crate::runtime::system;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::application::{self, StyleSheet as _};
|
use crate::application;
|
||||||
use crate::conversion;
|
use crate::conversion;
|
||||||
use crate::core::mouse;
|
use crate::core::mouse;
|
||||||
use crate::core::{Color, Size};
|
use crate::core::{Color, Size};
|
||||||
|
|
@ -14,7 +14,7 @@ use winit::window::Window;
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct State<A: Application>
|
pub struct State<A: Application>
|
||||||
where
|
where
|
||||||
A::Theme: application::StyleSheet,
|
application::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
title: String,
|
title: String,
|
||||||
scale_factor: f64,
|
scale_factor: f64,
|
||||||
|
|
@ -29,14 +29,14 @@ where
|
||||||
|
|
||||||
impl<A: Application> State<A>
|
impl<A: Application> State<A>
|
||||||
where
|
where
|
||||||
A::Theme: application::StyleSheet,
|
application::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
/// Creates a new [`State`] for the provided [`Application`] and window.
|
/// Creates a new [`State`] for the provided [`Application`] and window.
|
||||||
pub fn new(application: &A, window: &Window) -> Self {
|
pub fn new(application: &A, window: &Window) -> Self {
|
||||||
let title = application.title();
|
let title = application.title();
|
||||||
let scale_factor = application.scale_factor();
|
let scale_factor = application.scale_factor();
|
||||||
let theme = application.theme();
|
let theme = application.theme();
|
||||||
let appearance = theme.appearance(&application.style());
|
let appearance = application.style(&theme);
|
||||||
|
|
||||||
let viewport = {
|
let viewport = {
|
||||||
let physical_size = window.inner_size();
|
let physical_size = window.inner_size();
|
||||||
|
|
@ -216,6 +216,6 @@ where
|
||||||
|
|
||||||
// Update theme and appearance
|
// Update theme and appearance
|
||||||
self.theme = application.theme();
|
self.theme = application.theme();
|
||||||
self.appearance = self.theme.appearance(&application.style());
|
self.appearance = application.style(&self.theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,10 @@ use crate::runtime::command::{self, Command};
|
||||||
use crate::runtime::multi_window::Program;
|
use crate::runtime::multi_window::Program;
|
||||||
use crate::runtime::user_interface::{self, UserInterface};
|
use crate::runtime::user_interface::{self, UserInterface};
|
||||||
use crate::runtime::Debug;
|
use crate::runtime::Debug;
|
||||||
use crate::style::application::StyleSheet;
|
|
||||||
use crate::{Clipboard, Error, Proxy, Settings};
|
use crate::{Clipboard, Error, Proxy, Settings};
|
||||||
|
|
||||||
|
pub use crate::application::{default, Appearance, Style};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -41,7 +42,7 @@ use std::time::Instant;
|
||||||
/// can be toggled by pressing `F12`.
|
/// can be toggled by pressing `F12`.
|
||||||
pub trait Application: Program
|
pub trait Application: Program
|
||||||
where
|
where
|
||||||
Self::Theme: StyleSheet,
|
Style<Self::Theme>: Default,
|
||||||
{
|
{
|
||||||
/// The data needed to initialize your [`Application`].
|
/// The data needed to initialize your [`Application`].
|
||||||
type Flags;
|
type Flags;
|
||||||
|
|
@ -66,8 +67,8 @@ where
|
||||||
fn theme(&self, window: window::Id) -> Self::Theme;
|
fn theme(&self, window: window::Id) -> Self::Theme;
|
||||||
|
|
||||||
/// Returns the `Style` variation of the `Theme`.
|
/// Returns the `Style` variation of the `Theme`.
|
||||||
fn style(&self) -> <Self::Theme as StyleSheet>::Style {
|
fn style(&self, theme: &Self::Theme) -> Appearance {
|
||||||
Default::default()
|
Style::default().resolve(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the event `Subscription` for the current state of the
|
/// Returns the event `Subscription` for the current state of the
|
||||||
|
|
@ -108,7 +109,7 @@ where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use winit::event_loop::EventLoopBuilder;
|
use winit::event_loop::EventLoopBuilder;
|
||||||
|
|
||||||
|
|
@ -349,7 +350,7 @@ async fn run_instance<A, E, C>(
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use winit::event;
|
use winit::event;
|
||||||
use winit::event_loop::ControlFlow;
|
use winit::event_loop::ControlFlow;
|
||||||
|
|
@ -819,7 +820,7 @@ fn build_user_interface<'a, A: Application>(
|
||||||
id: window::Id,
|
id: window::Id,
|
||||||
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
) -> UserInterface<'a, A::Message, A::Theme, A::Renderer>
|
||||||
where
|
where
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
debug.view_started();
|
debug.view_started();
|
||||||
let view = application.view(id);
|
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>,
|
ui_caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||||
) where
|
) where
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
debug.log_message(&message);
|
debug.log_message(&message);
|
||||||
|
|
@ -890,7 +891,7 @@ fn run_command<A, C, E>(
|
||||||
A: Application,
|
A: Application,
|
||||||
E: Executor,
|
E: Executor,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Renderer = A::Renderer> + 'static,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
use crate::runtime::clipboard;
|
use crate::runtime::clipboard;
|
||||||
use crate::runtime::system;
|
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>,
|
mut cached_user_interfaces: HashMap<window::Id, user_interface::Cache>,
|
||||||
) -> HashMap<window::Id, UserInterface<'a, A::Message, A::Theme, A::Renderer>>
|
) -> HashMap<window::Id, UserInterface<'a, A::Message, A::Theme, A::Renderer>>
|
||||||
where
|
where
|
||||||
A::Theme: StyleSheet,
|
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
cached_user_interfaces
|
cached_user_interfaces
|
||||||
.drain()
|
.drain()
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,16 @@ use crate::conversion;
|
||||||
use crate::core::{mouse, window};
|
use crate::core::{mouse, window};
|
||||||
use crate::core::{Color, Size};
|
use crate::core::{Color, Size};
|
||||||
use crate::graphics::Viewport;
|
use crate::graphics::Viewport;
|
||||||
use crate::multi_window::Application;
|
use crate::multi_window::{self, Application};
|
||||||
use crate::style::application;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
use iced_style::application::StyleSheet;
|
|
||||||
use winit::event::{Touch, WindowEvent};
|
use winit::event::{Touch, WindowEvent};
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
|
||||||
/// The state of a multi-windowed [`Application`].
|
/// The state of a multi-windowed [`Application`].
|
||||||
pub struct State<A: Application>
|
pub struct State<A: Application>
|
||||||
where
|
where
|
||||||
A::Theme: application::StyleSheet,
|
multi_window::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
title: String,
|
title: String,
|
||||||
scale_factor: f64,
|
scale_factor: f64,
|
||||||
|
|
@ -22,12 +20,12 @@ where
|
||||||
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
|
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
|
||||||
modifiers: winit::keyboard::ModifiersState,
|
modifiers: winit::keyboard::ModifiersState,
|
||||||
theme: A::Theme,
|
theme: A::Theme,
|
||||||
appearance: application::Appearance,
|
appearance: multi_window::Appearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Application> Debug for State<A>
|
impl<A: Application> Debug for State<A>
|
||||||
where
|
where
|
||||||
A::Theme: application::StyleSheet,
|
multi_window::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("multi_window::State")
|
f.debug_struct("multi_window::State")
|
||||||
|
|
@ -43,7 +41,7 @@ where
|
||||||
|
|
||||||
impl<A: Application> State<A>
|
impl<A: Application> State<A>
|
||||||
where
|
where
|
||||||
A::Theme: application::StyleSheet,
|
multi_window::Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
/// Creates a new [`State`] for the provided [`Application`]'s `window`.
|
/// Creates a new [`State`] for the provided [`Application`]'s `window`.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
|
@ -54,7 +52,7 @@ where
|
||||||
let title = application.title(window_id);
|
let title = application.title(window_id);
|
||||||
let scale_factor = application.scale_factor(window_id);
|
let scale_factor = application.scale_factor(window_id);
|
||||||
let theme = application.theme(window_id);
|
let theme = application.theme(window_id);
|
||||||
let appearance = theme.appearance(&application.style());
|
let appearance = application.style(&theme);
|
||||||
|
|
||||||
let viewport = {
|
let viewport = {
|
||||||
let physical_size = window.inner_size();
|
let physical_size = window.inner_size();
|
||||||
|
|
@ -236,6 +234,6 @@ where
|
||||||
|
|
||||||
// Update theme and appearance
|
// Update theme and appearance
|
||||||
self.theme = application.theme(window_id);
|
self.theme = application.theme(window_id);
|
||||||
self.appearance = self.theme.appearance(&application.style());
|
self.appearance = application.style(&self.theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ use crate::core::mouse;
|
||||||
use crate::core::window::Id;
|
use crate::core::window::Id;
|
||||||
use crate::core::{Point, Size};
|
use crate::core::{Point, Size};
|
||||||
use crate::graphics::Compositor;
|
use crate::graphics::Compositor;
|
||||||
use crate::multi_window::{Application, State};
|
use crate::multi_window::{Application, State, Style};
|
||||||
use crate::style::application::StyleSheet;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -12,8 +11,8 @@ use winit::monitor::MonitorHandle;
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct WindowManager<A: Application, C: Compositor>
|
pub struct WindowManager<A: Application, C: Compositor>
|
||||||
where
|
where
|
||||||
A::Theme: StyleSheet,
|
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
aliases: BTreeMap<winit::window::WindowId, Id>,
|
aliases: BTreeMap<winit::window::WindowId, Id>,
|
||||||
entries: BTreeMap<Id, Window<A, C>>,
|
entries: BTreeMap<Id, Window<A, C>>,
|
||||||
|
|
@ -23,7 +22,7 @@ impl<A, C> WindowManager<A, C>
|
||||||
where
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -109,7 +108,7 @@ impl<A, C> Default for WindowManager<A, C>
|
||||||
where
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
|
|
@ -121,7 +120,7 @@ pub struct Window<A, C>
|
||||||
where
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
pub raw: Arc<winit::window::Window>,
|
pub raw: Arc<winit::window::Window>,
|
||||||
pub state: State<A>,
|
pub state: State<A>,
|
||||||
|
|
@ -136,7 +135,7 @@ impl<A, C> Window<A, C>
|
||||||
where
|
where
|
||||||
A: Application,
|
A: Application,
|
||||||
C: Compositor<Renderer = A::Renderer>,
|
C: Compositor<Renderer = A::Renderer>,
|
||||||
A::Theme: StyleSheet,
|
Style<A::Theme>: Default,
|
||||||
{
|
{
|
||||||
pub fn position(&self) -> Option<Point> {
|
pub fn position(&self) -> Option<Point> {
|
||||||
self.raw
|
self.raw
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue