From ba56a561b254c9a5f3d23cb54d23dc311759ab4c Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector0193@gmail.com>
Date: Thu, 21 Nov 2019 18:00:27 +0100
Subject: Implement `iced::Sandbox` trait for simple apps

---
 examples/tour.rs   | 31 ++++++++++-------------
 src/application.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib.rs         | 72 +++---------------------------------------------------
 src/sandbox.rs     | 45 ++++++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+), 86 deletions(-)
 create mode 100644 src/application.rs
 create mode 100644 src/sandbox.rs

diff --git a/examples/tour.rs b/examples/tour.rs
index 8a805088..0169c8e1 100644
--- a/examples/tour.rs
+++ b/examples/tour.rs
@@ -1,7 +1,7 @@
 use iced::{
-    button, scrollable, slider, text_input, Application, Background, Button,
-    Checkbox, Color, Column, Command, Container, Element, HorizontalAlignment,
-    Image, Length, Radio, Row, Scrollable, Slider, Text, TextInput,
+    button, scrollable, slider, text_input, Background, Button, Checkbox,
+    Color, Column, Container, Element, HorizontalAlignment, Image, Length,
+    Radio, Row, Sandbox, Scrollable, Slider, Text, TextInput,
 };
 
 pub fn main() {
@@ -18,27 +18,24 @@ pub struct Tour {
     debug: bool,
 }
 
-impl Application for Tour {
+impl Sandbox for Tour {
     type Message = Message;
 
-    fn new() -> (Tour, Command<Message>) {
-        (
-            Tour {
-                steps: Steps::new(),
-                scroll: scrollable::State::new(),
-                back_button: button::State::new(),
-                next_button: button::State::new(),
-                debug: true,
-            },
-            Command::none(),
-        )
+    fn new() -> Tour {
+        Tour {
+            steps: Steps::new(),
+            scroll: scrollable::State::new(),
+            back_button: button::State::new(),
+            next_button: button::State::new(),
+            debug: true,
+        }
     }
 
     fn title(&self) -> String {
         format!("{} - Iced", self.steps.title())
     }
 
-    fn update(&mut self, event: Message) -> Command<Message> {
+    fn update(&mut self, event: Message) {
         match event {
             Message::BackPressed => {
                 self.steps.go_back();
@@ -50,8 +47,6 @@ impl Application for Tour {
                 self.steps.update(step_msg, &mut self.debug);
             }
         }
-
-        Command::none()
     }
 
     fn view(&mut self) -> Element<Message> {
diff --git a/src/application.rs b/src/application.rs
new file mode 100644
index 00000000..ba8da446
--- /dev/null
+++ b/src/application.rs
@@ -0,0 +1,69 @@
+use crate::{Command, Element};
+
+pub trait Application: Sized {
+    type Message: std::fmt::Debug + Send;
+
+    fn new() -> (Self, Command<Self::Message>);
+
+    fn title(&self) -> String;
+
+    fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
+
+    fn view(&mut self) -> Element<Self::Message>;
+
+    fn run()
+    where
+        Self: 'static + Sized,
+    {
+        #[cfg(not(target_arch = "wasm32"))]
+        <Instance<Self> as iced_winit::Application>::run();
+
+        #[cfg(target_arch = "wasm32")]
+        iced_web::Application::run(Instance(self));
+    }
+}
+
+struct Instance<A: Application>(A);
+
+#[cfg(not(target_arch = "wasm32"))]
+impl<A> iced_winit::Application for Instance<A>
+where
+    A: Application,
+{
+    type Renderer = iced_wgpu::Renderer;
+    type Message = A::Message;
+
+    fn new() -> (Self, Command<A::Message>) {
+        let (app, command) = A::new();
+
+        (Instance(app), command)
+    }
+
+    fn title(&self) -> String {
+        self.0.title()
+    }
+
+    fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
+        self.0.update(message)
+    }
+
+    fn view(&mut self) -> Element<Self::Message> {
+        self.0.view()
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+impl<A> iced_web::Application for Instance<A>
+where
+    A: Application,
+{
+    type Message = A::Message;
+
+    fn update(&mut self, message: Self::Message) {
+        self.0.update(message);
+    }
+
+    fn view(&mut self) -> Element<Self::Message> {
+        self.0.view()
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index e64767c2..8462cd3c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,73 +1,9 @@
+mod application;
 #[cfg_attr(target_arch = "wasm32", path = "web.rs")]
 #[cfg_attr(not(target_arch = "wasm32"), path = "native.rs")]
 mod platform;
+mod sandbox;
 
+pub use application::Application;
 pub use platform::*;
-
-pub trait Application: Sized {
-    type Message: std::fmt::Debug + Send;
-
-    fn new() -> (Self, Command<Self::Message>);
-
-    fn title(&self) -> String;
-
-    fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
-
-    fn view(&mut self) -> Element<Self::Message>;
-
-    fn run()
-    where
-        Self: 'static + Sized,
-    {
-        #[cfg(not(target_arch = "wasm32"))]
-        <Instance<Self> as iced_winit::Application>::run();
-
-        #[cfg(target_arch = "wasm32")]
-        iced_web::Application::run(Instance(self));
-    }
-}
-
-struct Instance<A: Application>(A);
-
-#[cfg(not(target_arch = "wasm32"))]
-impl<A> iced_winit::Application for Instance<A>
-where
-    A: Application,
-{
-    type Renderer = iced_wgpu::Renderer;
-    type Message = A::Message;
-
-    fn new() -> (Self, Command<A::Message>) {
-        let (app, command) = A::new();
-
-        (Instance(app), command)
-    }
-
-    fn title(&self) -> String {
-        self.0.title()
-    }
-
-    fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
-        self.0.update(message)
-    }
-
-    fn view(&mut self) -> Element<Self::Message> {
-        self.0.view()
-    }
-}
-
-#[cfg(target_arch = "wasm32")]
-impl<A> iced_web::Application for Instance<A>
-where
-    A: Application,
-{
-    type Message = A::Message;
-
-    fn update(&mut self, message: Self::Message) {
-        self.0.update(message);
-    }
-
-    fn view(&mut self) -> Element<Self::Message> {
-        self.0.view()
-    }
-}
+pub use sandbox::Sandbox;
diff --git a/src/sandbox.rs b/src/sandbox.rs
new file mode 100644
index 00000000..8ff374f7
--- /dev/null
+++ b/src/sandbox.rs
@@ -0,0 +1,45 @@
+use crate::{Application, Command, Element};
+
+pub trait Sandbox {
+    type Message: std::fmt::Debug + Send;
+
+    fn new() -> Self;
+
+    fn title(&self) -> String;
+
+    fn update(&mut self, message: Self::Message);
+
+    fn view(&mut self) -> Element<Self::Message>;
+
+    fn run()
+    where
+        Self: 'static + Sized,
+    {
+        <Self as Application>::run()
+    }
+}
+
+impl<T> Application for T
+where
+    T: Sandbox,
+{
+    type Message = T::Message;
+
+    fn new() -> (Self, Command<T::Message>) {
+        (T::new(), Command::none())
+    }
+
+    fn title(&self) -> String {
+        T::title(self)
+    }
+
+    fn update(&mut self, message: T::Message) -> Command<T::Message> {
+        T::update(self, message);
+
+        Command::none()
+    }
+
+    fn view(&mut self) -> Element<T::Message> {
+        T::view(self)
+    }
+}
-- 
cgit