1use std::sync::Arc;
2
3use crate::{
4 DispatchPhase, Element, EventListeners, MouseButton, MouseClickEvent, MouseDownEvent,
5 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
148pub trait Click: Interactive {
149 fn on_click(
150 mut self,
151 handler: impl Fn(&mut Self::ViewState, &MouseClickEvent, &mut ViewContext<Self::ViewState>)
152 + Send
153 + Sync
154 + 'static,
155 ) -> Self
156 where
157 Self: Sized,
158 {
159 self.listeners()
160 .mouse_click
161 .push(Arc::new(move |view, event, cx| handler(view, event, cx)));
162 self
163 }
164}