freya_native_core/
events.rs

1use std::str::FromStr;
2
3use smallvec::SmallVec;
4
5#[derive(Clone, Copy, PartialEq, Debug, Hash)]
6pub enum EventName {
7    Click,
8    MiddleClick,
9    RightClick,
10
11    MouseUp,
12    MouseDown,
13    MouseMove,
14    MouseEnter,
15    MouseLeave,
16
17    Wheel,
18
19    PointerOver,
20    PointerDown,
21    PointerEnter,
22    PointerLeave,
23    PointerUp,
24
25    KeyDown,
26    KeyUp,
27    GlobalKeyDown,
28    GlobalKeyUp,
29
30    TouchCancel,
31    TouchStart,
32    TouchMove,
33    TouchEnd,
34
35    GlobalClick,
36    GlobalPointerUp,
37    GlobalMouseDown,
38    GlobalMouseMove,
39    GlobalFileHover,
40    GlobalFileHoverCancelled,
41
42    FileDrop,
43}
44
45impl FromStr for EventName {
46    type Err = ();
47
48    fn from_str(txt: &str) -> Result<Self, Self::Err> {
49        match txt {
50            "click" => Ok(EventName::Click),
51            "rightclick" => Ok(EventName::RightClick),
52            "middleclick" => Ok(EventName::MiddleClick),
53            "mouseup" => Ok(EventName::MouseUp),
54            "mousedown" => Ok(EventName::MouseDown),
55            "mousemove" => Ok(EventName::MouseMove),
56            "mouseenter" => Ok(EventName::MouseEnter),
57            "mouseleave" => Ok(EventName::MouseLeave),
58            "wheel" => Ok(EventName::Wheel),
59            "pointermove" => Ok(EventName::PointerOver),
60            "pointerdown" => Ok(EventName::PointerDown),
61            "pointerenter" => Ok(EventName::PointerEnter),
62            "pointerleave" => Ok(EventName::PointerLeave),
63            "pointerup" => Ok(EventName::PointerUp),
64            "keydown" => Ok(EventName::KeyDown),
65            "keyup" => Ok(EventName::KeyUp),
66            "globalkeydown" => Ok(EventName::GlobalKeyDown),
67            "globalkeyup" => Ok(EventName::GlobalKeyUp),
68            "touchcancel" => Ok(EventName::TouchCancel),
69            "touchstart" => Ok(EventName::TouchStart),
70            "touchmove" => Ok(EventName::TouchMove),
71            "touchend" => Ok(EventName::TouchEnd),
72            "globalclick" => Ok(EventName::GlobalClick),
73            "globalpointerup" => Ok(EventName::GlobalPointerUp),
74            "globalmousedown" => Ok(EventName::GlobalMouseDown),
75            "globalmousemove" => Ok(EventName::GlobalMouseMove),
76            "filedrop" => Ok(EventName::FileDrop),
77            "globalfilehover" => Ok(EventName::GlobalFileHover),
78            "globalfilehovercancelled" => Ok(EventName::GlobalFileHoverCancelled),
79            _ => Err(()),
80        }
81    }
82}
83
84impl From<EventName> for &str {
85    fn from(event: EventName) -> Self {
86        match event {
87            EventName::Click => "click",
88            EventName::MiddleClick => "middleclick",
89            EventName::RightClick => "rightclick",
90            EventName::MouseUp => "mouseup",
91            EventName::MouseDown => "mousedown",
92            EventName::MouseMove => "mousemove",
93            EventName::MouseEnter => "mouseenter",
94            EventName::MouseLeave => "mouseleave",
95            EventName::Wheel => "wheel",
96            EventName::PointerOver => "pointermove",
97            EventName::PointerDown => "pointerdown",
98            EventName::PointerEnter => "pointerenter",
99            EventName::PointerLeave => "pointerleave",
100            EventName::PointerUp => "pointerup",
101            EventName::KeyUp => "keyup",
102            EventName::KeyDown => "keydown",
103            EventName::GlobalKeyDown => "globalkeydown",
104            EventName::GlobalKeyUp => "globalkeyup",
105            EventName::TouchCancel => "touchcancel",
106            EventName::TouchStart => "touchstart",
107            EventName::TouchMove => "touchmove",
108            EventName::TouchEnd => "touchend",
109            EventName::GlobalClick => "globalclick",
110            EventName::GlobalPointerUp => "globalpointerup",
111            EventName::GlobalMouseDown => "globalmousedown",
112            EventName::GlobalMouseMove => "globalmousemove",
113            EventName::FileDrop => "filedrop",
114            EventName::GlobalFileHover => "globalfilehover",
115            EventName::GlobalFileHoverCancelled => "globalfilehovercancelled",
116        }
117    }
118}
119
120impl Eq for EventName {}
121
122impl PartialOrd for EventName {
123    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
124        Some(self.cmp(other))
125    }
126}
127
128impl Ord for EventName {
129    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
130        match self {
131            // Always prioritize leave events before anything else
132            Self::MouseLeave | Self::PointerLeave => {
133                if self == other {
134                    std::cmp::Ordering::Equal
135                } else {
136                    std::cmp::Ordering::Less
137                }
138            }
139
140            _ => std::cmp::Ordering::Greater,
141        }
142    }
143}
144
145impl EventName {
146    /// Get the equivalent to a global event
147    pub fn get_global_event(&self) -> Option<Self> {
148        match self {
149            Self::MouseUp => Some(Self::GlobalClick),
150            Self::PointerUp => Some(Self::GlobalPointerUp),
151            Self::MouseDown => Some(Self::GlobalMouseDown),
152            Self::MouseMove => Some(Self::GlobalMouseMove),
153            Self::GlobalFileHover => Some(Self::GlobalFileHover),
154            Self::GlobalFileHoverCancelled => Some(Self::GlobalFileHoverCancelled),
155            Self::KeyDown => Some(EventName::GlobalKeyDown),
156            Self::KeyUp => Some(EventName::GlobalKeyUp),
157            _ => None,
158        }
159    }
160
161    /// Some events might cause other events, like for example:
162    /// A `mousemove` might also trigger a `mouseenter`
163    /// A `mousedown` or a `touchdown` might also trigger a `pointerdown`
164    pub fn get_derived_events(&self) -> SmallVec<[Self; 4]> {
165        let mut events = SmallVec::new();
166
167        events.push(*self);
168
169        match self {
170            Self::MouseMove => {
171                events.extend([Self::MouseEnter, Self::PointerEnter, Self::PointerOver])
172            }
173            Self::TouchMove => events.extend([Self::PointerEnter, Self::PointerOver]),
174            Self::MouseDown | Self::TouchStart => events.push(Self::PointerDown),
175            Self::MouseUp | Self::MiddleClick | Self::RightClick | Self::TouchEnd => {
176                events.extend([Self::Click, Self::PointerUp])
177            }
178            Self::MouseLeave => events.push(Self::PointerLeave),
179            _ => {}
180        }
181
182        events
183    }
184
185    /// Check if the event means that the pointer (e.g. cursor) just entered a Node
186    pub fn is_enter(&self) -> bool {
187        matches!(&self, Self::MouseEnter | Self::PointerEnter)
188    }
189
190    pub fn is_global(&self) -> bool {
191        matches!(
192            &self,
193            Self::GlobalKeyDown
194                | Self::GlobalKeyUp
195                | Self::GlobalClick
196                | Self::GlobalPointerUp
197                | Self::GlobalMouseDown
198                | Self::GlobalMouseMove
199                | Self::GlobalFileHover
200                | Self::GlobalFileHoverCancelled
201        )
202    }
203
204    /// Check if it's one of the Pointer variants
205    pub fn is_pointer(&self) -> bool {
206        matches!(
207            &self,
208            Self::PointerEnter
209                | Self::PointerLeave
210                | Self::PointerOver
211                | Self::PointerDown
212                | Self::PointerUp
213                | Self::GlobalPointerUp
214        )
215    }
216
217    /// Check if the event means the cursor was moved.
218    pub fn is_moved(&self) -> bool {
219        matches!(
220            &self,
221            Self::MouseMove | Self::MouseEnter | Self::PointerEnter | Self::PointerOver
222        )
223    }
224
225    /// Check if the event means the cursor has left.
226    pub fn is_left(&self) -> bool {
227        matches!(&self, Self::MouseLeave | Self::PointerLeave)
228    }
229
230    // Bubble all events except:
231    // - Global events
232    // - Mouse movements events
233    pub fn does_bubble(&self) -> bool {
234        !self.is_moved() && !self.is_left() && !self.is_global()
235    }
236
237    /// Only let events that do not move the mouse, go through solid nodes
238    pub fn does_go_through_solid(&self) -> bool {
239        matches!(self, Self::GlobalKeyDown | Self::GlobalKeyUp)
240    }
241
242    /// Check if this event can change the hover state of a Node.
243    pub fn is_hovered(&self) -> bool {
244        matches!(
245            self,
246            Self::MouseMove | Self::MouseEnter | Self::PointerOver | Self::PointerEnter
247        )
248    }
249
250    /// Check if this event can press state of a Node.
251    pub fn is_pressed(&self) -> bool {
252        matches!(self, Self::MouseDown | Self::TouchStart | Self::PointerDown)
253    }
254
255    /// Check if this event can release the press state of a Node.
256    pub fn is_released(&self) -> bool {
257        matches!(&self, Self::Click | Self::PointerUp)
258    }
259}