summaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2021-09-13 11:49:06 +0700
committerLibravatar GitHub <noreply@github.com>2021-09-13 11:49:06 +0700
commit93fec8d273ef8305e1c2456abe0c8ecd7a9d9407 (patch)
treec0c2445703133293b13657ab4f9c1c936e9cd688 /native
parent589f68df0f647d93f2b9dd7bf29cfacb0201351c (diff)
parent01b945b9814b9dc546e783a6dab66e4f7fe49786 (diff)
downloadiced-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 'native')
-rw-r--r--native/src/clipboard.rs34
-rw-r--r--native/src/command.rs72
-rw-r--r--native/src/command/action.rs46
-rw-r--r--native/src/lib.rs4
-rw-r--r--native/src/program.rs11
-rw-r--r--native/src/program/state.rs7
-rw-r--r--native/src/window.rs2
-rw-r--r--native/src/window/action.rs18
-rw-r--r--native/src/window/event.rs5
9 files changed, 183 insertions, 16 deletions
diff --git a/native/src/clipboard.rs b/native/src/clipboard.rs
index 081b4004..60703c31 100644
--- a/native/src/clipboard.rs
+++ b/native/src/clipboard.rs
@@ -1,4 +1,5 @@
//! Access the clipboard.
+use std::fmt;
/// A buffer for short-term storage and transfer within and between
/// applications.
@@ -21,3 +22,36 @@ impl Clipboard for Null {
fn write(&mut self, _contents: String) {}
}
+
+/// A clipboard action to be performed by some [`Command`].
+///
+/// [`Command`]: crate::Command
+pub enum Action<T> {
+ /// Read the clipboard and produce `T` with the result.
+ Read(Box<dyn Fn(Option<String>) -> T>),
+
+ /// Write the given contents to the clipboard.
+ Write(String),
+}
+
+impl<T> Action<T> {
+ /// Maps the output of a clipboard [`Action`] using the provided closure.
+ pub fn map<A>(self, f: impl Fn(T) -> A + 'static + Send + Sync) -> Action<A>
+ where
+ T: 'static,
+ {
+ match self {
+ Self::Read(o) => Action::Read(Box::new(move |s| f(o(s)))),
+ Self::Write(content) => Action::Write(content),
+ }
+ }
+}
+
+impl<T> fmt::Debug for Action<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Read(_) => write!(f, "Action::Read"),
+ Self::Write(_) => write!(f, "Action::Write"),
+ }
+ }
+}
diff --git a/native/src/command.rs b/native/src/command.rs
new file mode 100644
index 00000000..6fe518d7
--- /dev/null
+++ b/native/src/command.rs
@@ -0,0 +1,72 @@
+//! Run asynchronous actions.
+mod action;
+
+pub use action::Action;
+
+use std::fmt;
+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.
+ 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))))
+ }
+
+ /// 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`].
+ pub fn map<A>(
+ self,
+ f: impl Fn(T) -> A + 'static + Send + Sync + 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/native/src/command/action.rs b/native/src/command/action.rs
new file mode 100644
index 00000000..77be1b59
--- /dev/null
+++ b/native/src/command/action.rs
@@ -0,0 +1,46 @@
+use crate::clipboard;
+use crate::window;
+
+use std::fmt;
+
+/// An action that a [`Command`] can perform.
+///
+/// [`Command`]: crate::Command
+pub enum Action<T> {
+ /// Run a [`Future`] to completion.
+ Future(iced_futures::BoxFuture<T>),
+
+ /// Run a clipboard action.
+ Clipboard(clipboard::Action<T>),
+
+ /// Run a window action.
+ 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),
+ }
+ }
+}
+
+impl<T> fmt::Debug for Action<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Future(_) => write!(f, "Action::Future"),
+ Self::Clipboard(action) => {
+ write!(f, "Action::Clipboard({:?})", action)
+ }
+ Self::Window(action) => write!(f, "Action::Window({:?})", action),
+ }
+ }
+}
diff --git a/native/src/lib.rs b/native/src/lib.rs
index cbb02506..573be51d 100644
--- a/native/src/lib.rs
+++ b/native/src/lib.rs
@@ -34,6 +34,7 @@
#![forbid(unsafe_code)]
#![forbid(rust_2018_idioms)]
pub mod clipboard;
+pub mod command;
pub mod event;
pub mod keyboard;
pub mod layout;
@@ -64,12 +65,13 @@ pub use iced_core::{
menu, 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};
#[doc(no_inline)]
pub use executor::Executor;
pub use clipboard::Clipboard;
+pub use command::Command;
pub use debug::Debug;
pub use element::Element;
pub use event::Event;
diff --git a/native/src/program.rs b/native/src/program.rs
index 75fab094..fa83c0b1 100644
--- a/native/src/program.rs
+++ b/native/src/program.rs
@@ -1,5 +1,5 @@
//! Build interactive programs using The Elm Architecture.
-use crate::{Clipboard, Command, Element, Renderer};
+use crate::{Command, Element, Renderer};
mod state;
@@ -13,9 +13,6 @@ pub trait Program: Sized {
/// The type of __messages__ your [`Program`] will produce.
type Message: std::fmt::Debug + Clone + Send;
- /// The type of [`Clipboard`] your [`Program`] will use.
- type Clipboard: Clipboard;
-
/// Handles a __message__ and updates the state of the [`Program`].
///
/// This is where you define your __update logic__. All the __messages__,
@@ -24,11 +21,7 @@ pub trait Program: Sized {
///
/// Any [`Command`] returned will be executed immediately in the
/// background by shells.
- fn update(
- &mut self,
- message: Self::Message,
- clipboard: &mut Self::Clipboard,
- ) -> Command<Self::Message>;
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
/// Returns the widgets to display in the [`Program`].
///
diff --git a/native/src/program/state.rs b/native/src/program/state.rs
index fd1f2b52..3f5f6069 100644
--- a/native/src/program/state.rs
+++ b/native/src/program/state.rs
@@ -1,5 +1,6 @@
use crate::{
- Cache, Command, Debug, Event, Point, Program, Renderer, Size, UserInterface,
+ Cache, Clipboard, Command, Debug, Event, Point, Program, Renderer, Size,
+ UserInterface,
};
/// The execution state of a [`Program`]. It leverages caching, event
@@ -91,7 +92,7 @@ where
bounds: Size,
cursor_position: Point,
renderer: &mut P::Renderer,
- clipboard: &mut P::Clipboard,
+ clipboard: &mut dyn Clipboard,
debug: &mut Debug,
) -> Option<Command<P::Message>> {
let mut user_interface = build_user_interface(
@@ -135,7 +136,7 @@ where
debug.log_message(&message);
debug.update_started();
- let command = self.program.update(message, clipboard);
+ let command = self.program.update(message);
debug.update_finished();
command
diff --git a/native/src/window.rs b/native/src/window.rs
index 220bb3be..62487fb9 100644
--- a/native/src/window.rs
+++ b/native/src/window.rs
@@ -1,4 +1,6 @@
//! Build window-based GUI applications.
+mod action;
mod event;
+pub use action::Action;
pub use event::Event;
diff --git a/native/src/window/action.rs b/native/src/window/action.rs
new file mode 100644
index 00000000..01294e83
--- /dev/null
+++ b/native/src/window/action.rs
@@ -0,0 +1,18 @@
+/// An operation to be performed on some window.
+#[derive(Debug)]
+pub enum Action {
+ /// Resize the window.
+ Resize {
+ /// The new logical width of the window
+ width: u32,
+ /// The new logical height of the window
+ height: u32,
+ },
+ /// Move the window.
+ Move {
+ /// The new logical x location of the window
+ x: i32,
+ /// The new logical y location of the window
+ y: i32,
+ },
+}
diff --git a/native/src/window/event.rs b/native/src/window/event.rs
index 64f2b8d8..691af29a 100644
--- a/native/src/window/event.rs
+++ b/native/src/window/event.rs
@@ -13,10 +13,9 @@ pub enum Event {
/// A window was resized.
Resized {
- /// The new width of the window (in units)
+ /// The new logical width of the window
width: u32,
-
- /// The new height of the window (in units)
+ /// The new logical height of the window
height: u32,
},