use crate::program::{self, Program};
use crate::window;
use crate::{
Element, Executor, Font, Result, Settings, Size, Subscription, Task,
};
use std::borrow::Cow;
pub use crate::shell::program::{Appearance, DefaultStyle};
pub fn application<State, Message, Theme, Renderer>(
title: impl Title<State>,
update: impl Update<State, Message>,
view: impl for<'a> self::View<'a, State, Message, Theme, Renderer>,
) -> Application<impl Program<State = State, Message = Message, Theme = Theme>>
where
State: 'static,
Message: Send + std::fmt::Debug + 'static,
Theme: Default + DefaultStyle,
Renderer: program::Renderer,
{
use std::marker::PhantomData;
struct Instance<State, Message, Theme, Renderer, Update, View> {
update: Update,
view: View,
_state: PhantomData<State>,
_message: PhantomData<Message>,
_theme: PhantomData<Theme>,
_renderer: PhantomData<Renderer>,
}
impl<State, Message, Theme, Renderer, Update, View> Program
for Instance<State, Message, Theme, Renderer, Update, View>
where
Message: Send + std::fmt::Debug + 'static,
Theme: Default + DefaultStyle,
Renderer: program::Renderer,
Update: self::Update<State, Message>,
View: for<'a> self::View<'a, State, Message, Theme, Renderer>,
{
type State = State;
type Message = Message;
type Theme = Theme;
type Renderer = Renderer;
type Executor = iced_futures::backend::default::Executor;
fn update(
&self,
state: &mut Self::State,
message: Self::Message,
) -> Task<Self::Message> {
self.update.update(state, message).into()
}
fn view<'a>(
&self,
state: &'a Self::State,
_window: window::Id,
) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
self.view.view(state).into()
}
}
Application {
raw: Instance {
update,
view,
_state: PhantomData,
_message: PhantomData,
_theme: PhantomData,
_renderer: PhantomData,
},
settings: Settings::default(),
window: window::Settings::default(),
}
.title(title)
}
#[derive(Debug)]
pub struct Application<P: Program> {
raw: P,
settings: Settings,
window: window::Settings,
}
impl<P: Program> Application<P> {
pub fn run(self) -> Result
where
Self: 'static,
P::State: Default,
{
self.raw.run(self.settings, Some(self.window))
}
pub fn run_with<I>(self, initialize: I) -> Result
where
Self: 'static,
I: FnOnce() -> (P::State, Task<P::Message>) + 'static,
{
self.raw
.run_with(self.settings, Some(self.window), initialize)
}
pub fn settings(self, settings: Settings) -> Self {
Self { settings, ..self }
}
pub fn antialiasing(self, antialiasing: bool) -> Self {
Self {
settings: Settings {
antialiasing,
..self.settings
},
..self
}
}
pub fn default_font(self, default_font: Font) -> Self {
Self {
settings: Settings {
default_font,
..self.settings
},
..self
}
}
pub fn font(mut self, font: impl Into<Cow<'static, [u8]>>) -> Self {
self.settings.fonts.push(font.into());
self
}
pub fn window(self, window: window::Settings) -> Self {
Self { window, ..self }
}
pub fn centered(self) -> Self {
Self {
window: window::Settings {
position: window::Position::Centered,
..self.window
},
..self
}
}
pub fn exit_on_close_request(self, exit_on_close_request: bool) -> Self {
Self {
window: window::Settings {
exit_on_close_request,
..self.window
},
..self
}
}
pub fn window_size(self, size: impl Into<Size>) -> Self {
Self {
window: window::Settings {
size: size.into(),
..self.window
},
..self
}
}
pub fn transparent(self, transparent: bool) -> Self {
Self {
window: window::Settings {
transparent,
..self.window
},
..self
}
}
pub fn resizable(self, resizable: bool) -> Self {
Self {
window: window::Settings {
resizable,
..self.window
},
..self
}
}
pub fn decorations(self, decorations: bool) -> Self {
Self {
window: window::Settings {
decorations,
..self.window
},
..self
}
}
pub fn position(self, position: window::Position) -> Self {
Self {
window: window::Settings {
position,
..self.window
},
..self
}
}
pub fn level(self, level: window::Level) -> Self {
Self {
window: window::Settings {
level,
..self.window
},
..self
}
}
pub(crate) fn title(
self,
title: impl Title<P::State>,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Application {
raw: program::with_title(self.raw, move |state, _window| {
title.title(state)
}),
settings: self.settings,
window: self.window,
}
}
pub fn subscription(
self,
f: impl Fn(&P::State) -> Subscription<P::Message>,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Application {
raw: program::with_subscription(self.raw, f),
settings: self.settings,
window: self.window,
}
}
pub fn theme(
self,
f: impl Fn(&P::State) -> P::Theme,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Application {
raw: program::with_theme(self.raw, move |state, _window| f(state)),
settings: self.settings,
window: self.window,
}
}
pub fn style(
self,
f: impl Fn(&P::State, &P::Theme) -> Appearance,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Application {
raw: program::with_style(self.raw, f),
settings: self.settings,
window: self.window,
}
}
pub fn scale_factor(
self,
f: impl Fn(&P::State) -> f64,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> {
Application {
raw: program::with_scale_factor(self.raw, move |state, _window| {
f(state)
}),
settings: self.settings,
window: self.window,
}
}
pub fn executor<E>(
self,
) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
>
where
E: Executor,
{
Application {
raw: program::with_executor::<P, E>(self.raw),
settings: self.settings,
window: self.window,
}
}
}
pub trait Title<State> {
fn title(&self, state: &State) -> String;
}
impl<State> Title<State> for &'static str {
fn title(&self, _state: &State) -> String {
self.to_string()
}
}
impl<T, State> Title<State> for T
where
T: Fn(&State) -> String,
{
fn title(&self, state: &State) -> String {
self(state)
}
}
pub trait Update<State, Message> {
fn update(
&self,
state: &mut State,
message: Message,
) -> impl Into<Task<Message>>;
}
impl<State, Message> Update<State, Message> for () {
fn update(
&self,
_state: &mut State,
_message: Message,
) -> impl Into<Task<Message>> {
}
}
impl<T, State, Message, C> Update<State, Message> for T
where
T: Fn(&mut State, Message) -> C,
C: Into<Task<Message>>,
{
fn update(
&self,
state: &mut State,
message: Message,
) -> impl Into<Task<Message>> {
self(state, message)
}
}
pub trait View<'a, State, Message, Theme, Renderer> {
fn view(
&self,
state: &'a State,
) -> impl Into<Element<'a, Message, Theme, Renderer>>;
}
impl<'a, T, State, Message, Theme, Renderer, Widget>
View<'a, State, Message, Theme, Renderer> for T
where
T: Fn(&'a State) -> Widget,
State: 'static,
Widget: Into<Element<'a, Message, Theme, Renderer>>,
{
fn view(
&self,
state: &'a State,
) -> impl Into<Element<'a, Message, Theme, Renderer>> {
self(state)
}
}