1use crate::application::{Application, BootFn, ViewFn};
3use crate::program;
4use crate::theme;
5use crate::time::Instant;
6use crate::window;
7use crate::{Element, Program, Settings, Subscription, Task};
8
9pub fn timed<State, Message, Theme, Renderer>(
21 boot: impl BootFn<State, Message>,
22 update: impl UpdateFn<State, Message>,
23 subscription: impl Fn(&State) -> Subscription<Message>,
24 view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
25) -> Application<impl Program<State = State, Message = (Message, Instant), Theme = Theme>>
26where
27 State: 'static,
28 Message: Send + 'static,
29 Theme: theme::Base + 'static,
30 Renderer: program::Renderer + 'static,
31{
32 use std::marker::PhantomData;
33
34 struct Instance<State, Message, Theme, Renderer, Boot, Update, Subscription, View> {
35 boot: Boot,
36 update: Update,
37 subscription: Subscription,
38 view: View,
39 _state: PhantomData<State>,
40 _message: PhantomData<Message>,
41 _theme: PhantomData<Theme>,
42 _renderer: PhantomData<Renderer>,
43 }
44
45 impl<State, Message, Theme, Renderer, Boot, Update, Subscription, View> Program
46 for Instance<State, Message, Theme, Renderer, Boot, Update, Subscription, View>
47 where
48 Message: Send + 'static,
49 Theme: theme::Base + 'static,
50 Renderer: program::Renderer + 'static,
51 Boot: self::BootFn<State, Message>,
52 Update: self::UpdateFn<State, Message>,
53 Subscription: Fn(&State) -> self::Subscription<Message>,
54 View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
55 {
56 type State = State;
57 type Message = (Message, Instant);
58 type Theme = Theme;
59 type Renderer = Renderer;
60 type Executor = iced_futures::backend::default::Executor;
61
62 fn name() -> &'static str {
63 let name = std::any::type_name::<State>();
64
65 name.split("::").next().unwrap_or("a_cool_application")
66 }
67
68 fn settings(&self) -> Settings {
69 Settings::default()
70 }
71
72 fn window(&self) -> Option<iced_core::window::Settings> {
73 Some(window::Settings::default())
74 }
75
76 fn boot(&self) -> (State, Task<Self::Message>) {
77 let (state, task) = self.boot.boot();
78
79 (state, task.map(|message| (message, Instant::now())))
80 }
81
82 #[inline]
83 fn update(
84 &self,
85 state: &mut Self::State,
86 (message, now): Self::Message,
87 ) -> Task<Self::Message> {
88 self.update
89 .update(state, message, now)
90 .into()
91 .map(|message| (message, Instant::now()))
92 }
93
94 #[inline]
95 fn view<'a>(
96 &self,
97 state: &'a Self::State,
98 _window: window::Id,
99 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
100 self.view
101 .view(state)
102 .map(|message| (message, Instant::now()))
103 }
104
105 #[inline]
106 fn subscription(&self, state: &Self::State) -> self::Subscription<Self::Message> {
107 (self.subscription)(state).map(|message| (message, Instant::now()))
108 }
109 }
110
111 Application {
112 raw: Instance {
113 boot,
114 update,
115 subscription,
116 view,
117 _state: PhantomData,
118 _message: PhantomData,
119 _theme: PhantomData,
120 _renderer: PhantomData,
121 },
122 settings: Settings::default(),
123 window: window::Settings::default(),
124 presets: Vec::new(),
125 }
126}
127
128pub trait UpdateFn<State, Message> {
133 fn update(&self, state: &mut State, message: Message, now: Instant)
135 -> impl Into<Task<Message>>;
136}
137
138impl<State, Message> UpdateFn<State, Message> for () {
139 fn update(
140 &self,
141 _state: &mut State,
142 _message: Message,
143 _now: Instant,
144 ) -> impl Into<Task<Message>> {
145 }
146}
147
148impl<T, State, Message, C> UpdateFn<State, Message> for T
149where
150 T: Fn(&mut State, Message, Instant) -> C,
151 C: Into<Task<Message>>,
152{
153 fn update(
154 &self,
155 state: &mut State,
156 message: Message,
157 now: Instant,
158 ) -> impl Into<Task<Message>> {
159 self(state, message, now)
160 }
161}