Allow `canvas::State` to produce messages

This commit is contained in:
Héctor Ramón Jiménez 2020-04-28 03:46:03 +02:00
parent 2ca73036ab
commit e4eb0553de
4 changed files with 31 additions and 17 deletions

View File

@ -136,7 +136,7 @@ impl State {
} }
} }
impl canvas::State for State { impl<Message> canvas::State<Message> for State {
fn draw(&self, bounds: Size) -> Vec<canvas::Geometry> { fn draw(&self, bounds: Size) -> Vec<canvas::Geometry> {
vec![ vec![
self.space_cache.draw(bounds, self.space()), self.space_cache.draw(bounds, self.space()),

View File

@ -13,6 +13,7 @@ use iced_native::{
MouseCursor, Point, Size, Vector, Widget, MouseCursor, Point, Size, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData;
pub mod path; pub mod path;
@ -91,16 +92,17 @@ pub use text::Text;
/// let cache = Cache::new(); /// let cache = Cache::new();
/// ///
/// // Finally, we simply use our `Cache` to create the `Canvas`! /// // 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)] #[derive(Debug)]
pub struct Canvas<S: State> { pub struct Canvas<S: State<Message>, Message> {
width: Length, width: Length,
height: Length, height: Length,
state: S, state: S,
phantom: PhantomData<Message>,
} }
impl<S: State> Canvas<S> { impl<Message, S: State<Message>> Canvas<S, Message> {
const DEFAULT_SIZE: u16 = 100; const DEFAULT_SIZE: u16 = 100;
/// Creates a new [`Canvas`] with no layers. /// Creates a new [`Canvas`] with no layers.
@ -111,6 +113,7 @@ impl<S: State> Canvas<S> {
width: Length::Units(Self::DEFAULT_SIZE), width: Length::Units(Self::DEFAULT_SIZE),
height: Length::Units(Self::DEFAULT_SIZE), height: Length::Units(Self::DEFAULT_SIZE),
state, 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 { fn width(&self) -> Length {
self.width self.width
} }
@ -156,7 +161,7 @@ impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
event: iced_native::Event, event: iced_native::Event,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor_position: Point,
_messages: &mut Vec<Message>, messages: &mut Vec<Message>,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: Option<&dyn Clipboard>, _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 { 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> for Element<'a, Message, Renderer>
where where
Message: 'static, Message: 'static,
{ {
fn from(canvas: Canvas<S>) -> Element<'a, Message, Renderer> { fn from(canvas: Canvas<S, Message>) -> Element<'a, Message, Renderer> {
Element::new(canvas) Element::new(canvas)
} }
} }

View File

@ -80,7 +80,10 @@ impl Cache {
Geometry::from_primitive(Primitive::Cached { cache: primitive }) 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 where
T: Drawable + std::fmt::Debug + 'a, T: Drawable + std::fmt::Debug + 'a,
{ {
@ -93,7 +96,7 @@ struct Bind<'a, T> {
input: 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 where
T: Drawable + std::fmt::Debug + 'a, T: Drawable + std::fmt::Debug + 'a,
{ {

View File

@ -1,17 +1,19 @@
use crate::canvas::{Event, Geometry, Size}; use crate::canvas::{Event, Geometry, Size};
pub trait State { pub trait State<Message> {
fn update(&mut self, _event: Event, _bounds: Size) {} fn update(&mut self, _event: Event, _bounds: Size) -> Option<Message> {
None
}
fn draw(&self, bounds: Size) -> Vec<Geometry>; fn draw(&self, bounds: Size) -> Vec<Geometry>;
} }
impl<T> State for &mut T impl<T, Message> State<Message> for &mut T
where where
T: State, T: State<Message>,
{ {
fn update(&mut self, event: Event, bounds: Size) { fn update(&mut self, event: Event, bounds: Size) -> Option<Message> {
T::update(self, event, bounds); T::update(self, event, bounds)
} }
fn draw(&self, bounds: Size) -> Vec<Geometry> { fn draw(&self, bounds: Size) -> Vec<Geometry> {