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 right_mouse_down: Option<Box<dyn FnMut(&mut EventContext) -> bool>>,
14 other_mouse_down: Option<Box<dyn FnMut(u16, &mut EventContext) -> bool>>,
15}
16
17impl EventHandler {
18 pub fn new(child: ElementBox) -> Self {
19 Self {
20 child,
21 capture: None,
22 mouse_down: None,
23 right_mouse_down: None,
24 other_mouse_down: None,
25 }
26 }
27
28 pub fn on_mouse_down<F>(mut self, callback: F) -> Self
29 where
30 F: 'static + FnMut(&mut EventContext) -> bool,
31 {
32 self.mouse_down = Some(Box::new(callback));
33 self
34 }
35
36 pub fn on_right_mouse_down<F>(mut self, callback: F) -> Self
37 where
38 F: 'static + FnMut(&mut EventContext) -> bool,
39 {
40 self.right_mouse_down = Some(Box::new(callback));
41 self
42 }
43
44 pub fn on_other_mouse_down<F>(mut self, callback: F) -> Self
45 where
46 F: 'static + FnMut(u16, &mut EventContext) -> bool,
47 {
48 self.other_mouse_down = Some(Box::new(callback));
49 self
50 }
51
52 pub fn capture<F>(mut self, callback: F) -> Self
53 where
54 F: 'static + FnMut(&Event, RectF, &mut EventContext) -> bool,
55 {
56 self.capture = Some(Box::new(callback));
57 self
58 }
59}
60
61impl Element for EventHandler {
62 type LayoutState = ();
63 type PaintState = ();
64
65 fn layout(
66 &mut self,
67 constraint: SizeConstraint,
68 cx: &mut LayoutContext,
69 ) -> (Vector2F, Self::LayoutState) {
70 let size = self.child.layout(constraint, cx);
71 (size, ())
72 }
73
74 fn paint(
75 &mut self,
76 bounds: RectF,
77 visible_bounds: RectF,
78 _: &mut Self::LayoutState,
79 cx: &mut PaintContext,
80 ) -> Self::PaintState {
81 self.child.paint(bounds.origin(), visible_bounds, cx);
82 }
83
84 fn dispatch_event(
85 &mut self,
86 event: &Event,
87 bounds: RectF,
88 _: &mut Self::LayoutState,
89 _: &mut Self::PaintState,
90 cx: &mut EventContext,
91 ) -> bool {
92 if let Some(capture) = self.capture.as_mut() {
93 if capture(event, bounds, cx) {
94 return true;
95 }
96 }
97
98 if self.child.dispatch_event(event, cx) {
99 true
100 } else {
101 match event {
102 Event::LeftMouseDown { position, .. } => {
103 if let Some(callback) = self.mouse_down.as_mut() {
104 if bounds.contains_point(*position) {
105 return callback(cx);
106 }
107 }
108 false
109 },
110 Event::RightMouseDown { position, .. } => {
111 if let Some(callback) = self.right_mouse_down.as_mut() {
112 if bounds.contains_point(*position) {
113 return callback(cx);
114 }
115 }
116 false
117 },
118 Event::OtherMouseDown { position, button, .. } => {
119 if let Some(callback) = self.other_mouse_down.as_mut() {
120 if bounds.contains_point(*position) {
121 return callback(*button, cx);
122 }
123 }
124 false
125 },
126 _ => false,
127 }
128 }
129 }
130
131 fn debug(
132 &self,
133 _: RectF,
134 _: &Self::LayoutState,
135 _: &Self::PaintState,
136 cx: &DebugContext,
137 ) -> serde_json::Value {
138 json!({
139 "type": "EventHandler",
140 "child": self.child.debug(cx),
141 })
142 }
143}