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
9use iced_debug as debug;
10
11pub fn timed<State, Message, Theme, Renderer>(
23 boot: impl BootFn<State, Message>,
24 update: impl UpdateFn<State, Message>,
25 subscription: impl Fn(&State) -> Subscription<Message>,
26 view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
27) -> Application<
28 impl Program<State = State, Message = (Message, Instant), Theme = Theme>,
29>
30where
31 State: 'static,
32 Message: Send + 'static,
33 Theme: theme::Base + 'static,
34 Renderer: program::Renderer + 'static,
35{
36 use std::marker::PhantomData;
37
38 struct Instance<
39 State,
40 Message,
41 Theme,
42 Renderer,
43 Boot,
44 Update,
45 Subscription,
46 View,
47 > {
48 boot: Boot,
49 update: Update,
50 subscription: Subscription,
51 view: View,
52 _state: PhantomData<State>,
53 _message: PhantomData<Message>,
54 _theme: PhantomData<Theme>,
55 _renderer: PhantomData<Renderer>,
56 }
57
58 impl<State, Message, Theme, Renderer, Boot, Update, Subscription, View>
59 Program
60 for Instance<
61 State,
62 Message,
63 Theme,
64 Renderer,
65 Boot,
66 Update,
67 Subscription,
68 View,
69 >
70 where
71 Message: Send + 'static,
72 Theme: theme::Base + 'static,
73 Renderer: program::Renderer + 'static,
74 Boot: self::BootFn<State, Message>,
75 Update: self::UpdateFn<State, Message>,
76 Subscription: Fn(&State) -> self::Subscription<Message>,
77 View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
78 {
79 type State = State;
80 type Message = (Message, Instant);
81 type Theme = Theme;
82 type Renderer = Renderer;
83 type Executor = iced_futures::backend::default::Executor;
84
85 fn name() -> &'static str {
86 let name = std::any::type_name::<State>();
87
88 name.split("::").next().unwrap_or("a_cool_application")
89 }
90
91 fn settings(&self) -> Settings {
92 Settings::default()
93 }
94
95 fn window(&self) -> Option<iced_core::window::Settings> {
96 Some(window::Settings::default())
97 }
98
99 fn boot(&self) -> (State, Task<Self::Message>) {
100 let (state, task) = self.boot.boot();
101
102 (state, task.map(|message| (message, Instant::now())))
103 }
104
105 fn update(
106 &self,
107 state: &mut Self::State,
108 (message, now): Self::Message,
109 ) -> Task<Self::Message> {
110 debug::hot(move || {
111 self.update
112 .update(state, message, now)
113 .into()
114 .map(|message| (message, Instant::now()))
115 })
116 }
117
118 fn view<'a>(
119 &self,
120 state: &'a Self::State,
121 _window: window::Id,
122 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
123 debug::hot(|| {
124 self.view
125 .view(state)
126 .map(|message| (message, Instant::now()))
127 })
128 }
129
130 fn subscription(
131 &self,
132 state: &Self::State,
133 ) -> self::Subscription<Self::Message> {
134 debug::hot(|| {
135 (self.subscription)(state)
136 .map(|message| (message, Instant::now()))
137 })
138 }
139 }
140
141 Application {
142 raw: Instance {
143 boot,
144 update,
145 subscription,
146 view,
147 _state: PhantomData,
148 _message: PhantomData,
149 _theme: PhantomData,
150 _renderer: PhantomData,
151 },
152 settings: Settings::default(),
153 window: window::Settings::default(),
154 presets: Vec::new(),
155 }
156}
157
158pub trait UpdateFn<State, Message> {
163 fn update(
165 &self,
166 state: &mut State,
167 message: Message,
168 now: Instant,
169 ) -> impl Into<Task<Message>>;
170}
171
172impl<State, Message> UpdateFn<State, Message> for () {
173 fn update(
174 &self,
175 _state: &mut State,
176 _message: Message,
177 _now: Instant,
178 ) -> impl Into<Task<Message>> {
179 }
180}
181
182impl<T, State, Message, C> UpdateFn<State, Message> for T
183where
184 T: Fn(&mut State, Message, Instant) -> C,
185 C: Into<Task<Message>>,
186{
187 fn update(
188 &self,
189 state: &mut State,
190 message: Message,
191 now: Instant,
192 ) -> impl Into<Task<Message>> {
193 self(state, message, now)
194 }
195}