Skip to content

Commit

Permalink
Merge pull request #614 from hecrj/feature/event-capturing
Browse files Browse the repository at this point in the history
Event capturing
  • Loading branch information
hecrj authored Nov 14, 2020
2 parents 73811c3 + bf2d256 commit 62295f5
Show file tree
Hide file tree
Showing 33 changed files with 711 additions and 425 deletions.
75 changes: 43 additions & 32 deletions examples/bezier_tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ impl Sandbox for Example {

mod bezier {
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,
};

Expand Down Expand Up @@ -109,41 +110,51 @@ mod bezier {
event: Event,
bounds: Rectangle,
cursor: Cursor,
) -> Option<Curve> {
let cursor_position = cursor.position_in(&bounds)?;
) -> (event::Status, Option<Curve>) {
let cursor_position =
if let Some(position) = cursor.position_in(&bounds) {
position
} else {
return (event::Status::Ignored, None);
};

match event {
Event::Mouse(mouse_event) => match mouse_event {
mouse::Event::ButtonPressed(mouse::Button::Left) => {
match self.state.pending {
None => {
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
}
Some(Pending::Two { from, to }) => {
self.state.pending = None;

Some(Curve {
from,
to,
control: cursor_position,
})
Event::Mouse(mouse_event) => {
let message = match mouse_event {
mouse::Event::ButtonPressed(mouse::Button::Left) => {
match self.state.pending {
None => {
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
}
Some(Pending::Two { from, to }) => {
self.state.pending = None;

Some(Curve {
from,
to,
control: cursor_position,
})
}
}
}
}
_ => None,
},
_ => None,
_ => None,
};

(event::Status::Captured, message)
}
_ => (event::Status::Ignored, None),
}
}

Expand Down
74 changes: 45 additions & 29 deletions examples/game_of_life/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,8 @@ impl Application for GameOfLife {
mod grid {
use crate::Preset;
use iced::{
canvas::{
self, Cache, Canvas, Cursor, Event, Frame, Geometry, Path, Text,
},
canvas::event::{self, Event},
canvas::{self, Cache, Canvas, Cursor, Frame, Geometry, Path, Text},
mouse, Color, Element, HorizontalAlignment, Length, Point, Rectangle,
Size, Vector, VerticalAlignment,
};
Expand Down Expand Up @@ -328,12 +327,18 @@ mod grid {
event: Event,
bounds: Rectangle,
cursor: Cursor,
) -> Option<Message> {
) -> (event::Status, Option<Message>) {
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
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 is_populated = self.state.contains(&cell);

Expand All @@ -345,28 +350,32 @@ mod grid {

match event {
Event::Mouse(mouse_event) => match mouse_event {
mouse::Event::ButtonPressed(button) => match button {
mouse::Button::Left => {
self.interaction = if is_populated {
Interaction::Erasing
} else {
Interaction::Drawing
};

populate.or(unpopulate)
}
mouse::Button::Right => {
self.interaction = Interaction::Panning {
translation: self.translation,
start: cursor_position,
};
mouse::Event::ButtonPressed(button) => {
let message = match button {
mouse::Button::Left => {
self.interaction = if is_populated {
Interaction::Erasing
} else {
Interaction::Drawing
};

populate.or(unpopulate)
}
mouse::Button::Right => {
self.interaction = Interaction::Panning {
translation: self.translation,
start: cursor_position,
};

None
}
_ => None,
},
None
}
_ => None,
};

(event::Status::Captured, message)
}
mouse::Event::CursorMoved { .. } => {
match self.interaction {
let message = match self.interaction {
Interaction::Drawing => populate,
Interaction::Erasing => unpopulate,
Interaction::Panning { translation, start } => {
Expand All @@ -380,7 +389,14 @@ mod grid {
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::ScrollDelta::Lines { y, .. }
Expand Down Expand Up @@ -413,12 +429,12 @@ mod grid {
self.grid_cache.clear();
}

None
(event::Status::Captured, None)
}
},
_ => None,
_ => (event::Status::Ignored, None),
},
_ => None,
_ => (event::Status::Ignored, None),
}
}

Expand Down
20 changes: 13 additions & 7 deletions examples/pane_grid/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use iced::{
Button, Column, Command, Container, Element, HorizontalAlignment, Length,
PaneGrid, Scrollable, Settings, Subscription, Text,
};
use iced_native::{subscription, Event};
use iced_native::{event, subscription, Event};

pub fn main() -> iced::Result {
Example::run(Settings::default())
Expand Down Expand Up @@ -119,12 +119,18 @@ impl Application for Example {
}

fn subscription(&self) -> Subscription<Message> {
subscription::events_with(|event| match event {
Event::Keyboard(keyboard::Event::KeyPressed {
modifiers,
key_code,
}) if modifiers.is_command_pressed() => handle_hotkey(key_code),
_ => None,
subscription::events_with(|event, status| {
if let event::Status::Captured = status {
return None;
}

match event {
Event::Keyboard(keyboard::Event::KeyPressed {
modifiers,
key_code,
}) if modifiers.is_command_pressed() => handle_hotkey(key_code),
_ => None,
}
})
}

Expand Down
21 changes: 12 additions & 9 deletions glutin/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,29 +156,33 @@ async fn run_instance<A, E, C>(
let mut mouse_interaction = mouse::Interaction::default();

let mut events = Vec::new();
let mut external_messages = Vec::new();
let mut messages = Vec::new();

debug.startup_finished();

while let Some(event) = receiver.next().await {
match event {
event::Event::MainEventsCleared => {
if events.is_empty() && external_messages.is_empty() {
if events.is_empty() && messages.is_empty() {
continue;
}

debug.event_processing_started();
let mut messages = user_interface.update(

let statuses = user_interface.update(
&events,
state.cursor_position(),
clipboard.as_ref().map(|c| c as _),
&mut renderer,
&mut messages,
);

messages.extend(external_messages.drain(..));
events.clear();
debug.event_processing_finished();

for event in events.drain(..).zip(statuses.into_iter()) {
runtime.broadcast(event);
}

if !messages.is_empty() {
let cache =
ManuallyDrop::into_inner(user_interface).into_cache();
Expand All @@ -188,7 +192,7 @@ async fn run_instance<A, E, C>(
&mut application,
&mut runtime,
&mut debug,
messages,
&mut messages,
);

// Update window
Expand All @@ -212,7 +216,7 @@ async fn run_instance<A, E, C>(
context.window().request_redraw();
}
event::Event::UserEvent(message) => {
external_messages.push(message);
messages.push(message);
}
event::Event::RedrawRequested(_) => {
debug.render_started();
Expand Down Expand Up @@ -283,8 +287,7 @@ async fn run_instance<A, E, C>(
state.scale_factor(),
state.modifiers(),
) {
events.push(event.clone());
runtime.broadcast(event);
events.push(event);
}
}
_ => {}
Expand Down
21 changes: 14 additions & 7 deletions graphics/src/widget/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@
//! [`Canvas`]: struct.Canvas.html
//! [`Frame`]: struct.Frame.html
use crate::{Backend, Defaults, Primitive, Renderer};
use iced_native::layout;
use iced_native::mouse;
use iced_native::{
layout, mouse, Clipboard, Element, Hasher, Layout, Length, Point,
Rectangle, Size, Vector, Widget,
Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector,
Widget,
};
use std::hash::Hash;
use std::marker::PhantomData;

pub mod event;
pub mod path;

mod cache;
mod cursor;
mod event;
mod fill;
mod frame;
mod geometry;
Expand Down Expand Up @@ -166,7 +168,7 @@ where
messages: &mut Vec<Message>,
_renderer: &Renderer<B>,
_clipboard: Option<&dyn Clipboard>,
) {
) -> event::Status {
let bounds = layout.bounds();

let canvas_event = match event {
Expand All @@ -182,12 +184,17 @@ where
let cursor = Cursor::from_window_position(cursor_position);

if let Some(canvas_event) = canvas_event {
if let Some(message) =
self.program.update(canvas_event, bounds, cursor)
{
let (event_status, message) =
self.program.update(canvas_event, bounds, cursor);

if let Some(message) = message {
messages.push(message);
}

return event_status;
}

event::Status::Ignored
}

fn draw(
Expand Down
3 changes: 3 additions & 0 deletions graphics/src/widget/canvas/event.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Handle events of a canvas.
use iced_native::keyboard;
use iced_native::mouse;

pub use iced_native::event::Status;

/// A [`Canvas`] event.
///
/// [`Canvas`]: struct.Event.html
Expand Down
Loading

0 comments on commit 62295f5

Please sign in to comment.