From 93ae790da14544667176ecdbdd6a4eaaa98a248a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 16 Mar 2024 15:53:03 +0100 Subject: Implement `Program::load` to specify startup `Command` --- src/lib.rs | 2 +- src/program.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index f42a845e..19815f0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -362,7 +362,7 @@ pub type Result = std::result::Result<(), Error>; /// } /// ``` pub fn run( - title: &'static str, + title: impl program::Title + 'static, update: impl Fn(&mut State, Message) + 'static, view: impl for<'a> program::View<'a, State, Message> + 'static, ) -> Result diff --git a/src/program.rs b/src/program.rs index 3a16ea29..746f8f29 100644 --- a/src/program.rs +++ b/src/program.rs @@ -143,31 +143,30 @@ where /// Creates a [`Program`] that can leverage the [`Command`] API for /// concurrent operations. pub fn application( - new: impl Fn() -> (State, Command), + title: impl Title, update: impl Fn(&mut State, Message) -> Command, view: impl for<'a> self::View<'a, State, Message>, ) -> Program< impl Definition, > where - State: 'static, + State: Default + 'static, Message: Send + std::fmt::Debug, { use std::marker::PhantomData; - struct Application { - new: New, + struct Application { update: Update, view: View, _state: PhantomData, _message: PhantomData, } - impl Definition - for Application + impl Definition + for Application where + State: Default, Message: Send + std::fmt::Debug, - New: Fn() -> (State, Command), Update: Fn(&mut State, Message) -> Command, View: for<'a> self::View<'a, State, Message>, { @@ -177,7 +176,7 @@ where type Executor = executor::Default; fn build(&self) -> (Self::State, Command) { - (self.new)() + (Self::State::default(), Command::none()) } fn update( @@ -198,7 +197,6 @@ where Program { raw: Application { - new, update, view, _state: PhantomData, @@ -206,6 +204,7 @@ where }, settings: Settings::default(), } + .title(title) } /// A fully functioning and configured iced application. @@ -367,6 +366,19 @@ impl Program

{ } } + /// Runs the [`Command`] produced by the closure at startup. + pub fn load( + self, + f: impl Fn() -> Command, + ) -> Program< + impl Definition, + > { + Program { + raw: with_load(self.raw, f), + settings: self.settings, + } + } + /// Sets the subscription logic of the [`Program`]. pub fn subscription( self, @@ -500,6 +512,64 @@ fn with_title( WithTitle { program, title } } +fn with_load( + program: P, + f: impl Fn() -> Command, +) -> impl Definition { + struct WithLoad { + program: P, + load: F, + } + + impl Definition for WithLoad + where + F: Fn() -> Command, + { + type State = P::State; + type Message = P::Message; + 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 update( + &self, + state: &mut Self::State, + message: Self::Message, + ) -> Command { + self.program.update(state, message) + } + + fn view<'a>( + &self, + state: &'a Self::State, + ) -> Element<'a, Self::Message, Self::Theme> { + self.program.view(state) + } + + fn title(&self, state: &Self::State) -> String { + self.program.title(state) + } + + fn theme(&self, state: &Self::State) -> Self::Theme { + self.program.theme(state) + } + + fn subscription( + &self, + state: &Self::State, + ) -> Subscription { + self.program.subscription(state) + } + } + + WithLoad { program, load: f } +} + fn with_subscription( program: P, f: impl Fn(&P::State) -> Subscription, -- cgit