event_handler.rs

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