Merge branch 'master' into feature/test-recorder

This commit is contained in:
Héctor Ramón Jiménez 2025-09-11 04:57:17 +02:00
commit a052ce58b0
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
69 changed files with 1555 additions and 833 deletions

View file

@ -7,6 +7,7 @@ use crate::theme;
use crate::window;
use crate::{
Element, Executor, Font, Preset, Result, Settings, Subscription, Task,
Theme,
};
use iced_debug as debug;
@ -24,14 +25,14 @@ use std::borrow::Cow;
///
/// [`exit`]: crate::exit
pub fn daemon<State, Message, Theme, Renderer>(
boot: impl application::Boot<State, Message>,
update: impl application::Update<State, Message>,
view: impl for<'a> View<'a, State, Message, Theme, Renderer>,
boot: impl application::BootFn<State, Message>,
update: impl application::UpdateFn<State, Message>,
view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
) -> Daemon<impl Program<State = State, Message = Message, Theme = Theme>>
where
State: 'static,
Message: Send + 'static,
Theme: Default + theme::Base,
Theme: theme::Base,
Renderer: program::Renderer,
{
use std::marker::PhantomData;
@ -50,11 +51,11 @@ where
for Instance<State, Message, Theme, Renderer, Boot, Update, View>
where
Message: Send + 'static,
Theme: Default + theme::Base,
Theme: theme::Base,
Renderer: program::Renderer,
Boot: application::Boot<State, Message>,
Update: application::Update<State, Message>,
View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
Boot: application::BootFn<State, Message>,
Update: application::UpdateFn<State, Message>,
View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
{
type State = State;
type Message = Message;
@ -183,10 +184,10 @@ impl<P: Program> Daemon<P> {
self
}
/// Sets the [`Title`] of the [`Daemon`].
/// Sets the title of the [`Daemon`].
pub fn title(
self,
title: impl Title<P::State>,
title: impl TitleFn<P::State>,
) -> Daemon<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
@ -216,12 +217,14 @@ impl<P: Program> Daemon<P> {
/// Sets the theme logic of the [`Daemon`].
pub fn theme(
self,
f: impl Fn(&P::State, window::Id) -> P::Theme,
f: impl ThemeFn<P::State, P::Theme>,
) -> Daemon<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Daemon {
raw: program::with_theme(self.raw, f),
raw: program::with_theme(self.raw, move |state, window| {
f.theme(state, window)
}),
settings: self.settings,
presets: self.presets,
}
@ -244,7 +247,7 @@ impl<P: Program> Daemon<P> {
/// Sets the scale factor of the [`Daemon`].
pub fn scale_factor(
self,
f: impl Fn(&P::State, window::Id) -> f64,
f: impl Fn(&P::State, window::Id) -> f32,
) -> Daemon<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
@ -338,7 +341,7 @@ impl<P: Program> Program for Daemon<P> {
&self,
state: &Self::State,
window: iced_core::window::Id,
) -> Self::Theme {
) -> Option<Self::Theme> {
debug::hot(|| self.raw.theme(state, window))
}
@ -346,7 +349,7 @@ impl<P: Program> Program for Daemon<P> {
debug::hot(|| self.raw.style(state, theme))
}
fn scale_factor(&self, state: &Self::State, window: window::Id) -> f64 {
fn scale_factor(&self, state: &Self::State, window: window::Id) -> f32 {
debug::hot(|| self.raw.scale_factor(state, window))
}
@ -361,18 +364,18 @@ impl<P: Program> Program for Daemon<P> {
/// any closure `Fn(&State, window::Id) -> String`.
///
/// This trait allows the [`daemon`] builder to take any of them.
pub trait Title<State> {
pub trait TitleFn<State> {
/// Produces the title of the [`Daemon`].
fn title(&self, state: &State, window: window::Id) -> String;
}
impl<State> Title<State> for &'static str {
impl<State> TitleFn<State> for &'static str {
fn title(&self, _state: &State, _window: window::Id) -> String {
self.to_string()
}
}
impl<T, State> Title<State> for T
impl<T, State> TitleFn<State> for T
where
T: Fn(&State, window::Id) -> String,
{
@ -385,7 +388,7 @@ where
///
/// This trait allows the [`daemon`] builder to take any closure that
/// returns any `Into<Element<'_, Message>>`.
pub trait View<'a, State, Message, Theme, Renderer> {
pub trait ViewFn<'a, State, Message, Theme, Renderer> {
/// Produces the widget of the [`Daemon`].
fn view(
&self,
@ -395,7 +398,7 @@ pub trait View<'a, State, Message, Theme, Renderer> {
}
impl<'a, T, State, Message, Theme, Renderer, Widget>
View<'a, State, Message, Theme, Renderer> for T
ViewFn<'a, State, Message, Theme, Renderer> for T
where
T: Fn(&'a State, window::Id) -> Widget,
State: 'static,
@ -409,3 +412,35 @@ where
self(state, window).into()
}
}
/// The theme logic of some [`Daemon`].
///
/// Any implementors of this trait can be provided as an argument to
/// [`Daemon::theme`].
///
/// `iced` provides two implementors:
/// - the built-in [`Theme`] itself
/// - and any `Fn(&State, window::Id) -> impl Into<Option<Theme>>`.
pub trait ThemeFn<State, Theme> {
/// Returns the theme of the [`Daemon`] for the current state and window.
///
/// If `None` is returned, `iced` will try to use a theme that
/// matches the system color scheme.
fn theme(&self, state: &State, window: window::Id) -> Option<Theme>;
}
impl<State> ThemeFn<State, Theme> for Theme {
fn theme(&self, _state: &State, _window: window::Id) -> Option<Theme> {
Some(self.clone())
}
}
impl<F, T, State, Theme> ThemeFn<State, Theme> for F
where
F: Fn(&State, window::Id) -> T,
T: Into<Option<Theme>>,
{
fn theme(&self, state: &State, window: window::Id) -> Option<Theme> {
(self)(state, window).into()
}
}