freya_core/events/
dom_event.rs

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/// Event emitted to the DOM.
26#[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/// Data of a DOM event.
161#[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}