Introduce Program::run_with to control the initial state

This commit is contained in:
Héctor Ramón Jiménez 2024-03-17 19:15:31 +01:00
parent 92f8dddc2c
commit 943b6c9657
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 60 additions and 37 deletions

View file

@ -21,19 +21,13 @@ pub fn main() -> iced::Result {
.run()
}
#[derive(Default)]
pub struct Tour {
steps: Steps,
debug: bool,
}
impl Tour {
fn new() -> Self {
Self {
steps: Steps::new(),
debug: false,
}
}
fn title(&self) -> String {
format!("{} - Iced", self.steps.title())
}
@ -90,12 +84,6 @@ impl Tour {
}
}
impl Default for Tour {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub enum Message {
BackPressed,
@ -177,6 +165,12 @@ impl Steps {
}
}
impl Default for Steps {
fn default() -> Self {
Steps::new()
}
}
enum Step {
Welcome,
Slider {

View file

@ -70,7 +70,7 @@ pub fn program<State, Message, Theme>(
view: impl for<'a> self::View<'a, State, Message, Theme>,
) -> Program<impl Definition<State = State, Message = Message, Theme = Theme>>
where
State: Default + 'static,
State: 'static,
Message: Send + std::fmt::Debug,
Theme: Default + application::DefaultStyle,
{
@ -87,7 +87,6 @@ where
impl<State, Message, Theme, Update, View> Definition
for Application<State, Message, Theme, Update, View>
where
State: Default,
Message: Send + std::fmt::Debug,
Theme: Default + application::DefaultStyle,
Update: self::Update<State, Message>,
@ -98,8 +97,8 @@ where
type Theme = Theme;
type Executor = executor::Default;
fn build(&self) -> (Self::State, Command<Self::Message>) {
(Self::State::default(), Command::none())
fn load(&self) -> Command<Self::Message> {
Command::none()
}
fn update(
@ -151,25 +150,57 @@ pub struct Program<P: Definition> {
impl<P: Definition> Program<P> {
/// Runs the underlying [`Application`] of the [`Program`].
///
/// The state of the [`Program`] must implement [`Default`].
/// If your state does not implement [`Default`], use [`run_with`]
/// instead.
///
/// [`run_with`]: Self::run_with
pub fn run(self) -> Result
where
Self: 'static,
P::State: Default,
{
struct Instance<P: Definition> {
self.run_with(P::State::default)
}
/// Runs the underlying [`Application`] of the [`Program`] with a
/// closure that creates the initial state.
pub fn run_with(
self,
initialize: impl Fn() -> P::State + Clone + 'static,
) -> Result
where
Self: 'static,
{
use std::marker::PhantomData;
struct Instance<P: Definition, I> {
program: P,
state: P::State,
_initialize: PhantomData<I>,
}
impl<P: Definition> Application for Instance<P> {
impl<P: Definition, I: Fn() -> P::State> Application for Instance<P, I> {
type Message = P::Message;
type Theme = P::Theme;
type Flags = P;
type Flags = (P, I);
type Executor = P::Executor;
fn new(program: Self::Flags) -> (Self, Command<Self::Message>) {
let (state, command) = P::build(&program);
fn new(
(program, initialize): Self::Flags,
) -> (Self, Command<Self::Message>) {
let state = initialize();
let command = program.load();
(Self { program, state }, command)
(
Self {
program,
state,
_initialize: PhantomData,
},
command,
)
}
fn title(&self) -> String {
@ -206,7 +237,7 @@ impl<P: Definition> Program<P> {
let Self { raw, settings } = self;
Instance::run(Settings {
flags: raw,
flags: (raw, initialize),
id: settings.id,
window: settings.window,
fonts: settings.fonts,
@ -389,7 +420,7 @@ pub trait Definition: Sized {
/// The executor of the program.
type Executor: Executor;
fn build(&self) -> (Self::State, Command<Self::Message>);
fn load(&self) -> Command<Self::Message>;
fn update(
&self,
@ -445,8 +476,8 @@ fn with_title<P: Definition>(
type Theme = P::Theme;
type Executor = P::Executor;
fn build(&self) -> (Self::State, Command<Self::Message>) {
self.program.build()
fn load(&self) -> Command<Self::Message> {
self.program.load()
}
fn title(&self, state: &Self::State) -> String {
@ -509,10 +540,8 @@ fn with_load<P: Definition>(
type Theme = P::Theme;
type Executor = executor::Default;
fn build(&self) -> (Self::State, Command<Self::Message>) {
let (state, command) = self.program.build();
(state, Command::batch([command, (self.load)()]))
fn load(&self) -> Command<Self::Message> {
Command::batch([self.program.load(), (self.load)()])
}
fn update(
@ -582,8 +611,8 @@ fn with_subscription<P: Definition>(
(self.subscription)(state)
}
fn build(&self) -> (Self::State, Command<Self::Message>) {
self.program.build()
fn load(&self) -> Command<Self::Message> {
self.program.load()
}
fn update(
@ -646,8 +675,8 @@ fn with_theme<P: Definition>(
(self.theme)(state)
}
fn build(&self) -> (Self::State, Command<Self::Message>) {
self.program.build()
fn load(&self) -> Command<Self::Message> {
self.program.load()
}
fn title(&self, state: &Self::State) -> String {
@ -714,8 +743,8 @@ fn with_style<P: Definition>(
(self.style)(state, theme)
}
fn build(&self) -> (Self::State, Command<Self::Message>) {
self.program.build()
fn load(&self) -> Command<Self::Message> {
self.program.load()
}
fn title(&self, state: &Self::State) -> String {