Skip to content

Commit 49596cd

Browse files
committed
Add to MouseArea new functions to emit messages
containing the position on press and release events.
1 parent 599d8b5 commit 49596cd

File tree

1 file changed

+139
-31
lines changed

1 file changed

+139
-31
lines changed

widget/src/mouse_area.rs

+139-31
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ pub struct MouseArea<
1919
Renderer = crate::Renderer,
2020
> {
2121
content: Element<'a, Message, Theme, Renderer>,
22-
on_press: Option<Message>,
23-
on_release: Option<Message>,
24-
on_double_click: Option<Message>,
25-
on_right_press: Option<Message>,
26-
on_right_release: Option<Message>,
27-
on_middle_press: Option<Message>,
28-
on_middle_release: Option<Message>,
22+
on_press: Option<Reaction<'a, Message>>,
23+
on_release: Option<Reaction<'a, Message>>,
24+
on_double_click: Option<Reaction<'a, Message>>,
25+
on_right_press: Option<Reaction<'a, Message>>,
26+
on_right_release: Option<Reaction<'a, Message>>,
27+
on_middle_press: Option<Reaction<'a, Message>>,
28+
on_middle_release: Option<Reaction<'a, Message>>,
2929
on_scroll: Option<Box<dyn Fn(mouse::ScrollDelta) -> Message + 'a>>,
3030
on_enter: Option<Message>,
3131
on_move: Option<Box<dyn Fn(Point) -> Message + 'a>>,
@@ -37,14 +37,34 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
3737
/// The message to emit on a left button press.
3838
#[must_use]
3939
pub fn on_press(mut self, message: Message) -> Self {
40-
self.on_press = Some(message);
40+
self.on_press = Some(Reaction::Message(message));
41+
self
42+
}
43+
44+
/// The closure to create the message to emit on a left button press.
45+
#[must_use]
46+
pub fn on_press_position<F>(mut self, on_press: F) -> Self
47+
where
48+
F: 'a + Fn(Point) -> Message
49+
{
50+
self.on_press = Some(Reaction::MessageWithPosition(Box::new(on_press)));
4151
self
4252
}
4353

4454
/// The message to emit on a left button release.
4555
#[must_use]
4656
pub fn on_release(mut self, message: Message) -> Self {
47-
self.on_release = Some(message);
57+
self.on_release = Some(Reaction::Message(message));
58+
self
59+
}
60+
61+
/// The closure to create the message to emit on a left button release with the position.
62+
#[must_use]
63+
pub fn on_release_position<F>(mut self, on_release: F) -> Self
64+
where
65+
F: 'a + Fn(Point) -> Message
66+
{
67+
self.on_release = Some(Reaction::MessageWithPosition(Box::new(on_release)));
4868
self
4969
}
5070

@@ -60,35 +80,85 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
6080
/// [`on_release`]: Self::on_release
6181
#[must_use]
6282
pub fn on_double_click(mut self, message: Message) -> Self {
63-
self.on_double_click = Some(message);
83+
self.on_double_click = Some(Reaction::Message(message));
84+
self
85+
}
86+
87+
/// The closure to create the message to emit on a double click.
88+
#[must_use]
89+
pub fn on_double_click_position<F>(mut self, on_double_click: F) -> Self
90+
where
91+
F: 'a + Fn(Point) -> Message
92+
{
93+
self.on_double_click = Some(Reaction::MessageWithPosition(Box::new(on_double_click)));
6494
self
6595
}
6696

6797
/// The message to emit on a right button press.
6898
#[must_use]
6999
pub fn on_right_press(mut self, message: Message) -> Self {
70-
self.on_right_press = Some(message);
100+
self.on_right_press = Some(Reaction::Message(message));
101+
self
102+
}
103+
104+
/// The closure to create the message to emit on a right button press.
105+
#[must_use]
106+
pub fn on_right_press_position<F>(mut self, on_right_press: F) -> Self
107+
where
108+
F: 'a + Fn(Point) -> Message
109+
{
110+
self.on_right_press = Some(Reaction::MessageWithPosition(Box::new(on_right_press)));
71111
self
72112
}
73113

74114
/// The message to emit on a right button release.
75115
#[must_use]
76116
pub fn on_right_release(mut self, message: Message) -> Self {
77-
self.on_right_release = Some(message);
117+
self.on_right_release = Some(Reaction::Message(message));
118+
self
119+
}
120+
121+
/// The closure to create the message to emit on a right button release.
122+
#[must_use]
123+
pub fn on_right_release_position<F>(mut self, on_right_release: F) -> Self
124+
where
125+
F: 'a + Fn(Point) -> Message
126+
{
127+
self.on_right_release = Some(Reaction::MessageWithPosition(Box::new(on_right_release)));
78128
self
79129
}
80130

81131
/// The message to emit on a middle button press.
82132
#[must_use]
83133
pub fn on_middle_press(mut self, message: Message) -> Self {
84-
self.on_middle_press = Some(message);
134+
self.on_middle_press = Some(Reaction::Message(message));
135+
self
136+
}
137+
138+
/// The closure to create the message to emit on a middle button press.
139+
#[must_use]
140+
pub fn on_middle_press_position<F>(mut self, on_middle_press: F) -> Self
141+
where
142+
F: 'a + Fn(Point) -> Message
143+
{
144+
self.on_middle_press = Some(Reaction::MessageWithPosition(Box::new(on_middle_press)));
85145
self
86146
}
87147

88148
/// The message to emit on a middle button release.
89149
#[must_use]
90150
pub fn on_middle_release(mut self, message: Message) -> Self {
91-
self.on_middle_release = Some(message);
151+
self.on_middle_release = Some(Reaction::Message(message));
152+
self
153+
}
154+
155+
/// The closure to create the message to emit on a middle button release.
156+
#[must_use]
157+
pub fn on_middle_release_position<F>(mut self, on_middle_release: F) -> Self
158+
where
159+
F: 'a + Fn(Point) -> Message
160+
{
161+
self.on_middle_release = Some(Reaction::MessageWithPosition(Box::new(on_middle_release)));
92162
self
93163
}
94164

@@ -370,21 +440,23 @@ fn update<Message: Clone, Theme, Renderer>(
370440
match event {
371441
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
372442
| Event::Touch(touch::Event::FingerPressed { .. }) => {
373-
if let Some(message) = widget.on_press.as_ref() {
374-
shell.publish(message.clone());
375-
shell.capture_event();
443+
if let Some(reaction) = widget.on_press.as_ref() {
444+
if let Some(message) = reaction.react_maybe(cursor_position) {
445+
shell.publish(message);
446+
shell.capture_event();
447+
}
376448
}
377449

378450
if let Some(position) = cursor_position {
379-
if let Some(message) = widget.on_double_click.as_ref() {
451+
if let Some(reaction) = widget.on_double_click.as_ref() {
380452
let new_click = mouse::Click::new(
381453
position,
382454
mouse::Button::Left,
383455
state.previous_click,
384456
);
385457

386458
if new_click.kind() == mouse::click::Kind::Double {
387-
shell.publish(message.clone());
459+
shell.publish(reaction.react(position));
388460
}
389461

390462
state.previous_click = Some(new_click);
@@ -397,30 +469,40 @@ fn update<Message: Clone, Theme, Renderer>(
397469
}
398470
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
399471
| Event::Touch(touch::Event::FingerLifted { .. }) => {
400-
if let Some(message) = widget.on_release.as_ref() {
401-
shell.publish(message.clone());
472+
if let Some(reaction) = widget.on_release.as_ref() {
473+
if let Some(message) = reaction.react_maybe(cursor_position) {
474+
shell.publish(message);
475+
}
402476
}
403477
}
404478
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) => {
405-
if let Some(message) = widget.on_right_press.as_ref() {
406-
shell.publish(message.clone());
407-
shell.capture_event();
479+
if let Some(reaction) = widget.on_right_press.as_ref() {
480+
if let Some(message) = reaction.react_maybe(cursor_position) {
481+
shell.publish(message.clone());
482+
shell.capture_event();
483+
}
408484
}
409485
}
410486
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Right)) => {
411-
if let Some(message) = widget.on_right_release.as_ref() {
412-
shell.publish(message.clone());
487+
if let Some(reaction) = widget.on_right_release.as_ref() {
488+
if let Some(message) = reaction.react_maybe(cursor_position) {
489+
shell.publish(message);
490+
}
413491
}
414492
}
415493
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Middle)) => {
416-
if let Some(message) = widget.on_middle_press.as_ref() {
417-
shell.publish(message.clone());
418-
shell.capture_event();
494+
if let Some(reaction) = widget.on_middle_press.as_ref() {
495+
if let Some(message) = reaction.react_maybe(cursor_position) {
496+
shell.publish(message.clone());
497+
shell.capture_event();
498+
}
419499
}
420500
}
421501
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Middle)) => {
422-
if let Some(message) = widget.on_middle_release.as_ref() {
423-
shell.publish(message.clone());
502+
if let Some(reaction) = widget.on_middle_release.as_ref() {
503+
if let Some(message) = reaction.react_maybe(cursor_position) {
504+
shell.publish(message);
505+
}
424506
}
425507
}
426508
Event::Mouse(mouse::Event::WheelScrolled { delta }) => {
@@ -432,3 +514,29 @@ fn update<Message: Clone, Theme, Renderer>(
432514
_ => {}
433515
}
434516
}
517+
518+
enum Reaction<'a, Message> {
519+
Message(Message),
520+
MessageWithPosition(Box<dyn Fn(Point) -> Message + 'a>),
521+
}
522+
523+
impl<Message> Reaction<'_, Message>
524+
where
525+
Message: Clone,
526+
{
527+
pub(crate) fn react_maybe(&self, position: Option<Point>) -> Option<Message> {
528+
let position = position?;
529+
530+
Some(match self {
531+
Self::Message(message) => message.clone(),
532+
Self::MessageWithPosition(creator) => (creator)(position),
533+
})
534+
}
535+
536+
pub(crate) fn react(&self, position: Point) -> Message {
537+
match self {
538+
Self::Message(message) => message.clone(),
539+
Self::MessageWithPosition(creator) => (creator)(position),
540+
}
541+
}
542+
}

0 commit comments

Comments
 (0)