From 943b6c965773748f8cacaa4fe385ac4a3bfb1e69 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 17 Mar 2024 19:15:31 +0100 Subject: Introduce `Program::run_with` to control the initial state --- src/application/program.rs | 79 +++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/application/program.rs b/src/application/program.rs index 2e77678e..be635431 100644 --- a/src/application/program.rs +++ b/src/application/program.rs @@ -70,7 +70,7 @@ pub fn program( view: impl for<'a> self::View<'a, State, Message, Theme>, ) -> Program> where - State: Default + 'static, + State: 'static, Message: Send + std::fmt::Debug, Theme: Default + application::DefaultStyle, { @@ -87,7 +87,6 @@ where impl Definition for Application where - State: Default, Message: Send + std::fmt::Debug, Theme: Default + application::DefaultStyle, Update: self::Update, @@ -98,8 +97,8 @@ where type Theme = Theme; type Executor = executor::Default; - fn build(&self) -> (Self::State, Command) { - (Self::State::default(), Command::none()) + fn load(&self) -> Command { + Command::none() } fn update( @@ -151,25 +150,57 @@ pub struct Program { impl Program

{ /// 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, + { + 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, { - struct Instance { + use std::marker::PhantomData; + + struct Instance { program: P, state: P::State, + _initialize: PhantomData, } - impl Application for Instance

{ + impl P::State> Application for Instance { 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) { - let (state, command) = P::build(&program); - - (Self { program, state }, command) + fn new( + (program, initialize): Self::Flags, + ) -> (Self, Command) { + let state = initialize(); + let command = program.load(); + + ( + Self { + program, + state, + _initialize: PhantomData, + }, + command, + ) } fn title(&self) -> String { @@ -206,7 +237,7 @@ impl Program

{ 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); + fn load(&self) -> Command; fn update( &self, @@ -445,8 +476,8 @@ fn with_title( type Theme = P::Theme; type Executor = P::Executor; - fn build(&self) -> (Self::State, Command) { - self.program.build() + fn load(&self) -> Command { + self.program.load() } fn title(&self, state: &Self::State) -> String { @@ -509,10 +540,8 @@ fn with_load( type Theme = P::Theme; type Executor = executor::Default; - fn build(&self) -> (Self::State, Command) { - let (state, command) = self.program.build(); - - (state, Command::batch([command, (self.load)()])) + fn load(&self) -> Command { + Command::batch([self.program.load(), (self.load)()]) } fn update( @@ -582,8 +611,8 @@ fn with_subscription( (self.subscription)(state) } - fn build(&self) -> (Self::State, Command) { - self.program.build() + fn load(&self) -> Command { + self.program.load() } fn update( @@ -646,8 +675,8 @@ fn with_theme( (self.theme)(state) } - fn build(&self) -> (Self::State, Command) { - self.program.build() + fn load(&self) -> Command { + self.program.load() } fn title(&self, state: &Self::State) -> String { @@ -714,8 +743,8 @@ fn with_style( (self.style)(state, theme) } - fn build(&self) -> (Self::State, Command) { - self.program.build() + fn load(&self) -> Command { + self.program.load() } fn title(&self, state: &Self::State) -> String { -- cgit