interactive.rs

  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}