1use crate::program::{self, Program};
34use crate::shell;
35use crate::theme;
36use crate::window;
37use crate::{
38 Element, Executor, Font, Result, Settings, Size, Subscription, Task,
39};
40
41use std::borrow::Cow;
42
43pub fn application<State, Message, Theme, Renderer>(
72 boot: impl Boot<State, Message>,
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 + theme::Base,
80 Renderer: program::Renderer,
81{
82 use std::marker::PhantomData;
83
84 struct Instance<State, Message, Theme, Renderer, Boot, Update, View> {
85 boot: Boot,
86 update: Update,
87 view: View,
88 _state: PhantomData<State>,
89 _message: PhantomData<Message>,
90 _theme: PhantomData<Theme>,
91 _renderer: PhantomData<Renderer>,
92 }
93
94 impl<State, Message, Theme, Renderer, Boot, Update, View> Program
95 for Instance<State, Message, Theme, Renderer, Boot, Update, View>
96 where
97 Message: Send + std::fmt::Debug + 'static,
98 Theme: Default + theme::Base,
99 Renderer: program::Renderer,
100 Boot: self::Boot<State, Message>,
101 Update: self::Update<State, Message>,
102 View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
103 {
104 type State = State;
105 type Message = Message;
106 type Theme = Theme;
107 type Renderer = Renderer;
108 type Executor = iced_futures::backend::default::Executor;
109
110 fn name() -> &'static str {
111 let name = std::any::type_name::<State>();
112
113 name.split("::").next().unwrap_or("a_cool_application")
114 }
115
116 fn boot(&self) -> (State, Task<Message>) {
117 self.boot.boot()
118 }
119
120 fn update(
121 &self,
122 state: &mut Self::State,
123 message: Self::Message,
124 ) -> Task<Self::Message> {
125 self.update.update(state, message).into()
126 }
127
128 fn view<'a>(
129 &self,
130 state: &'a Self::State,
131 _window: window::Id,
132 ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
133 self.view.view(state).into()
134 }
135 }
136
137 Application {
138 raw: Instance {
139 boot,
140 update,
141 view,
142 _state: PhantomData,
143 _message: PhantomData,
144 _theme: PhantomData,
145 _renderer: PhantomData,
146 },
147 settings: Settings::default(),
148 window: window::Settings::default(),
149 }
150}
151
152#[derive(Debug)]
160pub struct Application<P: Program> {
161 raw: P,
162 settings: Settings,
163 window: window::Settings,
164}
165
166impl<P: Program> Application<P> {
167 pub fn run(self) -> Result
169 where
170 Self: 'static,
171 {
172 #[cfg(all(feature = "debug", not(target_arch = "wasm32")))]
173 let program = iced_devtools::attach(self.raw);
174
175 #[cfg(any(not(feature = "debug"), target_arch = "wasm32"))]
176 let program = self.raw;
177
178 Ok(shell::run(program, self.settings, Some(self.window))?)
179 }
180
181 pub fn settings(self, settings: Settings) -> Self {
183 Self { settings, ..self }
184 }
185
186 pub fn antialiasing(self, antialiasing: bool) -> Self {
188 Self {
189 settings: Settings {
190 antialiasing,
191 ..self.settings
192 },
193 ..self
194 }
195 }
196
197 pub fn default_font(self, default_font: Font) -> Self {
199 Self {
200 settings: Settings {
201 default_font,
202 ..self.settings
203 },
204 ..self
205 }
206 }
207
208 pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
210 self.settings.fonts.push(font.into());
211 self
212 }
213
214 pub fn window(self, window: window::Settings) -> Self {
218 Self { window, ..self }
219 }
220
221 pub fn centered(self) -> Self {
223 Self {
224 window: window::Settings {
225 position: window::Position::Centered,
226 ..self.window
227 },
228 ..self
229 }
230 }
231
232 pub fn exit_on_close_request(self, exit_on_close_request: bool) -> Self {
234 Self {
235 window: window::Settings {
236 exit_on_close_request,
237 ..self.window
238 },
239 ..self
240 }
241 }
242
243 pub fn window_size(self, size: impl Into<Size>) -> Self {
245 Self {
246 window: window::Settings {
247 size: size.into(),
248 ..self.window
249 },
250 ..self
251 }
252 }
253
254 pub fn transparent(self, transparent: bool) -> Self {
256 Self {
257 window: window::Settings {
258 transparent,
259 ..self.window
260 },
261 ..self
262 }
263 }
264
265 pub fn resizable(self, resizable: bool) -> Self {
267 Self {
268 window: window::Settings {
269 resizable,
270 ..self.window
271 },
272 ..self
273 }
274 }
275
276 pub fn decorations(self, decorations: bool) -> Self {
278 Self {
279 window: window::Settings {
280 decorations,
281 ..self.window
282 },
283 ..self
284 }
285 }
286
287 pub fn position(self, position: window::Position) -> Self {
289 Self {
290 window: window::Settings {
291 position,
292 ..self.window
293 },
294 ..self
295 }
296 }
297
298 pub fn level(self, level: window::Level) -> Self {
300 Self {
301 window: window::Settings {
302 level,
303 ..self.window
304 },
305 ..self
306 }
307 }
308
309 pub fn title(
311 self,
312 title: impl Title<P::State>,
313 ) -> Application<
314 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
315 > {
316 Application {
317 raw: program::with_title(self.raw, move |state, _window| {
318 title.title(state)
319 }),
320 settings: self.settings,
321 window: self.window,
322 }
323 }
324
325 pub fn subscription(
327 self,
328 f: impl Fn(&P::State) -> Subscription<P::Message>,
329 ) -> Application<
330 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
331 > {
332 Application {
333 raw: program::with_subscription(self.raw, f),
334 settings: self.settings,
335 window: self.window,
336 }
337 }
338
339 pub fn theme(
341 self,
342 f: impl Fn(&P::State) -> P::Theme,
343 ) -> Application<
344 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
345 > {
346 Application {
347 raw: program::with_theme(self.raw, move |state, _window| f(state)),
348 settings: self.settings,
349 window: self.window,
350 }
351 }
352
353 pub fn style(
355 self,
356 f: impl Fn(&P::State, &P::Theme) -> theme::Style,
357 ) -> Application<
358 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
359 > {
360 Application {
361 raw: program::with_style(self.raw, f),
362 settings: self.settings,
363 window: self.window,
364 }
365 }
366
367 pub fn scale_factor(
369 self,
370 f: impl Fn(&P::State) -> f64,
371 ) -> Application<
372 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
373 > {
374 Application {
375 raw: program::with_scale_factor(self.raw, move |state, _window| {
376 f(state)
377 }),
378 settings: self.settings,
379 window: self.window,
380 }
381 }
382
383 pub fn executor<E>(
385 self,
386 ) -> Application<
387 impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
388 >
389 where
390 E: Executor,
391 {
392 Application {
393 raw: program::with_executor::<P, E>(self.raw),
394 settings: self.settings,
395 window: self.window,
396 }
397 }
398}
399
400pub trait Boot<State, Message> {
409 fn boot(&self) -> (State, Task<Message>);
411}
412
413impl<T, C, State, Message> Boot<State, Message> for T
414where
415 T: Fn() -> C,
416 C: IntoBoot<State, Message>,
417{
418 fn boot(&self) -> (State, Task<Message>) {
419 self().into_boot()
420 }
421}
422
423pub trait IntoBoot<State, Message> {
425 fn into_boot(self) -> (State, Task<Message>);
427}
428
429impl<State, Message> IntoBoot<State, Message> for State {
430 fn into_boot(self) -> (State, Task<Message>) {
431 (self, Task::none())
432 }
433}
434
435impl<State, Message> IntoBoot<State, Message> for (State, Task<Message>) {
436 fn into_boot(self) -> (State, Task<Message>) {
437 self
438 }
439}
440
441pub trait Title<State> {
448 fn title(&self, state: &State) -> String;
450}
451
452impl<State> Title<State> for &'static str {
453 fn title(&self, _state: &State) -> String {
454 self.to_string()
455 }
456}
457
458impl<T, State> Title<State> for T
459where
460 T: Fn(&State) -> String,
461{
462 fn title(&self, state: &State) -> String {
463 self(state)
464 }
465}
466
467pub trait Update<State, Message> {
472 fn update(
474 &self,
475 state: &mut State,
476 message: Message,
477 ) -> impl Into<Task<Message>>;
478}
479
480impl<State, Message> Update<State, Message> for () {
481 fn update(
482 &self,
483 _state: &mut State,
484 _message: Message,
485 ) -> impl Into<Task<Message>> {
486 }
487}
488
489impl<T, State, Message, C> Update<State, Message> for T
490where
491 T: Fn(&mut State, Message) -> C,
492 C: Into<Task<Message>>,
493{
494 fn update(
495 &self,
496 state: &mut State,
497 message: Message,
498 ) -> impl Into<Task<Message>> {
499 self(state, message)
500 }
501}
502
503pub trait View<'a, State, Message, Theme, Renderer> {
508 fn view(
510 &self,
511 state: &'a State,
512 ) -> impl Into<Element<'a, Message, Theme, Renderer>>;
513}
514
515impl<'a, T, State, Message, Theme, Renderer, Widget>
516 View<'a, State, Message, Theme, Renderer> for T
517where
518 T: Fn(&'a State) -> Widget,
519 State: 'static,
520 Widget: Into<Element<'a, Message, Theme, Renderer>>,
521{
522 fn view(
523 &self,
524 state: &'a State,
525 ) -> impl Into<Element<'a, Message, Theme, Renderer>> {
526 self(state)
527 }
528}