1use std::{
2 any::Any,
3 rc::Rc,
4};
5
6use freya_elements::events::{
7 pointer::PointerType,
8 ErasedEventData,
9 FileData,
10 KeyboardData,
11 MouseData,
12 PointerData,
13 TouchData,
14 WheelData,
15};
16use freya_native_core::NodeId;
17use torin::prelude::*;
18
19use super::{
20 EventName,
21 PlatformEventData,
22 PotentialEvent,
23};
24
25#[derive(Debug, Clone, PartialEq)]
27pub struct DomEvent {
28 pub name: EventName,
29 pub node_id: NodeId,
30 pub data: DomEventData,
31 pub bubbles: bool,
32}
33
34impl Eq for DomEvent {}
35
36impl PartialOrd for DomEvent {
37 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
38 Some(self.cmp(other))
39 }
40}
41
42impl Ord for DomEvent {
43 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
44 self.name.cmp(&other.name)
45 }
46}
47
48impl DomEvent {
49 pub fn new(
50 PotentialEvent {
51 node_id,
52 name,
53 data,
54 ..
55 }: PotentialEvent,
56 node_area: Option<Area>,
57 scale_factor: f64,
58 ) -> Self {
59 let bubbles = name.does_bubble();
60
61 match data {
62 PlatformEventData::Mouse { cursor, button, .. } => {
63 let screen_coordinates = cursor / scale_factor;
64 let element_x =
65 (cursor.x - node_area.unwrap_or_default().min_x() as f64) / scale_factor;
66 let element_y =
67 (cursor.y - node_area.unwrap_or_default().min_y() as f64) / scale_factor;
68
69 let event_data = if name.is_pointer() {
70 DomEventData::Pointer(PointerData::new(
71 screen_coordinates,
72 (element_x, element_y).into(),
73 PointerType::Mouse {
74 trigger_button: button,
75 },
76 ))
77 } else {
78 DomEventData::Mouse(MouseData::new(
79 screen_coordinates,
80 (element_x, element_y).into(),
81 button,
82 ))
83 };
84
85 Self {
86 node_id,
87 name,
88 data: event_data,
89 bubbles,
90 }
91 }
92 PlatformEventData::Wheel { scroll, .. } => Self {
93 node_id,
94 name,
95 data: DomEventData::Wheel(WheelData::new(scroll.x, scroll.y)),
96 bubbles,
97 },
98 PlatformEventData::Keyboard {
99 ref key,
100 code,
101 modifiers,
102 ..
103 } => Self {
104 node_id,
105 name,
106 data: DomEventData::Keyboard(KeyboardData::new(key.clone(), code, modifiers)),
107 bubbles,
108 },
109 PlatformEventData::Touch {
110 location,
111 finger_id,
112 phase,
113 force,
114 ..
115 } => {
116 let element_x = location.x - node_area.unwrap_or_default().min_x() as f64;
117 let element_y = location.y - node_area.unwrap_or_default().min_y() as f64;
118
119 let event_data = if name.is_pointer() {
120 DomEventData::Pointer(PointerData::new(
121 location,
122 (element_x, element_y).into(),
123 PointerType::Touch {
124 finger_id,
125 phase,
126 force,
127 },
128 ))
129 } else {
130 DomEventData::Touch(TouchData::new(
131 location,
132 (element_x, element_y).into(),
133 finger_id,
134 phase,
135 force,
136 ))
137 };
138
139 Self {
140 node_id,
141 name,
142 data: event_data,
143 bubbles,
144 }
145 }
146 PlatformEventData::File { file_path, .. } => {
147 let event_data = DomEventData::File(FileData { file_path });
148
149 Self {
150 node_id,
151 name,
152 data: event_data,
153 bubbles,
154 }
155 }
156 }
157 }
158}
159
160#[derive(Debug, Clone, PartialEq)]
162pub enum DomEventData {
163 Mouse(MouseData),
164 Keyboard(KeyboardData),
165 Wheel(WheelData),
166 Touch(TouchData),
167 Pointer(PointerData),
168 File(FileData),
169}
170
171impl DomEventData {
172 pub fn any(self) -> Rc<dyn Any> {
173 match self {
174 DomEventData::Mouse(m) => Rc::new(ErasedEventData::new(Box::new(m))),
175 DomEventData::Keyboard(k) => Rc::new(ErasedEventData::new(Box::new(k))),
176 DomEventData::Wheel(w) => Rc::new(ErasedEventData::new(Box::new(w))),
177 DomEventData::Touch(t) => Rc::new(ErasedEventData::new(Box::new(t))),
178 DomEventData::Pointer(p) => Rc::new(ErasedEventData::new(Box::new(p))),
179 DomEventData::File(fd) => Rc::new(ErasedEventData::new(Box::new(fd))),
180 }
181 }
182}