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