1use crate::event::{self, Event};
4use crate::layout;
5use crate::mouse;
6use crate::overlay;
7use crate::renderer;
8use crate::touch;
9use crate::widget::{tree, Operation, Tree};
10use crate::{
11 Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget,
12};
13
14#[allow(missing_debug_implementations)]
16pub struct MouseArea<'a, Message, Renderer> {
17 content: Element<'a, Message, Renderer>,
18 on_press: Option<Message>,
19 on_release: Option<Message>,
20 on_right_press: Option<Message>,
21 on_right_release: Option<Message>,
22 on_middle_press: Option<Message>,
23 on_middle_release: Option<Message>,
24}
25
26impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> {
27 #[must_use]
29 pub fn on_press(mut self, message: Message) -> Self {
30 self.on_press = Some(message);
31 self
32 }
33
34 #[must_use]
36 pub fn on_release(mut self, message: Message) -> Self {
37 self.on_release = Some(message);
38 self
39 }
40
41 #[must_use]
43 pub fn on_right_press(mut self, message: Message) -> Self {
44 self.on_right_press = Some(message);
45 self
46 }
47
48 #[must_use]
50 pub fn on_right_release(mut self, message: Message) -> Self {
51 self.on_right_release = Some(message);
52 self
53 }
54
55 #[must_use]
57 pub fn on_middle_press(mut self, message: Message) -> Self {
58 self.on_middle_press = Some(message);
59 self
60 }
61
62 #[must_use]
64 pub fn on_middle_release(mut self, message: Message) -> Self {
65 self.on_middle_release = Some(message);
66 self
67 }
68}
69
70#[derive(Default)]
72struct State {
73 }
75
76impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> {
77 pub fn new(content: impl Into<Element<'a, Message, Renderer>>) -> Self {
79 MouseArea {
80 content: content.into(),
81 on_press: None,
82 on_release: None,
83 on_right_press: None,
84 on_right_release: None,
85 on_middle_press: None,
86 on_middle_release: None,
87 }
88 }
89}
90
91impl<'a, Message, Renderer> Widget<Message, Renderer>
92 for MouseArea<'a, Message, Renderer>
93where
94 Renderer: crate::Renderer,
95 Message: Clone,
96{
97 fn tag(&self) -> tree::Tag {
98 tree::Tag::of::<State>()
99 }
100
101 fn state(&self) -> tree::State {
102 tree::State::new(State::default())
103 }
104
105 fn children(&self) -> Vec<Tree> {
106 vec![Tree::new(&self.content)]
107 }
108
109 fn diff(&self, tree: &mut Tree) {
110 tree.diff_children(std::slice::from_ref(&self.content));
111 }
112
113 fn width(&self) -> Length {
114 self.content.as_widget().width()
115 }
116
117 fn height(&self) -> Length {
118 self.content.as_widget().height()
119 }
120
121 fn layout(
122 &self,
123 renderer: &Renderer,
124 limits: &layout::Limits,
125 ) -> layout::Node {
126 self.content.as_widget().layout(renderer, limits)
127 }
128
129 fn operate(
130 &self,
131 tree: &mut Tree,
132 layout: Layout<'_>,
133 renderer: &Renderer,
134 operation: &mut dyn Operation<Message>,
135 ) {
136 self.content.as_widget().operate(
137 &mut tree.children[0],
138 layout,
139 renderer,
140 operation,
141 );
142 }
143
144 fn on_event(
145 &mut self,
146 tree: &mut Tree,
147 event: Event,
148 layout: Layout<'_>,
149 cursor_position: Point,
150 renderer: &Renderer,
151 clipboard: &mut dyn Clipboard,
152 shell: &mut Shell<'_, Message>,
153 ) -> event::Status {
154 if let event::Status::Captured = self.content.as_widget_mut().on_event(
155 &mut tree.children[0],
156 event.clone(),
157 layout,
158 cursor_position,
159 renderer,
160 clipboard,
161 shell,
162 ) {
163 return event::Status::Captured;
164 }
165
166 update(self, &event, layout, cursor_position, shell)
167 }
168
169 fn mouse_interaction(
170 &self,
171 tree: &Tree,
172 layout: Layout<'_>,
173 cursor_position: Point,
174 viewport: &Rectangle,
175 renderer: &Renderer,
176 ) -> mouse::Interaction {
177 self.content.as_widget().mouse_interaction(
178 &tree.children[0],
179 layout,
180 cursor_position,
181 viewport,
182 renderer,
183 )
184 }
185
186 fn draw(
187 &self,
188 tree: &Tree,
189 renderer: &mut Renderer,
190 theme: &Renderer::Theme,
191 renderer_style: &renderer::Style,
192 layout: Layout<'_>,
193 cursor_position: Point,
194 viewport: &Rectangle,
195 ) {
196 self.content.as_widget().draw(
197 &tree.children[0],
198 renderer,
199 theme,
200 renderer_style,
201 layout,
202 cursor_position,
203 viewport,
204 );
205 }
206
207 fn overlay<'b>(
208 &'b mut self,
209 tree: &'b mut Tree,
210 layout: Layout<'_>,
211 renderer: &Renderer,
212 ) -> Option<overlay::Element<'b, Message, Renderer>> {
213 self.content.as_widget_mut().overlay(
214 &mut tree.children[0],
215 layout,
216 renderer,
217 )
218 }
219}
220
221impl<'a, Message, Renderer> From<MouseArea<'a, Message, Renderer>>
222 for Element<'a, Message, Renderer>
223where
224 Message: 'a + Clone,
225 Renderer: 'a + crate::Renderer,
226{
227 fn from(
228 area: MouseArea<'a, Message, Renderer>,
229 ) -> Element<'a, Message, Renderer> {
230 Element::new(area)
231 }
232}
233
234fn update<Message: Clone, Renderer>(
237 widget: &mut MouseArea<'_, Message, Renderer>,
238 event: &Event,
239 layout: Layout<'_>,
240 cursor_position: Point,
241 shell: &mut Shell<'_, Message>,
242) -> event::Status {
243 if !layout.bounds().contains(cursor_position) {
244 return event::Status::Ignored;
245 }
246
247 if let Some(message) = widget.on_press.as_ref() {
248 if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
249 | Event::Touch(touch::Event::FingerPressed { .. }) = event
250 {
251 shell.publish(message.clone());
252
253 return event::Status::Captured;
254 }
255 }
256
257 if let Some(message) = widget.on_release.as_ref() {
258 if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
259 | Event::Touch(touch::Event::FingerLifted { .. }) = event
260 {
261 shell.publish(message.clone());
262
263 return event::Status::Captured;
264 }
265 }
266
267 if let Some(message) = widget.on_right_press.as_ref() {
268 if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) =
269 event
270 {
271 shell.publish(message.clone());
272
273 return event::Status::Captured;
274 }
275 }
276
277 if let Some(message) = widget.on_right_release.as_ref() {
278 if let Event::Mouse(mouse::Event::ButtonReleased(
279 mouse::Button::Right,
280 )) = event
281 {
282 shell.publish(message.clone());
283
284 return event::Status::Captured;
285 }
286 }
287
288 if let Some(message) = widget.on_middle_press.as_ref() {
289 if let Event::Mouse(mouse::Event::ButtonPressed(
290 mouse::Button::Middle,
291 )) = event
292 {
293 shell.publish(message.clone());
294
295 return event::Status::Captured;
296 }
297 }
298
299 if let Some(message) = widget.on_middle_release.as_ref() {
300 if let Event::Mouse(mouse::Event::ButtonReleased(
301 mouse::Button::Middle,
302 )) = event
303 {
304 shell.publish(message.clone());
305
306 return event::Status::Captured;
307 }
308 }
309
310 event::Status::Ignored
311}