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}
 14
 15impl EventHandler {
 16    pub fn new(child: ElementBox) -> Self {
 17        Self {
 18            child,
 19            capture: None,
 20            mouse_down: None,
 21        }
 22    }
 23
 24    pub fn on_mouse_down<F>(mut self, callback: F) -> Self
 25    where
 26        F: 'static + FnMut(&mut EventContext) -> bool,
 27    {
 28        self.mouse_down = Some(Box::new(callback));
 29        self
 30    }
 31
 32    pub fn capture<F>(mut self, callback: F) -> Self
 33    where
 34        F: 'static + FnMut(&Event, RectF, &mut EventContext) -> bool,
 35    {
 36        self.capture = Some(Box::new(callback));
 37        self
 38    }
 39}
 40
 41impl Element for EventHandler {
 42    type LayoutState = ();
 43    type PaintState = ();
 44
 45    fn layout(
 46        &mut self,
 47        constraint: SizeConstraint,
 48        cx: &mut LayoutContext,
 49    ) -> (Vector2F, Self::LayoutState) {
 50        let size = self.child.layout(constraint, cx);
 51        (size, ())
 52    }
 53
 54    fn paint(
 55        &mut self,
 56        bounds: RectF,
 57        visible_bounds: RectF,
 58        _: &mut Self::LayoutState,
 59        cx: &mut PaintContext,
 60    ) -> Self::PaintState {
 61        self.child.paint(bounds.origin(), visible_bounds, cx);
 62    }
 63
 64    fn dispatch_event(
 65        &mut self,
 66        event: &Event,
 67        bounds: RectF,
 68        _: &mut Self::LayoutState,
 69        _: &mut Self::PaintState,
 70        cx: &mut EventContext,
 71    ) -> bool {
 72        if let Some(capture) = self.capture.as_mut() {
 73            if capture(event, bounds, cx) {
 74                return true;
 75            }
 76        }
 77
 78        if self.child.dispatch_event(event, cx) {
 79            true
 80        } else {
 81            match event {
 82                Event::LeftMouseDown { position, .. } => {
 83                    if let Some(callback) = self.mouse_down.as_mut() {
 84                        if bounds.contains_point(*position) {
 85                            return callback(cx);
 86                        }
 87                    }
 88                    false
 89                }
 90                _ => false,
 91            }
 92        }
 93    }
 94
 95    fn debug(
 96        &self,
 97        _: RectF,
 98        _: &Self::LayoutState,
 99        _: &Self::PaintState,
100        cx: &DebugContext,
101    ) -> serde_json::Value {
102        json!({
103            "type": "EventHandler",
104            "child": self.child.debug(cx),
105        })
106    }
107}