Skip to main content

iced/
application.rs

1//! Create and run iced applications step by step.
2//!
3//! # Example
4//! ```no_run,standalone_crate
5//! use iced::widget::{button, column, text, Column};
6//! use iced::Theme;
7//!
8//! pub fn main() -> iced::Result {
9//!     iced::application(u64::default, update, view)
10//!         .theme(Theme::Dark)
11//!         .centered()
12//!         .run()
13//! }
14//!
15//! #[derive(Debug, Clone)]
16//! enum Message {
17//!     Increment,
18//! }
19//!
20//! fn update(value: &mut u64, message: Message) {
21//!     match message {
22//!         Message::Increment => *value += 1,
23//!     }
24//! }
25//!
26//! fn view(value: &u64) -> Column<Message> {
27//!     column![
28//!         text(value),
29//!         button("+").on_press(Message::Increment),
30//!     ]
31//! }
32//! ```
33use crate::backend;
34use crate::message;
35use crate::program::{self, Program};
36use crate::shell;
37use crate::theme;
38use crate::widget::text;
39use crate::window;
40use crate::{
41    Backend, Element, Executor, Font, Never, Preset, Result, Settings, Size, Subscription, Task,
42    Theme,
43};
44
45#[cfg(feature = "hot")]
46use crate::hot::Hot;
47
48use std::borrow::Cow;
49
50pub mod timed;
51
52pub use timed::timed;
53
54/// Creates an iced [`Application`] given its boot, update, and view logic.
55///
56/// # Example
57/// ```no_run,standalone_crate
58/// use iced::widget::{button, column, text, Column};
59///
60/// pub fn main() -> iced::Result {
61///     iced::application(u64::default, update, view).run()
62/// }
63///
64/// #[derive(Debug, Clone)]
65/// enum Message {
66///     Increment,
67/// }
68///
69/// fn update(value: &mut u64, message: Message) {
70///     match message {
71///         Message::Increment => *value += 1,
72///     }
73/// }
74///
75/// fn view(value: &u64) -> Column<Message> {
76///     column![
77///         text(value),
78///         button("+").on_press(Message::Increment),
79///     ]
80/// }
81/// ```
82pub fn application<State, Message, Theme, Renderer>(
83    boot: impl BootFn<State, Message>,
84    update: impl UpdateFn<State, Message>,
85    view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
86) -> Application<impl Program<State = State, Message = Message, Theme = Theme>>
87where
88    State: 'static,
89    Message: Send + 'static,
90    Theme: theme::Base,
91    Renderer: program::Renderer,
92{
93    use std::marker::PhantomData;
94
95    struct Instance<State, Message, Theme, Renderer, Boot, Update, View> {
96        boot: Boot,
97        update: Update,
98        view: View,
99        _state: PhantomData<State>,
100        _message: PhantomData<Message>,
101        _theme: PhantomData<Theme>,
102        _renderer: PhantomData<Renderer>,
103    }
104
105    impl<State, Message, Theme, Renderer, Boot, Update, View> Program
106        for Instance<State, Message, Theme, Renderer, Boot, Update, View>
107    where
108        Message: Send + 'static,
109        Theme: theme::Base,
110        Renderer: program::Renderer,
111        Boot: self::BootFn<State, Message>,
112        Update: self::UpdateFn<State, Message>,
113        View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
114    {
115        type State = State;
116        type Message = Message;
117        type Theme = Theme;
118        type Renderer = Renderer;
119        type Executor = iced_futures::backend::default::Executor;
120
121        fn name() -> &'static str {
122            let name = std::any::type_name::<State>();
123
124            name.split("::").next().unwrap_or("a_cool_application")
125        }
126
127        fn boot(&self) -> (State, Task<Message>) {
128            self.boot.boot()
129        }
130
131        fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
132            self.update.update(state, message)
133        }
134
135        fn view<'a>(
136            &self,
137            state: &'a Self::State,
138            _window: window::Id,
139        ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
140            self.view.view(state)
141        }
142
143        fn settings(&self) -> Settings {
144            Settings::default()
145        }
146
147        fn window(&self) -> Option<iced_core::window::Settings> {
148            Some(window::Settings::default())
149        }
150    }
151
152    Application {
153        raw: Instance {
154            boot,
155            update,
156            view,
157            _state: PhantomData,
158            _message: PhantomData,
159            _theme: PhantomData,
160            _renderer: PhantomData,
161        },
162        settings: Settings::default(),
163        window: window::Settings::default(),
164        presets: Vec::new(),
165    }
166}
167
168/// The underlying definition and configuration of an iced application.
169///
170/// You can use this API to create and run iced applications
171/// step by step—without coupling your logic to a trait
172/// or a specific type.
173///
174/// You can create an [`Application`] with the [`application`] helper.
175#[derive(Debug)]
176pub struct Application<P: Program> {
177    raw: P,
178    settings: Settings,
179    window: window::Settings,
180    presets: Vec<Preset<P::State, P::Message>>,
181}
182
183impl<P: Program> Application<P> {
184    /// Runs the [`Application`].
185    pub fn run(self) -> Result
186    where
187        Self: 'static,
188        P::Message: message::MaybeDebug + message::MaybeClone,
189    {
190        #[cfg(feature = "debug")]
191        iced_debug::init(iced_debug::Metadata {
192            name: P::name(),
193            theme: None,
194            can_time_travel: cfg!(feature = "time-travel"),
195        });
196
197        #[cfg(feature = "tester")]
198        let program = iced_tester::attach(self);
199
200        #[cfg(all(
201            feature = "debug",
202            not(feature = "tester"),
203            not(target_arch = "wasm32")
204        ))]
205        let program = iced_devtools::attach(self);
206
207        #[cfg(not(any(
208            feature = "tester",
209            all(feature = "debug", not(target_arch = "wasm32"))
210        )))]
211        let program = self;
212
213        #[cfg(feature = "hot")]
214        let program = Hot::new(program);
215
216        Ok(shell::run(program)?)
217    }
218
219    /// Sets the [`Settings`] that will be used to run the [`Application`].
220    pub fn settings(self, settings: Settings) -> Self {
221        Self { settings, ..self }
222    }
223
224    /// Sets the [`Settings::antialiasing`] of the [`Application`].
225    pub fn antialiasing(self, antialiasing: bool) -> Self {
226        Self {
227            settings: Settings {
228                antialiasing,
229                ..self.settings
230            },
231            ..self
232        }
233    }
234
235    /// Sets the default [`Font`] of the [`Application`].
236    pub fn font(self, font: Font) -> Self {
237        Self {
238            settings: Settings {
239                font,
240                ..self.settings
241            },
242            ..self
243        }
244    }
245
246    /// Sets the default [`text::LineHeight`] of the [`Application`].
247    pub fn line_height(self, line_height: text::LineHeight) -> Self {
248        Self {
249            settings: Settings {
250                line_height,
251                ..self.settings
252            },
253            ..self
254        }
255    }
256
257    /// Adds a set of fonts to the list of fonts that will be loaded at the start of the [`Application`].
258    pub fn fonts(mut self, fonts: impl IntoIterator<Item = impl Into<Cow<'static, [u8]>>>) -> Self {
259        self.settings
260            .fonts
261            .extend(fonts.into_iter().map(Into::into));
262
263        self
264    }
265
266    /// Sets the [`window::Settings`] of the [`Application`].
267    ///
268    /// Overwrites any previous [`window::Settings`].
269    pub fn window(self, window: window::Settings) -> Self {
270        Self { window, ..self }
271    }
272
273    /// Sets the [`window::Settings::position`] to [`window::Position::Centered`] in the [`Application`].
274    pub fn centered(self) -> Self {
275        Self {
276            window: window::Settings {
277                position: window::Position::Centered,
278                ..self.window
279            },
280            ..self
281        }
282    }
283
284    /// Sets the [`window::Settings::exit_on_close_request`] of the [`Application`].
285    pub fn exit_on_close_request(self, exit_on_close_request: bool) -> Self {
286        Self {
287            window: window::Settings {
288                exit_on_close_request,
289                ..self.window
290            },
291            ..self
292        }
293    }
294
295    /// Sets the [`window::Settings::size`] of the [`Application`].
296    pub fn window_size(self, size: impl Into<Size>) -> Self {
297        Self {
298            window: window::Settings {
299                size: size.into(),
300                ..self.window
301            },
302            ..self
303        }
304    }
305
306    /// Sets the [`window::Settings::transparent`] of the [`Application`].
307    pub fn transparent(self, transparent: bool) -> Self {
308        Self {
309            window: window::Settings {
310                transparent,
311                ..self.window
312            },
313            ..self
314        }
315    }
316
317    /// Sets the [`window::Settings::resizable`] of the [`Application`].
318    pub fn resizable(self, resizable: bool) -> Self {
319        Self {
320            window: window::Settings {
321                resizable,
322                ..self.window
323            },
324            ..self
325        }
326    }
327
328    /// Sets the [`window::Settings::decorations`] of the [`Application`].
329    pub fn decorations(self, decorations: bool) -> Self {
330        Self {
331            window: window::Settings {
332                decorations,
333                ..self.window
334            },
335            ..self
336        }
337    }
338
339    /// Sets the [`window::Settings::position`] of the [`Application`].
340    pub fn position(self, position: window::Position) -> Self {
341        Self {
342            window: window::Settings {
343                position,
344                ..self.window
345            },
346            ..self
347        }
348    }
349
350    /// Sets the [`window::Settings::level`] of the [`Application`].
351    pub fn level(self, level: window::Level) -> Self {
352        Self {
353            window: window::Settings {
354                level,
355                ..self.window
356            },
357            ..self
358        }
359    }
360
361    /// Sets the [`Backend`] of the [`Application`].
362    pub fn backend(self, backend: Backend) -> Self {
363        Self {
364            settings: Settings {
365                backend,
366                ..self.settings
367            },
368            ..self
369        }
370    }
371
372    /// Sets the [`backend::PowerPreference`] of the [`Application`].
373    pub fn power_preference(self, power_preference: backend::PowerPreference) -> Self {
374        Self {
375            settings: Settings {
376                power_preference,
377                ..self.settings
378            },
379            ..self
380        }
381    }
382
383    /// Sets the title of the [`Application`].
384    pub fn title(
385        self,
386        title: impl TitleFn<P::State>,
387    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
388        Application {
389            raw: with_title(self.raw, title),
390            settings: self.settings,
391            window: self.window,
392            presets: self.presets,
393        }
394    }
395
396    /// Sets the subscription logic of the [`Application`].
397    pub fn subscription(
398        self,
399        f: impl Fn(&P::State) -> Subscription<P::Message>,
400    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
401        Application {
402            raw: program::with_subscription(self.raw, f),
403            settings: self.settings,
404            window: self.window,
405            presets: self.presets,
406        }
407    }
408
409    /// Sets the theme logic of the [`Application`].
410    pub fn theme(
411        self,
412        f: impl ThemeFn<P::State, P::Theme>,
413    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
414        Application {
415            raw: with_theme(self.raw, f),
416            settings: self.settings,
417            window: self.window,
418            presets: self.presets,
419        }
420    }
421
422    /// Sets the style logic of the [`Application`].
423    pub fn style(
424        self,
425        f: impl Fn(&P::State, &P::Theme) -> theme::Style,
426    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
427        Application {
428            raw: program::with_style(self.raw, f),
429            settings: self.settings,
430            window: self.window,
431            presets: self.presets,
432        }
433    }
434
435    /// Sets the scale factor of the [`Application`].
436    pub fn scale_factor(
437        self,
438        f: impl Fn(&P::State) -> f32,
439    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>> {
440        Application {
441            raw: with_scale_factor(self.raw, f),
442            settings: self.settings,
443            window: self.window,
444            presets: self.presets,
445        }
446    }
447
448    /// Sets the executor of the [`Application`].
449    pub fn executor<E>(
450        self,
451    ) -> Application<impl Program<State = P::State, Message = P::Message, Theme = P::Theme>>
452    where
453        E: Executor,
454    {
455        Application {
456            raw: program::with_executor::<P, E>(self.raw),
457            settings: self.settings,
458            window: self.window,
459            presets: self.presets,
460        }
461    }
462
463    /// Sets the boot presets of the [`Application`].
464    ///
465    /// Presets can be used to override the default booting strategy
466    /// of your application during testing to create reproducible
467    /// environments.
468    pub fn presets(self, presets: impl IntoIterator<Item = Preset<P::State, P::Message>>) -> Self {
469        Self {
470            presets: presets.into_iter().collect(),
471            ..self
472        }
473    }
474}
475
476impl<P: Program> Program for Application<P> {
477    type State = P::State;
478    type Message = P::Message;
479    type Theme = P::Theme;
480    type Renderer = P::Renderer;
481    type Executor = P::Executor;
482
483    fn name() -> &'static str {
484        P::name()
485    }
486
487    fn settings(&self) -> Settings {
488        self.settings.clone()
489    }
490
491    fn window(&self) -> Option<window::Settings> {
492        Some(self.window.clone())
493    }
494
495    #[inline]
496    fn boot(&self) -> (Self::State, Task<Self::Message>) {
497        self.raw.boot()
498    }
499
500    #[inline]
501    fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
502        self.raw.update(state, message)
503    }
504
505    #[inline]
506    fn view<'a>(
507        &self,
508        state: &'a Self::State,
509        window: window::Id,
510    ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
511        self.raw.view(state, window)
512    }
513
514    #[inline]
515    fn title(&self, state: &Self::State, window: window::Id) -> String {
516        self.raw.title(state, window)
517    }
518
519    #[inline]
520    fn subscription(&self, state: &Self::State) -> Subscription<Self::Message> {
521        self.raw.subscription(state)
522    }
523
524    #[inline]
525    fn theme(&self, state: &Self::State, window: iced_core::window::Id) -> Option<Self::Theme> {
526        self.raw.theme(state, window)
527    }
528
529    #[inline]
530    fn style(&self, state: &Self::State, theme: &Self::Theme) -> theme::Style {
531        self.raw.style(state, theme)
532    }
533
534    #[inline]
535    fn scale_factor(&self, state: &Self::State, window: window::Id) -> f32 {
536        self.raw.scale_factor(state, window)
537    }
538
539    fn presets(&self) -> &[Preset<Self::State, Self::Message>] {
540        &self.presets
541    }
542}
543
544/// The logic to initialize the `State` of some [`Application`].
545///
546/// This trait is implemented for both `Fn() -> State` and
547/// `Fn() -> (State, Task<Message>)`.
548///
549/// In practice, this means that [`application`] can both take
550/// simple functions like `State::default` and more advanced ones
551/// that return a [`Task`].
552pub trait BootFn<State, Message> {
553    /// Initializes the [`Application`] state.
554    fn boot(&self) -> (State, Task<Message>);
555}
556
557impl<T, C, State, Message> BootFn<State, Message> for T
558where
559    T: Fn() -> C,
560    C: IntoBoot<State, Message>,
561{
562    fn boot(&self) -> (State, Task<Message>) {
563        self().into_boot()
564    }
565}
566
567/// The initial state of some [`Application`].
568pub trait IntoBoot<State, Message> {
569    /// Turns some type into the initial state of some [`Application`].
570    fn into_boot(self) -> (State, Task<Message>);
571}
572
573impl<State, Message> IntoBoot<State, Message> for State {
574    fn into_boot(self) -> (State, Task<Message>) {
575        (self, Task::none())
576    }
577}
578
579impl<State, Message> IntoBoot<State, Message> for (State, Task<Message>) {
580    fn into_boot(self) -> (State, Task<Message>) {
581        self
582    }
583}
584
585/// The title logic of some [`Application`].
586///
587/// This trait is implemented both for `&'static str` and
588/// any closure `Fn(&State) -> String`.
589///
590/// This trait allows the [`Application::title`] builder to take any of them.
591pub trait TitleFn<State> {
592    /// Produces the title of the [`Application`].
593    fn title(&self, state: &State) -> String;
594}
595
596impl<State> TitleFn<State> for &'static str {
597    #[inline]
598    fn title(&self, _state: &State) -> String {
599        self.to_string()
600    }
601}
602
603impl<T, State> TitleFn<State> for T
604where
605    T: Fn(&State) -> String,
606{
607    #[inline]
608    fn title(&self, state: &State) -> String {
609        (self)(state)
610    }
611}
612
613/// The theme logic of some [`Application`].
614///
615/// Any implementors of this trait can be provided as an argument to
616/// [`Application::theme`].
617///
618/// `iced` provides two implementors:
619/// - the built-in [`Theme`] itself
620/// - and any `Fn(&State) -> impl Into<Option<Theme>>`.
621pub trait ThemeFn<State, Theme>
622where
623    Theme: theme::Base,
624{
625    /// Returns the theme of the [`Application`] for the current state.
626    ///
627    /// If `None` is returned, `iced` will try to use a theme that
628    /// matches the system color scheme.
629    fn theme(&self, state: &State) -> Option<Theme>;
630}
631
632impl<State> ThemeFn<State, Theme> for Theme {
633    #[inline]
634    fn theme(&self, _state: &State) -> Option<Theme> {
635        Some(self.clone())
636    }
637}
638
639impl<F, T, State, Theme> ThemeFn<State, Theme> for F
640where
641    F: Fn(&State) -> T,
642    T: Into<Option<Theme>>,
643    Theme: theme::Base,
644{
645    #[inline]
646    fn theme(&self, state: &State) -> Option<Theme> {
647        (self)(state).into()
648    }
649}
650
651/// The update logic of some [`Application`].
652///
653/// This trait allows the [`application`] builder to take any closure that
654/// returns any `Into<Task<Message>>`.
655pub trait UpdateFn<State, Message> {
656    /// Processes the message and updates the state of the [`Application`].
657    fn update(&self, state: &mut State, message: Message) -> Task<Message>;
658}
659
660impl<State> UpdateFn<State, Never> for () {
661    fn update(&self, _state: &mut State, _message: Never) -> Task<Never> {
662        Task::none()
663    }
664}
665
666impl<T, State, Message, C> UpdateFn<State, Message> for T
667where
668    T: Fn(&mut State, Message) -> C,
669    C: Into<Task<Message>>,
670{
671    fn update(&self, state: &mut State, message: Message) -> Task<Message> {
672        self(state, message).into()
673    }
674}
675
676/// The view logic of some [`Application`].
677///
678/// This trait allows the [`application`] builder to take any closure that
679/// returns any `Into<Element<'_, Message>>`.
680pub trait ViewFn<'a, State, Message, Theme, Renderer> {
681    /// Produces the widget of the [`Application`].
682    fn view(&self, state: &'a State) -> Element<'a, Message, Theme, Renderer>;
683}
684
685impl<'a, T, State, Message, Theme, Renderer, Widget> ViewFn<'a, State, Message, Theme, Renderer>
686    for T
687where
688    T: Fn(&'a State) -> Widget,
689    State: 'static,
690    Widget: Into<Element<'a, Message, Theme, Renderer>>,
691{
692    #[inline]
693    fn view(&self, state: &'a State) -> Element<'a, Message, Theme, Renderer> {
694        self(state).into()
695    }
696}
697
698/// Decorates a [`Program`] with the given title function.
699fn with_title<P: Program>(
700    program: P,
701    title: impl TitleFn<P::State>,
702) -> impl Program<State = P::State, Message = P::Message, Theme = P::Theme> {
703    struct WithTitle<P, Title> {
704        program: P,
705        title: Title,
706    }
707
708    impl<P, Title> Program for WithTitle<P, Title>
709    where
710        P: Program,
711        Title: TitleFn<P::State>,
712    {
713        type State = P::State;
714        type Message = P::Message;
715        type Theme = P::Theme;
716        type Renderer = P::Renderer;
717        type Executor = P::Executor;
718
719        #[inline]
720        fn title(&self, state: &Self::State, _window: window::Id) -> String {
721            self.title.title(state)
722        }
723
724        #[inline]
725        fn name() -> &'static str {
726            P::name()
727        }
728
729        #[inline]
730        fn settings(&self) -> Settings {
731            self.program.settings()
732        }
733
734        #[inline]
735        fn window(&self) -> Option<window::Settings> {
736            self.program.window()
737        }
738
739        #[inline]
740        fn boot(&self) -> (Self::State, Task<Self::Message>) {
741            self.program.boot()
742        }
743
744        #[inline]
745        fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
746            self.program.update(state, message)
747        }
748
749        #[inline]
750        fn view<'a>(
751            &self,
752            state: &'a Self::State,
753            window: window::Id,
754        ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
755            self.program.view(state, window)
756        }
757
758        #[inline]
759        fn theme(&self, state: &Self::State, window: window::Id) -> Option<Self::Theme> {
760            self.program.theme(state, window)
761        }
762
763        #[inline]
764        fn subscription(&self, state: &Self::State) -> Subscription<Self::Message> {
765            self.program.subscription(state)
766        }
767
768        #[inline]
769        fn style(&self, state: &Self::State, theme: &Self::Theme) -> theme::Style {
770            self.program.style(state, theme)
771        }
772
773        #[inline]
774        fn scale_factor(&self, state: &Self::State, window: window::Id) -> f32 {
775            self.program.scale_factor(state, window)
776        }
777    }
778
779    WithTitle { program, title }
780}
781
782/// Decorates a [`Program`] with the given theme function.
783fn with_theme<P: Program>(
784    program: P,
785    f: impl ThemeFn<P::State, P::Theme>,
786) -> impl Program<State = P::State, Message = P::Message, Theme = P::Theme> {
787    struct WithTheme<P, F> {
788        program: P,
789        theme: F,
790    }
791
792    impl<P: Program, F> Program for WithTheme<P, F>
793    where
794        F: ThemeFn<P::State, P::Theme>,
795    {
796        type State = P::State;
797        type Message = P::Message;
798        type Theme = P::Theme;
799        type Renderer = P::Renderer;
800        type Executor = P::Executor;
801
802        #[inline]
803        fn theme(&self, state: &Self::State, _window: window::Id) -> Option<Self::Theme> {
804            self.theme.theme(state)
805        }
806
807        #[inline]
808        fn name() -> &'static str {
809            P::name()
810        }
811
812        #[inline]
813        fn settings(&self) -> Settings {
814            self.program.settings()
815        }
816
817        #[inline]
818        fn window(&self) -> Option<window::Settings> {
819            self.program.window()
820        }
821
822        #[inline]
823        fn boot(&self) -> (Self::State, Task<Self::Message>) {
824            self.program.boot()
825        }
826
827        #[inline]
828        fn title(&self, state: &Self::State, window: window::Id) -> String {
829            self.program.title(state, window)
830        }
831
832        #[inline]
833        fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
834            self.program.update(state, message)
835        }
836
837        #[inline]
838        fn view<'a>(
839            &self,
840            state: &'a Self::State,
841            window: window::Id,
842        ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
843            self.program.view(state, window)
844        }
845
846        #[inline]
847        fn subscription(&self, state: &Self::State) -> Subscription<Self::Message> {
848            self.program.subscription(state)
849        }
850
851        #[inline]
852        fn style(&self, state: &Self::State, theme: &Self::Theme) -> theme::Style {
853            self.program.style(state, theme)
854        }
855
856        #[inline]
857        fn scale_factor(&self, state: &Self::State, window: window::Id) -> f32 {
858            self.program.scale_factor(state, window)
859        }
860    }
861
862    WithTheme { program, theme: f }
863}
864
865/// Decorates a [`Program`] with the given scale factor function.
866fn with_scale_factor<P: Program>(
867    program: P,
868    f: impl Fn(&P::State) -> f32,
869) -> impl Program<State = P::State, Message = P::Message, Theme = P::Theme> {
870    struct WithScaleFactor<P, F> {
871        program: P,
872        scale_factor: F,
873    }
874
875    impl<P, F> Program for WithScaleFactor<P, F>
876    where
877        P: Program,
878        F: Fn(&P::State) -> f32,
879    {
880        type State = P::State;
881        type Message = P::Message;
882        type Theme = P::Theme;
883        type Renderer = P::Renderer;
884        type Executor = P::Executor;
885
886        #[inline]
887        fn title(&self, state: &Self::State, window: window::Id) -> String {
888            self.program.title(state, window)
889        }
890
891        #[inline]
892        fn name() -> &'static str {
893            P::name()
894        }
895
896        #[inline]
897        fn settings(&self) -> Settings {
898            self.program.settings()
899        }
900
901        #[inline]
902        fn window(&self) -> Option<window::Settings> {
903            self.program.window()
904        }
905
906        #[inline]
907        fn boot(&self) -> (Self::State, Task<Self::Message>) {
908            self.program.boot()
909        }
910
911        #[inline]
912        fn update(&self, state: &mut Self::State, message: Self::Message) -> Task<Self::Message> {
913            self.program.update(state, message)
914        }
915
916        #[inline]
917        fn view<'a>(
918            &self,
919            state: &'a Self::State,
920            window: window::Id,
921        ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
922            self.program.view(state, window)
923        }
924
925        #[inline]
926        fn subscription(&self, state: &Self::State) -> Subscription<Self::Message> {
927            self.program.subscription(state)
928        }
929
930        #[inline]
931        fn theme(&self, state: &Self::State, window: window::Id) -> Option<Self::Theme> {
932            self.program.theme(state, window)
933        }
934
935        #[inline]
936        fn style(&self, state: &Self::State, theme: &Self::Theme) -> theme::Style {
937            self.program.style(state, theme)
938        }
939
940        #[inline]
941        fn scale_factor(&self, state: &Self::State, _window: window::Id) -> f32 {
942            (self.scale_factor)(state)
943        }
944    }
945
946    WithScaleFactor {
947        program,
948        scale_factor: f,
949    }
950}