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, 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    other_mouse_down: Option<Box<dyn FnMut(u16, &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            other_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_other_mouse_down<F>(mut self, callback: F) -> Self
 45    where
 46        F: 'static + FnMut(u16, &mut EventContext) -> bool,
 47    {
 48        self.other_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::OtherMouseDown { position, button, .. } => {
119                    if let Some(callback) = self.other_mouse_down.as_mut() {
120                        if bounds.contains_point(*position) {
121                            return callback(*button, cx);
122                        }
123                    }
124                    false
125                },
126                _ => false,
127            }
128        }
129    }
130
131    fn debug(
132        &self,
133        _: RectF,
134        _: &Self::LayoutState,
135        _: &Self::PaintState,
136        cx: &DebugContext,
137    ) -> serde_json::Value {
138        json!({
139            "type": "EventHandler",
140            "child": self.child.debug(cx),
141        })
142    }
143}