diff options
| author | 2021-09-13 11:49:06 +0700 | |
|---|---|---|
| committer | 2021-09-13 11:49:06 +0700 | |
| commit | 93fec8d273ef8305e1c2456abe0c8ecd7a9d9407 (patch) | |
| tree | c0c2445703133293b13657ab4f9c1c936e9cd688 /web/src | |
| parent | 589f68df0f647d93f2b9dd7bf29cfacb0201351c (diff) | |
| parent | 01b945b9814b9dc546e783a6dab66e4f7fe49786 (diff) | |
| download | iced-93fec8d273ef8305e1c2456abe0c8ecd7a9d9407.tar.gz iced-93fec8d273ef8305e1c2456abe0c8ecd7a9d9407.tar.bz2 iced-93fec8d273ef8305e1c2456abe0c8ecd7a9d9407.zip | |
Merge pull request #1019 from hecrj/command-actions
Platform-specific `Command` implementations
Diffstat (limited to 'web/src')
| -rw-r--r-- | web/src/clipboard.rs | 21 | ||||
| -rw-r--r-- | web/src/command.rs | 72 | ||||
| -rw-r--r-- | web/src/command/action.rs | 28 | ||||
| -rw-r--r-- | web/src/lib.rs | 45 | 
4 files changed, 128 insertions, 38 deletions
| diff --git a/web/src/clipboard.rs b/web/src/clipboard.rs deleted file mode 100644 index 167a1e53..00000000 --- a/web/src/clipboard.rs +++ /dev/null @@ -1,21 +0,0 @@ -/// A buffer for short-term storage and transfer within and between -/// applications. -#[derive(Debug, Clone, Copy)] -pub struct Clipboard; - -impl Clipboard { -    /// Creates a new [`Clipboard`]. -    pub fn new() -> Self { -        Self -    } - -    /// Reads the current content of the [`Clipboard`] as text. -    pub fn read(&self) -> Option<String> { -        unimplemented! {} -    } - -    /// Writes the given text contents to the [`Clipboard`]. -    pub fn write(&mut self, _contents: String) { -        unimplemented! {} -    } -} diff --git a/web/src/command.rs b/web/src/command.rs new file mode 100644 index 00000000..33e49e70 --- /dev/null +++ b/web/src/command.rs @@ -0,0 +1,72 @@ +mod action; + +pub use action::Action; + +use std::fmt; + +#[cfg(target_arch = "wasm32")] +use std::future::Future; + +/// A set of asynchronous actions to be performed by some runtime. +pub struct Command<T>(iced_futures::Command<Action<T>>); + +impl<T> Command<T> { +    /// Creates an empty [`Command`]. +    /// +    /// In other words, a [`Command`] that does nothing. +    pub const fn none() -> Self { +        Self(iced_futures::Command::none()) +    } + +    /// Creates a [`Command`] that performs a single [`Action`]. +    pub const fn single(action: Action<T>) -> Self { +        Self(iced_futures::Command::single(action)) +    } + +    /// Creates a [`Command`] that performs the action of the given future. +    #[cfg(target_arch = "wasm32")] +    pub fn perform<A>( +        future: impl Future<Output = T> + 'static, +        f: impl Fn(T) -> A + 'static + Send, +    ) -> Command<A> { +        use iced_futures::futures::FutureExt; + +        Command::single(Action::Future(Box::pin(future.map(f)))) +    } + +    /// 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 { +        Self(iced_futures::Command::batch( +            commands.into_iter().map(|Command(command)| command), +        )) +    } + +    /// Applies a transformation to the result of a [`Command`]. +    #[cfg(target_arch = "wasm32")] +    pub fn map<A>(self, f: impl Fn(T) -> A + 'static + Clone) -> Command<A> +    where +        T: 'static, +    { +        let Command(command) = self; + +        Command(command.map(move |action| action.map(f.clone()))) +    } + +    /// Returns all of the actions of the [`Command`]. +    pub fn actions(self) -> Vec<Action<T>> { +        let Command(command) = self; + +        command.actions() +    } +} + +impl<T> fmt::Debug for Command<T> { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        let Command(command) = self; + +        command.fmt(f) +    } +} diff --git a/web/src/command/action.rs b/web/src/command/action.rs new file mode 100644 index 00000000..c0223e50 --- /dev/null +++ b/web/src/command/action.rs @@ -0,0 +1,28 @@ +pub enum Action<T> { +    Future(iced_futures::BoxFuture<T>), +} + +use std::fmt; + +impl<T> Action<T> { +    /// Applies a transformation to the result of a [`Command`]. +    #[cfg(target_arch = "wasm32")] +    pub fn map<A>(self, f: impl Fn(T) -> A + 'static) -> Action<A> +    where +        T: 'static, +    { +        use iced_futures::futures::FutureExt; + +        match self { +            Self::Future(future) => Action::Future(Box::pin(future.map(f))), +        } +    } +} + +impl<T> fmt::Debug for Action<T> { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        match self { +            Self::Future(_) => write!(f, "Action::Future"), +        } +    } +} diff --git a/web/src/lib.rs b/web/src/lib.rs index bb09bb0d..5bbd2ee6 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -59,7 +59,7 @@ use dodrio::bumpalo;  use std::{cell::RefCell, rc::Rc};  mod bus; -mod clipboard; +mod command;  mod element;  mod hasher; @@ -68,7 +68,7 @@ pub mod subscription;  pub mod widget;  pub use bus::Bus; -pub use clipboard::Clipboard; +pub use command::Command;  pub use css::Css;  pub use dodrio;  pub use element::Element; @@ -77,7 +77,7 @@ pub use iced_core::{      keyboard, menu, mouse, Align, Background, Color, Font, HorizontalAlignment,      Length, Menu, Padding, Point, Rectangle, Size, Vector, VerticalAlignment,  }; -pub use iced_futures::{executor, futures, Command}; +pub use iced_futures::{executor, futures};  pub use subscription::Subscription;  #[doc(no_inline)] @@ -128,11 +128,7 @@ pub trait Application {      /// this method.      ///      /// Any [`Command`] returned will be executed immediately in the background. -    fn update( -        &mut self, -        message: Self::Message, -        clipboard: &mut Clipboard, -    ) -> Command<Self::Message>; +    fn update(&mut self, message: Self::Message) -> Command<Self::Message>;      /// Returns the widgets to display in the [`Application`].      /// @@ -162,8 +158,6 @@ pub trait Application {          let document = window.document().unwrap();          let body = document.body().unwrap(); -        let mut clipboard = Clipboard::new(); -          let (sender, receiver) =              iced_futures::futures::channel::mpsc::unbounded(); @@ -177,7 +171,7 @@ pub trait Application {          let mut title = app.title();          document.set_title(&title); -        runtime.spawn(command); +        run_command(command, &mut runtime);          let application = Rc::new(RefCell::new(app)); @@ -190,8 +184,7 @@ pub trait Application {          let event_loop = receiver.for_each(move |message| {              let (command, subscription) = runtime.enter(|| { -                let command = -                    application.borrow_mut().update(message, &mut clipboard); +                let command = application.borrow_mut().update(message);                  let subscription = application.borrow().subscription();                  (command, subscription) @@ -199,7 +192,7 @@ pub trait Application {              let new_title = application.borrow().title(); -            runtime.spawn(command); +            run_command(command, &mut runtime);              runtime.track(subscription);              if title != new_title { @@ -350,8 +343,7 @@ pub trait Embedded {          );          let (app, command) = runtime.enter(|| Self::new(flags)); - -        runtime.spawn(command); +        run_command(command, &mut runtime);          let application = Rc::new(RefCell::new(app)); @@ -370,7 +362,7 @@ pub trait Embedded {                  (command, subscription)              }); -            runtime.spawn(command); +            run_command(command, &mut runtime);              runtime.track(subscription);              vdom.weak().schedule_render(); @@ -382,6 +374,25 @@ pub trait Embedded {      }  } +fn run_command<Message: 'static + Send, E: Executor>( +    command: Command<Message>, +    runtime: &mut iced_futures::Runtime< +        Hasher, +        (), +        E, +        iced_futures::futures::channel::mpsc::UnboundedSender<Message>, +        Message, +    >, +) { +    for action in command.actions() { +        match action { +            command::Action::Future(future) => { +                runtime.spawn(future); +            } +        } +    } +} +  struct EmbeddedInstance<A: Embedded> {      application: Rc<RefCell<A>>,      bus: Bus<A::Message>, | 
