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}