1use crate::application;
3use crate::program::{self, Program};
4#[cfg(feature = "winit")]
5pub use crate::shell::program::{Appearance, DefaultStyle};
6use crate::window;
7use crate::{Element, Executor, Font, Settings, Subscription, Task};
8
9#[cfg(not(feature = "winit"))]
10use crate::runtime::{Appearance, DefaultStyle};
11
12use std::borrow::Cow;
13
14pub fn daemon<State, Message, Theme, Renderer>(
25 title: impl Title<State>,
26 update: impl application::Update<State, Message>,
27 view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
28) -> Daemon<impl Program<State = State, Message = Message, Theme = Theme>>
29where
30 State: 'static,
31 Message: Send + std::fmt::Debug + 'static,
32 Theme: Default + DefaultStyle,
33 Renderer: program::Renderer,
34{
35 use std::marker::PhantomData;
36
37 struct Instance<State, Message, Theme, Renderer, Update, View> {
38 update: Update,
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, Update, View> Program
47 for Instance<State, Message, Theme, Renderer, Update, View>
48 where
49 Message: Send + std::fmt::Debug + 'static,
50 Theme: Default + DefaultStyle,
51 Renderer: program::Renderer,
52 Update: application::Update<State, Message>,
53 View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
54 {
55 type State = State;
56 type Message = Message;
57 type Theme = Theme;
58 type Renderer = Renderer;
59 type Executor = iced_futures::backend::default::Executor;
60
61 fn update(
62 &self,
63 state: &mut Self::State,
64 message: Self::Message,
65 ) -> Task<Self::Message> {
66 self.update.update(state, message).into()
67 }
68
69 fn view<'a>(
70 &self,
71 state: &'a Self::State,
72 window: window::Id,
73 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
74 self.view.view(state, window).into()
75 }
76 }
77
78 Daemon {
79 raw: Instance {
80 update,
81 view,
82 _state: PhantomData,
83 _message: PhantomData,
84 _theme: PhantomData,
85 _renderer: PhantomData,
86 },
87 settings: Settings::default(),
88 }
89 .title(title)
90}
91
92#[derive(Debug)]
100pub struct Daemon<P: Program> {
101 raw: P,
102 settings: Settings,
103}
104
105impl<P: Program> Daemon<P> {
106 #[cfg(feature = "winit")]
107 pub fn run(self) -> crate::Result
115 where
116 Self: 'static,
117 P::State: Default,
118 {
119 self.raw.run(self.settings, None)
120 }
121
122 #[cfg(feature = "winit")]
123 pub fn run_with<I>(self, initialize: I) -> crate::Result
125 where
126 Self: 'static,
127 I: FnOnce() -> (P::State, Task<P::Message>) + 'static,
128 {
129 self.raw.run_with(self.settings, None, initialize)
130 }
131
132 pub fn settings(self, settings: Settings) -> Self {
134 Self { settings, ..self }
135 }
136
137 pub fn antialiasing(self, antialiasing: bool) -> Self {
139 Self {
140 settings: Settings {
141 antialiasing,
142 ..self.settings
143 },
144 ..self
145 }
146 }
147
148 pub fn default_font(self, default_font: Font) -> Self {
150 Self {
151 settings: Settings {
152 default_font,
153 ..self.settings
154 },
155 ..self
156 }
157 }
158
159 pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
161 self.settings.fonts.push(font.into());
162 self
163 }
164
165 pub(crate) fn title(
167 self,
168 title: impl Title<P::State>,
169 ) -> Daemon<
170 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
171 > {
172 Daemon {
173 raw: program::with_title(self.raw, move |state, window| {
174 title.title(state, window)
175 }),
176 settings: self.settings,
177 }
178 }
179
180 pub fn subscription(
182 self,
183 f: impl Fn(&P::State) -> Subscription<P::Message>,
184 ) -> Daemon<
185 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
186 > {
187 Daemon {
188 raw: program::with_subscription(self.raw, f),
189 settings: self.settings,
190 }
191 }
192
193 pub fn theme(
195 self,
196 f: impl Fn(&P::State, window::Id) -> P::Theme,
197 ) -> Daemon<
198 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
199 > {
200 Daemon {
201 raw: program::with_theme(self.raw, f),
202 settings: self.settings,
203 }
204 }
205
206 pub fn style(
208 self,
209 f: impl Fn(&P::State, &P::Theme) -> Appearance,
210 ) -> Daemon<
211 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
212 > {
213 Daemon {
214 raw: program::with_style(self.raw, f),
215 settings: self.settings,
216 }
217 }
218
219 pub fn scale_factor(
221 self,
222 f: impl Fn(&P::State, window::Id) -> f64,
223 ) -> Daemon<
224 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
225 > {
226 Daemon {
227 raw: program::with_scale_factor(self.raw, f),
228 settings: self.settings,
229 }
230 }
231
232 pub fn executor<E>(
234 self,
235 ) -> Daemon<
236 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
237 >
238 where
239 E: Executor,
240 {
241 Daemon {
242 raw: program::with_executor::<P, E>(self.raw),
243 settings: self.settings,
244 }
245 }
246}
247
248pub trait Title<State> {
255 fn title(&self, state: &State, window: window::Id) -> String;
257}
258
259impl<State> Title<State> for &'static str {
260 fn title(&self, _state: &State, _window: window::Id) -> String {
261 self.to_string()
262 }
263}
264
265impl<T, State> Title<State> for T
266where
267 T: Fn(&State, window::Id) -> String,
268{
269 fn title(&self, state: &State, window: window::Id) -> String {
270 self(state, window)
271 }
272}
273
274pub trait View<'a, State, Message, Theme, Renderer> {
279 fn view(
281 &self,
282 state: &'a State,
283 window: window::Id,
284 ) -> impl Into<Element<'a, Message, Theme, Renderer>>;
285}
286
287impl<'a, T, State, Message, Theme, Renderer, Widget>
288 View<'a, State, Message, Theme, Renderer> for T
289where
290 T: Fn(&'a State, window::Id) -> Widget,
291 State: 'static,
292 Widget: Into<Element<'a, Message, Theme, Renderer>>,
293{
294 fn view(
295 &self,
296 state: &'a State,
297 window: window::Id,
298 ) -> impl Into<Element<'a, Message, Theme, Renderer>> {
299 self(state, window)
300 }
301}