diff options
| author | 2021-09-01 19:21:49 +0700 | |
|---|---|---|
| committer | 2021-09-02 13:29:34 +0700 | |
| commit | 76698ff2b5753e637b14533650c0d28e681be3c5 (patch) | |
| tree | 6b3376df6ac84598b03f2885598b7908e993fe4a /native/src/command | |
| parent | b7b7741578257bbf6a8b873c360182e2c9b920ab (diff) | |
| download | iced-76698ff2b5753e637b14533650c0d28e681be3c5.tar.gz iced-76698ff2b5753e637b14533650c0d28e681be3c5.tar.bz2 iced-76698ff2b5753e637b14533650c0d28e681be3c5.zip  | |
Make `Command` implementations platform-specific
This allows us to introduce a platform-specific `Action` to both `iced_native`
and `iced_web` and remove the `Clipboard` from `Application::update` to maintain
purity.
Additionally, this should let us implement further actions to let users query
and modify the shell environment (e.g. window, clipboard, and more!)
Diffstat (limited to '')
| -rw-r--r-- | native/src/command.rs | 77 | ||||
| -rw-r--r-- | native/src/command/action.rs | 24 | 
2 files changed, 101 insertions, 0 deletions
diff --git a/native/src/command.rs b/native/src/command.rs new file mode 100644 index 00000000..16fd73ba --- /dev/null +++ b/native/src/command.rs @@ -0,0 +1,77 @@ +mod action; + +pub use action::Action; + +use std::future::Future; + +/// A set of asynchronous actions to be performed by some runtime. +pub enum Command<T> { +    None, +    Single(Action<T>), +    Batch(Vec<Action<T>>), +} + +impl<T> Command<T> { +    /// Creates an empty [`Command`]. +    /// +    /// In other words, a [`Command`] that does nothing. +    pub fn none() -> Self { +        Self::None +    } + +    /// Creates a [`Command`] that performs the action of the given future. +    pub fn perform<A>( +        future: impl Future<Output = T> + 'static + Send, +        f: impl Fn(T) -> A + 'static + Send, +    ) -> Command<A> { +        use iced_futures::futures::FutureExt; + +        Command::Single(Action::Future(Box::pin(future.map(f)))) +    } + +    /// Applies a transformation to the result of a [`Command`]. +    pub fn map<A>( +        self, +        f: impl Fn(T) -> A + 'static + Send + Sync + Clone, +    ) -> Command<A> +    where +        T: 'static, +    { +        match self { +            Self::None => Command::None, +            Self::Single(action) => Command::Single(action.map(f)), +            Self::Batch(batch) => Command::Batch( +                batch +                    .into_iter() +                    .map(|action| action.map(f.clone())) +                    .collect(), +            ), +        } +    } + +    /// Creates a [`Command`] that performs the actions of all the given +    /// commands. +    /// +    /// Once this command is run, all the commands will be executed at once. +    pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { +        let mut batch = Vec::new(); + +        for command in commands { +            match command { +                Self::None => {} +                Self::Single(command) => batch.push(command), +                Self::Batch(commands) => batch.extend(commands), +            } +        } + +        Self::Batch(batch) +    } + +    pub fn actions(self) -> Vec<Action<T>> { +        match self { +            Self::None => Vec::new(), +            Self::Single(action) => vec![action], +            Self::Batch(batch) => batch, +        } +    } +} diff --git a/native/src/command/action.rs b/native/src/command/action.rs new file mode 100644 index 00000000..23d6e96e --- /dev/null +++ b/native/src/command/action.rs @@ -0,0 +1,24 @@ +use crate::clipboard; +use crate::window; + +pub enum Action<T> { +    Future(iced_futures::BoxFuture<T>), +    Clipboard(clipboard::Action<T>), +    Window(window::Action), +} + +impl<T> Action<T> { +    /// Applies a transformation to the result of a [`Command`]. +    pub fn map<A>(self, f: impl Fn(T) -> A + 'static + Send + Sync) -> Action<A> +    where +        T: 'static, +    { +        use iced_futures::futures::FutureExt; + +        match self { +            Self::Future(future) => Action::Future(Box::pin(future.map(f))), +            Self::Clipboard(action) => Action::Clipboard(action.map(f)), +            Self::Window(window) => Action::Window(window), +        } +    } +}  | 
