event_handler.rs

  1use pathfinder_geometry::rect::RectF;
  2use serde_json::json;
  3
  4use crate::{
  5    geometry::vector::Vector2F, DebugContext, Element, ElementBox, Event, EventContext,
  6    LayoutContext, NavigationDirection, PaintContext, SizeConstraint,
  7};
  8
  9pub struct EventHandler {
 10    child: ElementBox,
 11    capture: Option<Box<dyn FnMut(&Event, RectF, &mut EventContext) -> bool>>,
 12    mouse_down: Option<Box<dyn FnMut(&mut EventContext) -> bool>>,
 13    right_mouse_down: Option<Box<dyn FnMut(&mut EventContext) -> bool>>,
 14    navigate_mouse_down: Option<Box<dyn FnMut(NavigationDirection, &mut EventContext) -> bool>>,
 15}
 16
 17impl EventHandler {
 18    pub fn new(child: ElementBox) -> Self {
 19        Self {
 20            child,
 21            capture: None,
 22            mouse_down: None,
 23            right_mouse_down: None,
 24            navigate_mouse_down: None,
 25        }
 26    }
 27
 28    pub fn on_mouse_down<F>(mut self, callback: F) -> Self
 29    where
 30        F: 'static + FnMut(&mut EventContext) -> bool,
 31    {
 32        self.mouse_down = Some(Box::new(callback));
 33        self
 34    }
 35
 36    pub fn on_right_mouse_down<F>(mut self, callback: F) -> Self
 37    where
 38        F: 'static + FnMut(&mut EventContext) -> bool,
 39    {
 40        self.right_mouse_down = Some(Box::new(callback));
 41        self
 42    }
 43
 44    pub fn on_navigate_mouse_down<F>(mut self, callback: F) -> Self
 45    where
 46        F: 'static + FnMut(NavigationDirection, &mut EventContext) -> bool,
 47    {
 48        self.navigate_mouse_down = Some(Box::new(callback));
 49        self
 50    }
 51
 52    pub fn capture<F>(mut self, callback: F) -> Self
 53    where
 54        F: 'static + FnMut(&Event, RectF, &mut EventContext) -> bool,
 55    {
 56        self.capture = Some(Box::new(callback));
 57        self
 58    }
 59}
 60
 61impl Element for EventHandler {
 62    type LayoutState = ();
 63    type PaintState = ();
 64
 65    fn layout(
 66        &mut self,
 67        constraint: SizeConstraint,
 68        cx: &mut LayoutContext,
 69    ) -> (Vector2F, Self::LayoutState) {
 70        let size = self.child.layout(constraint, cx);
 71        (size, ())
 72    }
 73
 74    fn paint(
 75        &mut self,
 76        bounds: RectF,
 77        visible_bounds: RectF,
 78        _: &mut Self::LayoutState,
 79        cx: &mut PaintContext,
 80    ) -> Self::PaintState {
 81        self.child.paint(bounds.origin(), visible_bounds, cx);
 82    }
 83
 84    fn dispatch_event(
 85        &mut self,
 86        event: &Event,
 87        bounds: RectF,
 88        _: &mut Self::LayoutState,
 89        _: &mut Self::PaintState,
 90        cx: &mut EventContext,
 91    ) -> bool {
 92        if let Some(capture) = self.capture.as_mut() {
 93            if capture(event, bounds, cx) {
 94                return true;
 95            }
 96        }
 97
 98        if self.child.dispatch_event(event, cx) {
 99            true
100        } else {
101            match event {
102                Event::LeftMouseDown { position, .. } => {
103                    if let Some(callback) = self.mouse_down.as_mut() {
104                        if bounds.contains_point(*position) {
105                            return callback(cx);
106                        }
107                    }
108                    false
109                }
110                Event::RightMouseDown { position, .. } => {
111                    if let Some(callback) = self.right_mouse_down.as_mut() {
112                        if bounds.contains_point(*position) {
113                            return callback(cx);
114                        }
115                    }
116                    false
117                }
118                Event::NavigateMouseDown {
119                    position,
120                    direction,
121                    ..
122                } => {
123                    if let Some(callback) = self.navigate_mouse_down.as_mut() {
124                        if bounds.contains_point(*position) {
125                            return callback(*direction, cx);
126                        }
127                    }
128                    false
129                }
130                _ => false,
131            }
132        }
133    }
134
135    fn debug(
136        &self,
137        _: RectF,
138        _: &Self::LayoutState,
139        _: &Self::PaintState,
140        cx: &DebugContext,
141    ) -> serde_json::Value {
142        json!({
143            "type": "EventHandler",
144            "child": self.child.debug(cx),
145        })
146    }
147}