1use crate::{
2 DispatchPhase, Element, EventListeners, MouseButton, MouseClickEvent, MouseDownEvent,
3 MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext,
4};
5use std::sync::Arc;
6
7pub trait Interactive: Element {
8 fn listeners(&mut self) -> &mut EventListeners<Self::ViewState>;
9
10 fn on_mouse_down(
11 mut self,
12 button: MouseButton,
13 handler: impl Fn(&mut Self::ViewState, &MouseDownEvent, &mut ViewContext<Self::ViewState>)
14 + Send
15 + Sync
16 + 'static,
17 ) -> Self
18 where
19 Self: Sized,
20 {
21 self.listeners()
22 .mouse_down
23 .push(Arc::new(move |view, event, bounds, phase, cx| {
24 if phase == DispatchPhase::Bubble
25 && event.button == button
26 && bounds.contains_point(&event.position)
27 {
28 handler(view, event, cx)
29 }
30 }));
31 self
32 }
33
34 fn on_mouse_up(
35 mut self,
36 button: MouseButton,
37 handler: impl Fn(&mut Self::ViewState, &MouseUpEvent, &mut ViewContext<Self::ViewState>)
38 + Send
39 + Sync
40 + 'static,
41 ) -> Self
42 where
43 Self: Sized,
44 {
45 self.listeners()
46 .mouse_up
47 .push(Arc::new(move |view, event, bounds, phase, cx| {
48 if phase == DispatchPhase::Bubble
49 && event.button == button
50 && bounds.contains_point(&event.position)
51 {
52 handler(view, event, cx)
53 }
54 }));
55 self
56 }
57
58 fn on_mouse_down_out(
59 mut self,
60 button: MouseButton,
61 handler: impl Fn(&mut Self::ViewState, &MouseDownEvent, &mut ViewContext<Self::ViewState>)
62 + Send
63 + Sync
64 + 'static,
65 ) -> Self
66 where
67 Self: Sized,
68 {
69 self.listeners()
70 .mouse_down
71 .push(Arc::new(move |view, event, bounds, phase, cx| {
72 if phase == DispatchPhase::Capture
73 && event.button == button
74 && !bounds.contains_point(&event.position)
75 {
76 handler(view, event, cx)
77 }
78 }));
79 self
80 }
81
82 fn on_mouse_up_out(
83 mut self,
84 button: MouseButton,
85 handler: impl Fn(&mut Self::ViewState, &MouseUpEvent, &mut ViewContext<Self::ViewState>)
86 + Send
87 + Sync
88 + 'static,
89 ) -> Self
90 where
91 Self: Sized,
92 {
93 self.listeners()
94 .mouse_up
95 .push(Arc::new(move |view, event, bounds, phase, cx| {
96 if phase == DispatchPhase::Capture
97 && event.button == button
98 && !bounds.contains_point(&event.position)
99 {
100 handler(view, event, cx);
101 }
102 }));
103 self
104 }
105
106 fn on_mouse_move(
107 mut self,
108 handler: impl Fn(&mut Self::ViewState, &MouseMoveEvent, &mut ViewContext<Self::ViewState>)
109 + Send
110 + Sync
111 + 'static,
112 ) -> Self
113 where
114 Self: Sized,
115 {
116 self.listeners()
117 .mouse_move
118 .push(Arc::new(move |view, event, bounds, phase, cx| {
119 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
120 handler(view, event, cx);
121 }
122 }));
123 self
124 }
125
126 fn on_scroll_wheel(
127 mut self,
128 handler: impl Fn(&mut Self::ViewState, &ScrollWheelEvent, &mut ViewContext<Self::ViewState>)
129 + Send
130 + Sync
131 + 'static,
132 ) -> Self
133 where
134 Self: Sized,
135 {
136 self.listeners()
137 .scroll_wheel
138 .push(Arc::new(move |view, event, bounds, phase, cx| {
139 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
140 handler(view, event, cx);
141 }
142 }));
143 self
144 }
145}
146
147pub trait Click: Interactive {
148 fn on_click(
149 mut self,
150 handler: impl Fn(&mut Self::ViewState, &MouseClickEvent, &mut ViewContext<Self::ViewState>)
151 + Send
152 + Sync
153 + 'static,
154 ) -> Self
155 where
156 Self: Sized,
157 {
158 self.listeners()
159 .mouse_click
160 .push(Arc::new(move |view, event, cx| handler(view, event, cx)));
161 self
162 }
163}