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