1use crate::application::{Application, Boot, View};
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 Boot<State, Message>,
24 update: impl Update<State, Message>,
25 subscription: impl Fn(&State) -> Subscription<Message>,
26 view: impl for<'a> View<'a, State, Message, Theme, Renderer>,
27) -> Application<
28 impl Program<State = State, Message = (Message, Instant), Theme = Theme>,
29>
30where
31 State: 'static,
32 Message: program::Message + 'static,
33 Theme: Default + 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: program::Message + 'static,
72 Theme: Default + theme::Base + 'static,
73 Renderer: program::Renderer + 'static,
74 Boot: self::Boot<State, Message>,
75 Update: self::Update<State, Message>,
76 Subscription: Fn(&State) -> self::Subscription<Message>,
77 View: for<'a> self::View<'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 boot(&self) -> (State, Task<Self::Message>) {
92 let (state, task) = self.boot.boot();
93
94 (state, task.map(|message| (message, Instant::now())))
95 }
96
97 fn update(
98 &self,
99 state: &mut Self::State,
100 (message, now): Self::Message,
101 ) -> Task<Self::Message> {
102 debug::hot(move || {
103 self.update
104 .update(state, message, now)
105 .into()
106 .map(|message| (message, Instant::now()))
107 })
108 }
109
110 fn view<'a>(
111 &self,
112 state: &'a Self::State,
113 _window: window::Id,
114 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
115 debug::hot(|| {
116 self.view
117 .view(state)
118 .map(|message| (message, Instant::now()))
119 })
120 }
121
122 fn subscription(
123 &self,
124 state: &Self::State,
125 ) -> self::Subscription<Self::Message> {
126 debug::hot(|| {
127 (self.subscription)(state)
128 .map(|message| (message, Instant::now()))
129 })
130 }
131 }
132
133 Application {
134 raw: Instance {
135 boot,
136 update,
137 subscription,
138 view,
139 _state: PhantomData,
140 _message: PhantomData,
141 _theme: PhantomData,
142 _renderer: PhantomData,
143 },
144 settings: Settings::default(),
145 window: window::Settings::default(),
146 }
147}
148
149pub trait Update<State, Message> {
154 fn update(
156 &self,
157 state: &mut State,
158 message: Message,
159 now: Instant,
160 ) -> impl Into<Task<Message>>;
161}
162
163impl<State, Message> Update<State, Message> for () {
164 fn update(
165 &self,
166 _state: &mut State,
167 _message: Message,
168 _now: Instant,
169 ) -> impl Into<Task<Message>> {
170 }
171}
172
173impl<T, State, Message, C> Update<State, Message> for T
174where
175 T: Fn(&mut State, Message, Instant) -> C,
176 C: Into<Task<Message>>,
177{
178 fn update(
179 &self,
180 state: &mut State,
181 message: Message,
182 now: Instant,
183 ) -> impl Into<Task<Message>> {
184 self(state, message, now)
185 }
186}