Implement event capturing for `Canvas`
This commit is contained in:
parent
bf6c65b5ad
commit
3aca177132
|
@ -69,7 +69,8 @@ impl Sandbox for Example {
|
||||||
|
|
||||||
mod bezier {
|
mod bezier {
|
||||||
use iced::{
|
use iced::{
|
||||||
canvas::{self, Canvas, Cursor, Event, Frame, Geometry, Path, Stroke},
|
canvas::event::{self, Event},
|
||||||
|
canvas::{self, Canvas, Cursor, Frame, Geometry, Path, Stroke},
|
||||||
mouse, Element, Length, Point, Rectangle,
|
mouse, Element, Length, Point, Rectangle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,41 +110,51 @@ mod bezier {
|
||||||
event: Event,
|
event: Event,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
) -> Option<Curve> {
|
) -> (event::Status, Option<Curve>) {
|
||||||
let cursor_position = cursor.position_in(&bounds)?;
|
let cursor_position =
|
||||||
|
if let Some(position) = cursor.position_in(&bounds) {
|
||||||
|
position
|
||||||
|
} else {
|
||||||
|
return (event::Status::Ignored, None);
|
||||||
|
};
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse_event) => match mouse_event {
|
Event::Mouse(mouse_event) => {
|
||||||
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
let message = match mouse_event {
|
||||||
match self.state.pending {
|
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
||||||
None => {
|
match self.state.pending {
|
||||||
self.state.pending = Some(Pending::One {
|
None => {
|
||||||
from: cursor_position,
|
self.state.pending = Some(Pending::One {
|
||||||
});
|
from: cursor_position,
|
||||||
None
|
});
|
||||||
}
|
|
||||||
Some(Pending::One { from }) => {
|
|
||||||
self.state.pending = Some(Pending::Two {
|
|
||||||
from,
|
|
||||||
to: cursor_position,
|
|
||||||
});
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(Pending::Two { from, to }) => {
|
Some(Pending::One { from }) => {
|
||||||
self.state.pending = None;
|
self.state.pending = Some(Pending::Two {
|
||||||
|
from,
|
||||||
|
to: cursor_position,
|
||||||
|
});
|
||||||
|
|
||||||
Some(Curve {
|
None
|
||||||
from,
|
}
|
||||||
to,
|
Some(Pending::Two { from, to }) => {
|
||||||
control: cursor_position,
|
self.state.pending = None;
|
||||||
})
|
|
||||||
|
Some(Curve {
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
control: cursor_position,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => None,
|
||||||
_ => None,
|
};
|
||||||
},
|
|
||||||
_ => None,
|
(event::Status::Captured, message)
|
||||||
|
}
|
||||||
|
_ => (event::Status::Ignored, None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,9 +153,8 @@ impl Application for GameOfLife {
|
||||||
mod grid {
|
mod grid {
|
||||||
use crate::Preset;
|
use crate::Preset;
|
||||||
use iced::{
|
use iced::{
|
||||||
canvas::{
|
canvas::event::{self, Event},
|
||||||
self, Cache, Canvas, Cursor, Event, Frame, Geometry, Path, Text,
|
canvas::{self, Cache, Canvas, Cursor, Frame, Geometry, Path, Text},
|
||||||
},
|
|
||||||
mouse, Color, Element, HorizontalAlignment, Length, Point, Rectangle,
|
mouse, Color, Element, HorizontalAlignment, Length, Point, Rectangle,
|
||||||
Size, Vector, VerticalAlignment,
|
Size, Vector, VerticalAlignment,
|
||||||
};
|
};
|
||||||
|
@ -328,12 +327,18 @@ mod grid {
|
||||||
event: Event,
|
event: Event,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
) -> Option<Message> {
|
) -> (event::Status, Option<Message>) {
|
||||||
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
|
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
|
||||||
self.interaction = Interaction::None;
|
self.interaction = Interaction::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cursor_position = cursor.position_in(&bounds)?;
|
let cursor_position =
|
||||||
|
if let Some(position) = cursor.position_in(&bounds) {
|
||||||
|
position
|
||||||
|
} else {
|
||||||
|
return (event::Status::Ignored, None);
|
||||||
|
};
|
||||||
|
|
||||||
let cell = Cell::at(self.project(cursor_position, bounds.size()));
|
let cell = Cell::at(self.project(cursor_position, bounds.size()));
|
||||||
let is_populated = self.state.contains(&cell);
|
let is_populated = self.state.contains(&cell);
|
||||||
|
|
||||||
|
@ -345,28 +350,32 @@ mod grid {
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse_event) => match mouse_event {
|
Event::Mouse(mouse_event) => match mouse_event {
|
||||||
mouse::Event::ButtonPressed(button) => match button {
|
mouse::Event::ButtonPressed(button) => {
|
||||||
mouse::Button::Left => {
|
let message = match button {
|
||||||
self.interaction = if is_populated {
|
mouse::Button::Left => {
|
||||||
Interaction::Erasing
|
self.interaction = if is_populated {
|
||||||
} else {
|
Interaction::Erasing
|
||||||
Interaction::Drawing
|
} else {
|
||||||
};
|
Interaction::Drawing
|
||||||
|
};
|
||||||
|
|
||||||
populate.or(unpopulate)
|
populate.or(unpopulate)
|
||||||
}
|
}
|
||||||
mouse::Button::Right => {
|
mouse::Button::Right => {
|
||||||
self.interaction = Interaction::Panning {
|
self.interaction = Interaction::Panning {
|
||||||
translation: self.translation,
|
translation: self.translation,
|
||||||
start: cursor_position,
|
start: cursor_position,
|
||||||
};
|
};
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
(event::Status::Captured, message)
|
||||||
|
}
|
||||||
mouse::Event::CursorMoved { .. } => {
|
mouse::Event::CursorMoved { .. } => {
|
||||||
match self.interaction {
|
let message = match self.interaction {
|
||||||
Interaction::Drawing => populate,
|
Interaction::Drawing => populate,
|
||||||
Interaction::Erasing => unpopulate,
|
Interaction::Erasing => unpopulate,
|
||||||
Interaction::Panning { translation, start } => {
|
Interaction::Panning { translation, start } => {
|
||||||
|
@ -380,7 +389,14 @@ mod grid {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let event_status = match self.interaction {
|
||||||
|
Interaction::None => event::Status::Ignored,
|
||||||
|
_ => event::Status::Captured,
|
||||||
|
};
|
||||||
|
|
||||||
|
(event_status, message)
|
||||||
}
|
}
|
||||||
mouse::Event::WheelScrolled { delta } => match delta {
|
mouse::Event::WheelScrolled { delta } => match delta {
|
||||||
mouse::ScrollDelta::Lines { y, .. }
|
mouse::ScrollDelta::Lines { y, .. }
|
||||||
|
@ -413,12 +429,12 @@ mod grid {
|
||||||
self.grid_cache.clear();
|
self.grid_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
(event::Status::Captured, None)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => (event::Status::Ignored, None),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => (event::Status::Ignored, None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ use iced_native::{
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
pub mod event;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod event;
|
|
||||||
mod fill;
|
mod fill;
|
||||||
mod frame;
|
mod frame;
|
||||||
mod geometry;
|
mod geometry;
|
||||||
|
@ -184,11 +184,14 @@ where
|
||||||
let cursor = Cursor::from_window_position(cursor_position);
|
let cursor = Cursor::from_window_position(cursor_position);
|
||||||
|
|
||||||
if let Some(canvas_event) = canvas_event {
|
if let Some(canvas_event) = canvas_event {
|
||||||
if let Some(message) =
|
let (event_status, message) =
|
||||||
self.program.update(canvas_event, bounds, cursor)
|
self.program.update(canvas_event, bounds, cursor);
|
||||||
{
|
|
||||||
|
if let Some(message) = message {
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return event_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
event::Status::Ignored
|
event::Status::Ignored
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Handle events of a canvas.
|
||||||
use iced_native::keyboard;
|
use iced_native::keyboard;
|
||||||
use iced_native::mouse;
|
use iced_native::mouse;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::canvas::{Cursor, Event, Geometry};
|
use crate::canvas::event::{self, Event};
|
||||||
|
use crate::canvas::{Cursor, Geometry};
|
||||||
use iced_native::{mouse, Rectangle};
|
use iced_native::{mouse, Rectangle};
|
||||||
|
|
||||||
/// The state and logic of a [`Canvas`].
|
/// The state and logic of a [`Canvas`].
|
||||||
|
@ -27,8 +28,8 @@ pub trait Program<Message> {
|
||||||
_event: Event,
|
_event: Event,
|
||||||
_bounds: Rectangle,
|
_bounds: Rectangle,
|
||||||
_cursor: Cursor,
|
_cursor: Cursor,
|
||||||
) -> Option<Message> {
|
) -> (event::Status, Option<Message>) {
|
||||||
None
|
(event::Status::Ignored, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws the state of the [`Program`], producing a bunch of [`Geometry`].
|
/// Draws the state of the [`Program`], producing a bunch of [`Geometry`].
|
||||||
|
@ -67,7 +68,7 @@ where
|
||||||
event: Event,
|
event: Event,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
) -> Option<Message> {
|
) -> (event::Status, Option<Message>) {
|
||||||
T::update(self, event, bounds, cursor)
|
T::update(self, event, bounds, cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue