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