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 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 paint(
45 &mut self,
46 bounds: RectF,
47 _: &mut Self::LayoutState,
48 cx: &mut PaintContext,
49 ) -> Self::PaintState {
50 self.child.paint(bounds.origin(), cx);
51 }
52
53 fn dispatch_event(
54 &mut self,
55 event: &Event,
56 bounds: RectF,
57 _: &mut Self::LayoutState,
58 _: &mut Self::PaintState,
59 cx: &mut EventContext,
60 ) -> bool {
61 if self.child.dispatch_event(event, cx) {
62 true
63 } else {
64 match event {
65 Event::LeftMouseDown { position, .. } => {
66 if let Some(callback) = self.mouse_down.as_mut() {
67 if bounds.contains_point(*position) {
68 return callback(cx);
69 }
70 }
71 false
72 }
73 _ => false,
74 }
75 }
76 }
77
78 fn debug(
79 &self,
80 _: RectF,
81 _: &Self::LayoutState,
82 _: &Self::PaintState,
83 cx: &DebugContext,
84 ) -> serde_json::Value {
85 json!({
86 "type": "EventHandler",
87 "child": self.child.debug(cx),
88 })
89 }
90}