interactive.rs

  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}