1use crate::program::{self, Program};
34#[cfg(not(feature = "winit"))]
35use crate::runtime::{Appearance, DefaultStyle};
36#[cfg(feature = "winit")]
37pub use crate::shell::program::{Appearance, DefaultStyle};
38use crate::window;
39use crate::{Element, Executor, Font, Settings, Size, Subscription, Task};
40
41use std::borrow::Cow;
42
43pub fn application<State, Message, Theme, Renderer>(
72 title: impl Title<State>,
73 update: impl Update<State, Message>,
74 view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
75) -> Application<impl Program<State = State, Message = Message, Theme = Theme>>
76where
77 State: 'static,
78 Message: Send + std::fmt::Debug + 'static,
79 Theme: Default + DefaultStyle,
80 Renderer: program::Renderer,
81{
82 use std::marker::PhantomData;
83
84 struct Instance<State, Message, Theme, Renderer, Update, View> {
85 update: Update,
86 view: View,
87 _state: PhantomData<State>,
88 _message: PhantomData<Message>,
89 _theme: PhantomData<Theme>,
90 _renderer: PhantomData<Renderer>,
91 }
92
93 impl<State, Message, Theme, Renderer, Update, View> Program
94 for Instance<State, Message, Theme, Renderer, Update, View>
95 where
96 Message: Send + std::fmt::Debug + 'static,
97 Theme: Default + DefaultStyle,
98 Renderer: program::Renderer,
99 Update: self::Update<State, Message>,
100 View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
101 {
102 type State = State;
103 type Message = Message;
104 type Theme = Theme;
105 type Renderer = Renderer;
106 type Executor = iced_futures::backend::default::Executor;
107
108 fn update(
109 &self,
110 state: &mut Self::State,
111 message: Self::Message,
112 ) -> Task<Self::Message> {
113 self.update.update(state, message).into()
114 }
115
116 fn view<'a>(
117 &self,
118 state: &'a Self::State,
119 _window: window::Id,
120 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
121 self.view.view(state).into()
122 }
123 }
124
125 Application {
126 raw: Instance {
127 update,
128 view,
129 _state: PhantomData,
130 _message: PhantomData,
131 _theme: PhantomData,
132 _renderer: PhantomData,
133 },
134 settings: Settings::default(),
135 window: window::Settings::default(),
136 }
137 .title(title)
138}
139
140#[derive(Debug)]
148pub struct Application<P: Program> {
149 raw: P,
150 settings: Settings,
151 window: window::Settings,
152}
153
154impl<P: Program> Application<P> {
155 #[cfg(feature = "winit")]
156 pub fn run(self) -> crate::Result
164 where
165 Self: 'static,
166 P::State: Default,
167 {
168 self.raw.run(self.settings, Some(self.window))
169 }
170
171 #[cfg(feature = "winit")]
172 pub fn run_with<I>(self, initialize: I) -> crate::Result
174 where
175 Self: 'static,
176 I: FnOnce() -> (P::State, Task<P::Message>) + 'static,
177 {
178 self.raw
179 .run_with(self.settings, Some(self.window), initialize)
180 }
181
182 pub fn settings(self, settings: Settings) -> Self {
184 Self { settings, ..self }
185 }
186
187 pub fn antialiasing(self, antialiasing: bool) -> Self {
189 Self {
190 settings: Settings {
191 antialiasing,
192 ..self.settings
193 },
194 ..self
195 }
196 }
197
198 pub fn default_font(self, default_font: Font) -> Self {
200 Self {
201 settings: Settings {
202 default_font,
203 ..self.settings
204 },
205 ..self
206 }
207 }
208
209 pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
211 self.settings.fonts.push(font.into());
212 self
213 }
214
215 pub fn window(self, window: window::Settings) -> Self {
219 Self { window, ..self }
220 }
221
222 pub fn centered(self) -> Self {
224 Self {
225 window: window::Settings {
226 position: window::Position::Centered,
227 ..self.window
228 },
229 ..self
230 }
231 }
232
233 pub fn exit_on_close_request(self, exit_on_close_request: bool) -> Self {
235 Self {
236 window: window::Settings {
237 exit_on_close_request,
238 ..self.window
239 },
240 ..self
241 }
242 }
243
244 pub fn window_size(self, size: impl Into<Size>) -> Self {
246 Self {
247 window: window::Settings {
248 size: size.into(),
249 ..self.window
250 },
251 ..self
252 }
253 }
254
255 pub fn transparent(self, transparent: bool) -> Self {
257 Self {
258 window: window::Settings {
259 transparent,
260 ..self.window
261 },
262 ..self
263 }
264 }
265
266 pub fn resizable(self, resizable: bool) -> Self {
268 Self {
269 window: window::Settings {
270 resizable,
271 ..self.window
272 },
273 ..self
274 }
275 }
276
277 pub fn decorations(self, decorations: bool) -> Self {
279 Self {
280 window: window::Settings {
281 decorations,
282 ..self.window
283 },
284 ..self
285 }
286 }
287
288 pub fn position(self, position: window::Position) -> Self {
290 Self {
291 window: window::Settings {
292 position,
293 ..self.window
294 },
295 ..self
296 }
297 }
298
299 pub fn level(self, level: window::Level) -> Self {
301 Self {
302 window: window::Settings {
303 level,
304 ..self.window
305 },
306 ..self
307 }
308 }
309
310 pub(crate) fn title(
312 self,
313 title: impl Title<P::State>,
314 ) -> Application<
315 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
316 > {
317 Application {
318 raw: program::with_title(self.raw, move |state, _window| {
319 title.title(state)
320 }),
321 settings: self.settings,
322 window: self.window,
323 }
324 }
325
326 pub fn subscription(
328 self,
329 f: impl Fn(&P::State) -> Subscription<P::Message>,
330 ) -> Application<
331 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
332 > {
333 Application {
334 raw: program::with_subscription(self.raw, f),
335 settings: self.settings,
336 window: self.window,
337 }
338 }
339
340 pub fn theme(
342 self,
343 f: impl Fn(&P::State) -> P::Theme,
344 ) -> Application<
345 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
346 > {
347 Application {
348 raw: program::with_theme(self.raw, move |state, _window| f(state)),
349 settings: self.settings,
350 window: self.window,
351 }
352 }
353
354 pub fn style(
356 self,
357 f: impl Fn(&P::State, &P::Theme) -> Appearance,
358 ) -> Application<
359 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
360 > {
361 Application {
362 raw: program::with_style(self.raw, f),
363 settings: self.settings,
364 window: self.window,
365 }
366 }
367
368 pub fn scale_factor(
370 self,
371 f: impl Fn(&P::State) -> f64,
372 ) -> Application<
373 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
374 > {
375 Application {
376 raw: program::with_scale_factor(self.raw, move |state, _window| {
377 f(state)
378 }),
379 settings: self.settings,
380 window: self.window,
381 }
382 }
383
384 pub fn executor<E>(
386 self,
387 ) -> Application<
388 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
389 >
390 where
391 E: Executor,
392 {
393 Application {
394 raw: program::with_executor::<P, E>(self.raw),
395 settings: self.settings,
396 window: self.window,
397 }
398 }
399}
400
401pub trait Title<State> {
408 fn title(&self, state: &State) -> String;
410}
411
412impl<State> Title<State> for &'static str {
413 fn title(&self, _state: &State) -> String {
414 self.to_string()
415 }
416}
417
418impl<T, State> Title<State> for T
419where
420 T: Fn(&State) -> String,
421{
422 fn title(&self, state: &State) -> String {
423 self(state)
424 }
425}
426
427pub trait Update<State, Message> {
432 fn update(
434 &self,
435 state: &mut State,
436 message: Message,
437 ) -> impl Into<Task<Message>>;
438}
439
440impl<State, Message> Update<State, Message> for () {
441 fn update(
442 &self,
443 _state: &mut State,
444 _message: Message,
445 ) -> impl Into<Task<Message>> {
446 }
447}
448
449impl<T, State, Message, C> Update<State, Message> for T
450where
451 T: Fn(&mut State, Message) -> C,
452 C: Into<Task<Message>>,
453{
454 fn update(
455 &self,
456 state: &mut State,
457 message: Message,
458 ) -> impl Into<Task<Message>> {
459 self(state, message)
460 }
461}
462
463pub trait View<'a, State, Message, Theme, Renderer> {
468 fn view(
470 &self,
471 state: &'a State,
472 ) -> impl Into<Element<'a, Message, Theme, Renderer>>;
473}
474
475impl<'a, T, State, Message, Theme, Renderer, Widget>
476 View<'a, State, Message, Theme, Renderer> for T
477where
478 T: Fn(&'a State) -> Widget,
479 State: 'static,
480 Widget: Into<Element<'a, Message, Theme, Renderer>>,
481{
482 fn view(
483 &self,
484 state: &'a State,
485 ) -> impl Into<Element<'a, Message, Theme, Renderer>> {
486 self(state)
487 }
488}