11//! A container for capturing mouse events.
22
3+ use iced_renderer:: core:: Point ;
4+
35use crate :: core:: event:: { self , Event } ;
46use crate :: core:: layout;
57use crate :: core:: mouse;
@@ -26,6 +28,9 @@ pub struct MouseArea<
2628 on_right_release : Option < Message > ,
2729 on_middle_press : Option < Message > ,
2830 on_middle_release : Option < Message > ,
31+ on_mouse_enter : Option < Message > ,
32+ on_mouse_move : Option < Box < dyn Fn ( Point ) -> Message > > ,
33+ on_mouse_exit : Option < Message > ,
2934}
3035
3136impl < ' a , Message , Theme , Renderer > MouseArea < ' a , Message , Theme , Renderer > {
@@ -70,12 +75,36 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
7075 self . on_middle_release = Some ( message) ;
7176 self
7277 }
78+
79+ /// The message to emit when the mouse enters the area.
80+ #[ must_use]
81+ pub fn on_mouse_enter ( mut self , message : Message ) -> Self {
82+ self . on_mouse_enter = Some ( message) ;
83+ self
84+ }
85+
86+ /// The message to emit when the mouse moves in the area.
87+ #[ must_use]
88+ pub fn on_mouse_move < F > ( mut self , build_message : F ) -> Self
89+ where
90+ F : Fn ( Point ) -> Message + ' static ,
91+ {
92+ self . on_mouse_move = Some ( Box :: new ( build_message) ) ;
93+ self
94+ }
95+
96+ /// The message to emit when the mouse exits the area.
97+ #[ must_use]
98+ pub fn on_mouse_exit ( mut self , message : Message ) -> Self {
99+ self . on_mouse_exit = Some ( message) ;
100+ self
101+ }
73102}
74103
75104/// Local state of the [`MouseArea`].
76105#[ derive( Default ) ]
77106struct State {
78- // TODO: Support on_mouse_enter and on_mouse_exit
107+ is_hovered : bool ,
79108}
80109
81110impl < ' a , Message , Theme , Renderer > MouseArea < ' a , Message , Theme , Renderer > {
@@ -91,6 +120,9 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
91120 on_right_release : None ,
92121 on_middle_press : None ,
93122 on_middle_release : None ,
123+ on_mouse_enter : None ,
124+ on_mouse_move : None ,
125+ on_mouse_exit : None ,
94126 }
95127 }
96128}
@@ -171,7 +203,7 @@ where
171203 return event:: Status :: Captured ;
172204 }
173205
174- update ( self , & event, layout, cursor, shell)
206+ update ( self , tree , event, layout, cursor, shell)
175207 }
176208
177209 fn mouse_interaction (
@@ -246,11 +278,42 @@ where
246278/// accordingly.
247279fn update < Message : Clone , Theme , Renderer > (
248280 widget : & mut MouseArea < ' _ , Message , Theme , Renderer > ,
249- event : & Event ,
281+ tree : & mut Tree ,
282+ event : Event ,
250283 layout : Layout < ' _ > ,
251284 cursor : mouse:: Cursor ,
252285 shell : & mut Shell < ' _ , Message > ,
253286) -> event:: Status {
287+ if let Event :: Mouse ( mouse:: Event :: CursorMoved { .. } )
288+ | Event :: Touch ( touch:: Event :: FingerMoved { .. } ) = event
289+ {
290+ let state: & mut State = tree. state . downcast_mut ( ) ;
291+
292+ let was_hovered = state. is_hovered ;
293+ state. is_hovered = cursor. is_over ( layout. bounds ( ) ) ;
294+
295+ match (
296+ widget. on_mouse_enter . as_ref ( ) ,
297+ widget. on_mouse_move . as_ref ( ) ,
298+ widget. on_mouse_exit . as_ref ( ) ,
299+ ) {
300+ ( Some ( on_mouse_enter) , _, _)
301+ if state. is_hovered && !was_hovered =>
302+ {
303+ shell. publish ( on_mouse_enter. clone ( ) ) ;
304+ }
305+ ( _, Some ( on_mouse_move) , _) if state. is_hovered => {
306+ if let Some ( position) = cursor. position_in ( layout. bounds ( ) ) {
307+ shell. publish ( on_mouse_move ( position) ) ;
308+ }
309+ }
310+ ( _, _, Some ( on_mouse_exit) ) if !state. is_hovered && was_hovered => {
311+ shell. publish ( on_mouse_exit. clone ( ) ) ;
312+ }
313+ _ => { }
314+ }
315+ }
316+
254317 if !cursor. is_over ( layout. bounds ( ) ) {
255318 return event:: Status :: Ignored ;
256319 }
0 commit comments