use crate::application::{Application, BootFn, ViewFn};
use crate::program;
use crate::theme;
use crate::time::Instant;
use crate::window;
use crate::{Element, Program, Settings, Subscription, Task};
use iced_debug as debug;
pub fn timed<State, Message, Theme, Renderer>(
boot: impl BootFn<State, Message>,
update: impl UpdateFn<State, Message>,
subscription: impl Fn(&State) -> Subscription<Message>,
view: impl for<'a> ViewFn<'a, State, Message, Theme, Renderer>,
) -> Application<
impl Program<State = State, Message = (Message, Instant), Theme = Theme>,
>
where
State: 'static,
Message: Send + 'static,
Theme: theme::Base + 'static,
Renderer: program::Renderer + 'static,
{
use std::marker::PhantomData;
struct Instance<
State,
Message,
Theme,
Renderer,
Boot,
Update,
Subscription,
View,
> {
boot: Boot,
update: Update,
subscription: Subscription,
view: View,
_state: PhantomData<State>,
_message: PhantomData<Message>,
_theme: PhantomData<Theme>,
_renderer: PhantomData<Renderer>,
}
impl<State, Message, Theme, Renderer, Boot, Update, Subscription, View>
Program
for Instance<
State,
Message,
Theme,
Renderer,
Boot,
Update,
Subscription,
View,
>
where
Message: Send + 'static,
Theme: theme::Base + 'static,
Renderer: program::Renderer + 'static,
Boot: self::BootFn<State, Message>,
Update: self::UpdateFn<State, Message>,
Subscription: Fn(&State) -> self::Subscription<Message>,
View: for<'a> self::ViewFn<'a, State, Message, Theme, Renderer>,
{
type State = State;
type Message = (Message, Instant);
type Theme = Theme;
type Renderer = Renderer;
type Executor = iced_futures::backend::default::Executor;
fn name() -> &'static str {
let name = std::any::type_name::<State>();
name.split("::").next().unwrap_or("a_cool_application")
}
fn settings(&self) -> Settings {
Settings::default()
}
fn window(&self) -> Option<iced_core::window::Settings> {
Some(window::Settings::default())
}
fn boot(&self) -> (State, Task<Self::Message>) {
let (state, task) = self.boot.boot();
(state, task.map(|message| (message, Instant::now())))
}
fn update(
&self,
state: &mut Self::State,
(message, now): Self::Message,
) -> Task<Self::Message> {
debug::hot(move || {
self.update
.update(state, message, now)
.into()
.map(|message| (message, Instant::now()))
})
}
fn view<'a>(
&self,
state: &'a Self::State,
_window: window::Id,
) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
debug::hot(|| {
self.view
.view(state)
.map(|message| (message, Instant::now()))
})
}
fn subscription(
&self,
state: &Self::State,
) -> self::Subscription<Self::Message> {
debug::hot(|| {
(self.subscription)(state)
.map(|message| (message, Instant::now()))
})
}
}
Application {
raw: Instance {
boot,
update,
subscription,
view,
_state: PhantomData,
_message: PhantomData,
_theme: PhantomData,
_renderer: PhantomData,
},
settings: Settings::default(),
window: window::Settings::default(),
presets: Vec::new(),
}
}
pub trait UpdateFn<State, Message> {
fn update(
&self,
state: &mut State,
message: Message,
now: Instant,
) -> impl Into<Task<Message>>;
}
impl<State, Message> UpdateFn<State, Message> for () {
fn update(
&self,
_state: &mut State,
_message: Message,
_now: Instant,
) -> impl Into<Task<Message>> {
}
}
impl<T, State, Message, C> UpdateFn<State, Message> for T
where
T: Fn(&mut State, Message, Instant) -> C,
C: Into<Task<Message>>,
{
fn update(
&self,
state: &mut State,
message: Message,
now: Instant,
) -> impl Into<Task<Message>> {
self(state, message, now)
}
}