1use crate::application;
3use crate::program::{self, Program};
4use crate::shell;
5use crate::theme;
6use crate::window;
7use crate::{Element, Executor, Font, Result, Settings, Subscription, Task};
8
9use std::borrow::Cow;
10
11pub fn daemon<State, Message, Theme, Renderer>(
22 boot: impl application::Boot<State, Message>,
23 update: impl application::Update<State, Message>,
24 view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
25) -> Daemon<impl Program<State = State, Message = Message, Theme = Theme>>
26where
27 State: 'static,
28 Message: Send + std::fmt::Debug + 'static,
29 Theme: Default + theme::Base,
30 Renderer: program::Renderer,
31{
32 use std::marker::PhantomData;
33
34 struct Instance<State, Message, Theme, Renderer, Boot, Update, View> {
35 boot: Boot,
36 update: Update,
37 view: View,
38 _state: PhantomData<State>,
39 _message: PhantomData<Message>,
40 _theme: PhantomData<Theme>,
41 _renderer: PhantomData<Renderer>,
42 }
43
44 impl<State, Message, Theme, Renderer, Boot, Update, View> Program
45 for Instance<State, Message, Theme, Renderer, Boot, Update, View>
46 where
47 Message: Send + std::fmt::Debug + 'static,
48 Theme: Default + theme::Base,
49 Renderer: program::Renderer,
50 Boot: application::Boot<State, Message>,
51 Update: application::Update<State, Message>,
52 View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
53 {
54 type State = State;
55 type Message = Message;
56 type Theme = Theme;
57 type Renderer = Renderer;
58 type Executor = iced_futures::backend::default::Executor;
59
60 fn name() -> &'static str {
61 let name = std::any::type_name::<State>();
62
63 name.split("::").next().unwrap_or("a_cool_daemon")
64 }
65
66 fn boot(&self) -> (Self::State, Task<Self::Message>) {
67 self.boot.boot()
68 }
69
70 fn update(
71 &self,
72 state: &mut Self::State,
73 message: Self::Message,
74 ) -> Task<Self::Message> {
75 self.update.update(state, message).into()
76 }
77
78 fn view<'a>(
79 &self,
80 state: &'a Self::State,
81 window: window::Id,
82 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
83 self.view.view(state, window).into()
84 }
85 }
86
87 Daemon {
88 raw: Instance {
89 boot,
90 update,
91 view,
92 _state: PhantomData,
93 _message: PhantomData,
94 _theme: PhantomData,
95 _renderer: PhantomData,
96 },
97 settings: Settings::default(),
98 }
99}
100
101#[derive(Debug)]
109pub struct Daemon<P: Program> {
110 raw: P,
111 settings: Settings,
112}
113
114impl<P: Program> Daemon<P> {
115 pub fn run(self) -> Result
117 where
118 Self: 'static,
119 {
120 #[cfg(all(feature = "debug", not(target_arch = "wasm32")))]
121 let program = iced_devtools::attach(self.raw);
122
123 #[cfg(any(not(feature = "debug"), target_arch = "wasm32"))]
124 let program = self.raw;
125
126 Ok(shell::run(program, self.settings, None)?)
127 }
128
129 pub fn settings(self, settings: Settings) -> Self {
131 Self { settings, ..self }
132 }
133
134 pub fn antialiasing(self, antialiasing: bool) -> Self {
136 Self {
137 settings: Settings {
138 antialiasing,
139 ..self.settings
140 },
141 ..self
142 }
143 }
144
145 pub fn default_font(self, default_font: Font) -> Self {
147 Self {
148 settings: Settings {
149 default_font,
150 ..self.settings
151 },
152 ..self
153 }
154 }
155
156 pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
158 self.settings.fonts.push(font.into());
159 self
160 }
161
162 pub fn title(
164 self,
165 title: impl Title<P::State>,
166 ) -> Daemon<
167 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
168 > {
169 Daemon {
170 raw: program::with_title(self.raw, move |state, window| {
171 title.title(state, window)
172 }),
173 settings: self.settings,
174 }
175 }
176
177 pub fn subscription(
179 self,
180 f: impl Fn(&P::State) -> Subscription<P::Message>,
181 ) -> Daemon<
182 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
183 > {
184 Daemon {
185 raw: program::with_subscription(self.raw, f),
186 settings: self.settings,
187 }
188 }
189
190 pub fn theme(
192 self,
193 f: impl Fn(&P::State, window::Id) -> P::Theme,
194 ) -> Daemon<
195 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
196 > {
197 Daemon {
198 raw: program::with_theme(self.raw, f),
199 settings: self.settings,
200 }
201 }
202
203 pub fn style(
205 self,
206 f: impl Fn(&P::State, &P::Theme) -> theme::Style,
207 ) -> Daemon<
208 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
209 > {
210 Daemon {
211 raw: program::with_style(self.raw, f),
212 settings: self.settings,
213 }
214 }
215
216 pub fn scale_factor(
218 self,
219 f: impl Fn(&P::State, window::Id) -> f64,
220 ) -> Daemon<
221 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
222 > {
223 Daemon {
224 raw: program::with_scale_factor(self.raw, f),
225 settings: self.settings,
226 }
227 }
228
229 pub fn executor<E>(
231 self,
232 ) -> Daemon<
233 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
234 >
235 where
236 E: Executor,
237 {
238 Daemon {
239 raw: program::with_executor::<P, E>(self.raw),
240 settings: self.settings,
241 }
242 }
243}
244
245pub trait Title<State> {
252 fn title(&self, state: &State, window: window::Id) -> String;
254}
255
256impl<State> Title<State> for &'static str {
257 fn title(&self, _state: &State, _window: window::Id) -> String {
258 self.to_string()
259 }
260}
261
262impl<T, State> Title<State> for T
263where
264 T: Fn(&State, window::Id) -> String,
265{
266 fn title(&self, state: &State, window: window::Id) -> String {
267 self(state, window)
268 }
269}
270
271pub trait View<'a, State, Message, Theme, Renderer> {
276 fn view(
278 &self,
279 state: &'a State,
280 window: window::Id,
281 ) -> impl Into<Element<'a, Message, Theme, Renderer>>;
282}
283
284impl<'a, T, State, Message, Theme, Renderer, Widget>
285 View<'a, State, Message, Theme, Renderer> for T
286where
287 T: Fn(&'a State, window::Id) -> Widget,
288 State: 'static,
289 Widget: Into<Element<'a, Message, Theme, Renderer>>,
290{
291 fn view(
292 &self,
293 state: &'a State,
294 window: window::Id,
295 ) -> impl Into<Element<'a, Message, Theme, Renderer>> {
296 self(state, window)
297 }
298}