From e4eb0553de13053c9828fd5454c281e27e598d65 Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector0193@gmail.com>
Date: Tue, 28 Apr 2020 03:46:03 +0200
Subject: Allow `canvas::State` to produce messages

---
 wgpu/src/widget/canvas.rs       | 25 +++++++++++++++++--------
 wgpu/src/widget/canvas/cache.rs |  7 +++++--
 wgpu/src/widget/canvas/state.rs | 14 ++++++++------
 3 files changed, 30 insertions(+), 16 deletions(-)

(limited to 'wgpu/src')

diff --git a/wgpu/src/widget/canvas.rs b/wgpu/src/widget/canvas.rs
index 744d901e..044bc3ec 100644
--- a/wgpu/src/widget/canvas.rs
+++ b/wgpu/src/widget/canvas.rs
@@ -13,6 +13,7 @@ use iced_native::{
     MouseCursor, Point, Size, Vector, Widget,
 };
 use std::hash::Hash;
+use std::marker::PhantomData;
 
 pub mod path;
 
@@ -91,16 +92,17 @@ pub use text::Text;
 /// let cache = Cache::new();
 ///
 /// // Finally, we simply use our `Cache` to create the `Canvas`!
-/// let canvas = Canvas::new(cache.with(Circle { radius: 50.0 }));
+/// let canvas: Canvas<_, ()> = Canvas::new(cache.with(Circle { radius: 50.0 }));
 /// ```
 #[derive(Debug)]
-pub struct Canvas<S: State> {
+pub struct Canvas<S: State<Message>, Message> {
     width: Length,
     height: Length,
     state: S,
+    phantom: PhantomData<Message>,
 }
 
-impl<S: State> Canvas<S> {
+impl<Message, S: State<Message>> Canvas<S, Message> {
     const DEFAULT_SIZE: u16 = 100;
 
     /// Creates a new [`Canvas`] with no layers.
@@ -111,6 +113,7 @@ impl<S: State> Canvas<S> {
             width: Length::Units(Self::DEFAULT_SIZE),
             height: Length::Units(Self::DEFAULT_SIZE),
             state,
+            phantom: PhantomData,
         }
     }
 
@@ -131,7 +134,9 @@ impl<S: State> Canvas<S> {
     }
 }
 
-impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
+impl<Message, S: State<Message>> Widget<Message, Renderer>
+    for Canvas<S, Message>
+{
     fn width(&self) -> Length {
         self.width
     }
@@ -156,7 +161,7 @@ impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
         event: iced_native::Event,
         layout: Layout<'_>,
         cursor_position: Point,
-        _messages: &mut Vec<Message>,
+        messages: &mut Vec<Message>,
         _renderer: &Renderer,
         _clipboard: Option<&dyn Clipboard>,
     ) {
@@ -178,7 +183,11 @@ impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
         };
 
         if let Some(canvas_event) = canvas_event {
-            self.state.update(canvas_event, bounds.size())
+            if let Some(message) =
+                self.state.update(canvas_event, bounds.size())
+            {
+                messages.push(message);
+            }
         }
     }
 
@@ -218,12 +227,12 @@ impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
     }
 }
 
-impl<'a, Message, S: State + 'a> From<Canvas<S>>
+impl<'a, Message, S: State<Message> + 'a> From<Canvas<S, Message>>
     for Element<'a, Message, Renderer>
 where
     Message: 'static,
 {
-    fn from(canvas: Canvas<S>) -> Element<'a, Message, Renderer> {
+    fn from(canvas: Canvas<S, Message>) -> Element<'a, Message, Renderer> {
         Element::new(canvas)
     }
 }
diff --git a/wgpu/src/widget/canvas/cache.rs b/wgpu/src/widget/canvas/cache.rs
index 12cc6442..2beed0f7 100644
--- a/wgpu/src/widget/canvas/cache.rs
+++ b/wgpu/src/widget/canvas/cache.rs
@@ -80,7 +80,10 @@ impl Cache {
         Geometry::from_primitive(Primitive::Cached { cache: primitive })
     }
 
-    pub fn with<'a, T>(&'a self, input: T) -> impl crate::canvas::State + 'a
+    pub fn with<'a, T, Message>(
+        &'a self,
+        input: T,
+    ) -> impl crate::canvas::State<Message> + 'a
     where
         T: Drawable + std::fmt::Debug + 'a,
     {
@@ -93,7 +96,7 @@ struct Bind<'a, T> {
     input: T,
 }
 
-impl<'a, T> crate::canvas::State for Bind<'a, T>
+impl<'a, T, Message> crate::canvas::State<Message> for Bind<'a, T>
 where
     T: Drawable + std::fmt::Debug + 'a,
 {
diff --git a/wgpu/src/widget/canvas/state.rs b/wgpu/src/widget/canvas/state.rs
index 8388f94d..ab433dd1 100644
--- a/wgpu/src/widget/canvas/state.rs
+++ b/wgpu/src/widget/canvas/state.rs
@@ -1,17 +1,19 @@
 use crate::canvas::{Event, Geometry, Size};
 
-pub trait State {
-    fn update(&mut self, _event: Event, _bounds: Size) {}
+pub trait State<Message> {
+    fn update(&mut self, _event: Event, _bounds: Size) -> Option<Message> {
+        None
+    }
 
     fn draw(&self, bounds: Size) -> Vec<Geometry>;
 }
 
-impl<T> State for &mut T
+impl<T, Message> State<Message> for &mut T
 where
-    T: State,
+    T: State<Message>,
 {
-    fn update(&mut self, event: Event, bounds: Size) {
-        T::update(self, event, bounds);
+    fn update(&mut self, event: Event, bounds: Size) -> Option<Message> {
+        T::update(self, event, bounds)
     }
 
     fn draw(&self, bounds: Size) -> Vec<Geometry> {
-- 
cgit