1use std::{any::TypeId, sync::Arc};
2
3use crate::{
4 DispatchPhase, Element, EventListeners, KeyDownEvent, KeyUpEvent, MouseButton, MouseClickEvent,
5 MouseDownEvent, MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext,
6};
7
8pub trait Interactive: Element {
9 fn listeners(&mut self) -> &mut EventListeners<Self::ViewState>;
10
11 fn on_mouse_down(
12 mut self,
13 button: MouseButton,
14 handler: impl Fn(&mut Self::ViewState, &MouseDownEvent, &mut ViewContext<Self::ViewState>)
15 + Send
16 + Sync
17 + 'static,
18 ) -> Self
19 where
20 Self: Sized,
21 {
22 self.listeners()
23 .mouse_down
24 .push(Arc::new(move |view, event, bounds, phase, cx| {
25 if phase == DispatchPhase::Bubble
26 && event.button == button
27 && bounds.contains_point(&event.position)
28 {
29 handler(view, event, cx)
30 }
31 }));
32 self
33 }
34
35 fn on_mouse_up(
36 mut self,
37 button: MouseButton,
38 handler: impl Fn(&mut Self::ViewState, &MouseUpEvent, &mut ViewContext<Self::ViewState>)
39 + Send
40 + Sync
41 + 'static,
42 ) -> Self
43 where
44 Self: Sized,
45 {
46 self.listeners()
47 .mouse_up
48 .push(Arc::new(move |view, event, bounds, phase, cx| {
49 if phase == DispatchPhase::Bubble
50 && event.button == button
51 && bounds.contains_point(&event.position)
52 {
53 handler(view, event, cx)
54 }
55 }));
56 self
57 }
58
59 fn on_mouse_down_out(
60 mut self,
61 button: MouseButton,
62 handler: impl Fn(&mut Self::ViewState, &MouseDownEvent, &mut ViewContext<Self::ViewState>)
63 + Send
64 + Sync
65 + 'static,
66 ) -> Self
67 where
68 Self: Sized,
69 {
70 self.listeners()
71 .mouse_down
72 .push(Arc::new(move |view, event, bounds, phase, cx| {
73 if phase == DispatchPhase::Capture
74 && event.button == button
75 && !bounds.contains_point(&event.position)
76 {
77 handler(view, event, cx)
78 }
79 }));
80 self
81 }
82
83 fn on_mouse_up_out(
84 mut self,
85 button: MouseButton,
86 handler: impl Fn(&mut Self::ViewState, &MouseUpEvent, &mut ViewContext<Self::ViewState>)
87 + Send
88 + Sync
89 + 'static,
90 ) -> Self
91 where
92 Self: Sized,
93 {
94 self.listeners()
95 .mouse_up
96 .push(Arc::new(move |view, event, bounds, phase, cx| {
97 if phase == DispatchPhase::Capture
98 && event.button == button
99 && !bounds.contains_point(&event.position)
100 {
101 handler(view, event, cx);
102 }
103 }));
104 self
105 }
106
107 fn on_mouse_move(
108 mut self,
109 handler: impl Fn(&mut Self::ViewState, &MouseMoveEvent, &mut ViewContext<Self::ViewState>)
110 + Send
111 + Sync
112 + 'static,
113 ) -> Self
114 where
115 Self: Sized,
116 {
117 self.listeners()
118 .mouse_move
119 .push(Arc::new(move |view, event, bounds, phase, cx| {
120 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
121 handler(view, event, cx);
122 }
123 }));
124 self
125 }
126
127 fn on_scroll_wheel(
128 mut self,
129 handler: impl Fn(&mut Self::ViewState, &ScrollWheelEvent, &mut ViewContext<Self::ViewState>)
130 + Send
131 + Sync
132 + 'static,
133 ) -> Self
134 where
135 Self: Sized,
136 {
137 self.listeners()
138 .scroll_wheel
139 .push(Arc::new(move |view, event, bounds, phase, cx| {
140 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
141 handler(view, event, cx);
142 }
143 }));
144 self
145 }
146
147 fn on_key_down(
148 mut self,
149 listener: impl Fn(
150 &mut Self::ViewState,
151 &KeyDownEvent,
152 DispatchPhase,
153 &mut ViewContext<Self::ViewState>,
154 ) + Send
155 + Sync
156 + 'static,
157 ) -> Self
158 where
159 Self: Sized,
160 {
161 self.listeners().key.push((
162 TypeId::of::<KeyDownEvent>(),
163 Arc::new(move |view, event, phase, cx| {
164 let event = event.downcast_ref().unwrap();
165 listener(view, event, phase, cx);
166 None
167 }),
168 ));
169 self
170 }
171
172 fn on_key_up(
173 mut self,
174 listener: impl Fn(&mut Self::ViewState, &KeyUpEvent, DispatchPhase, &mut ViewContext<Self::ViewState>)
175 + Send
176 + Sync
177 + 'static,
178 ) -> Self
179 where
180 Self: Sized,
181 {
182 self.listeners().key.push((
183 TypeId::of::<KeyUpEvent>(),
184 Arc::new(move |view, event, phase, cx| {
185 let event = event.downcast_ref().unwrap();
186 listener(view, event, phase, cx);
187 None
188 }),
189 ));
190 self
191 }
192
193 fn on_action<A: 'static>(
194 mut self,
195 listener: impl Fn(&mut Self::ViewState, &A, DispatchPhase, &mut ViewContext<Self::ViewState>)
196 + Send
197 + Sync
198 + 'static,
199 ) -> Self
200 where
201 Self: Sized,
202 {
203 self.listeners().key.push((
204 TypeId::of::<A>(),
205 Arc::new(move |view, event, phase, cx| {
206 let event = event.downcast_ref().unwrap();
207 listener(view, event, phase, cx);
208 None
209 }),
210 ));
211 self
212 }
213}
214
215pub trait Click: Interactive {
216 fn on_click(
217 mut self,
218 handler: impl Fn(&mut Self::ViewState, &MouseClickEvent, &mut ViewContext<Self::ViewState>)
219 + Send
220 + Sync
221 + 'static,
222 ) -> Self
223 where
224 Self: Sized,
225 {
226 self.listeners()
227 .mouse_click
228 .push(Arc::new(move |view, event, cx| handler(view, event, cx)));
229 self
230 }
231}