Skip to main content

fyrox_ui/
message.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Message and events module contains all possible widget messages and OS events. See [`UiMessage`] docs for more info and
22//! examples.
23
24#![warn(missing_docs)]
25
26use crate::{
27    core::{algebra::Vector2, pool::Handle, reflect::prelude::*, visitor::prelude::*},
28    UiNode, UserInterface,
29};
30use fyrox_core::pool::ObjectOrVariant;
31use fyrox_core::uuid_provider;
32use serde::{Deserialize, Serialize};
33use std::{any::Any, cell::Cell, fmt::Debug};
34use strum_macros::{AsRefStr, EnumString, VariantNames};
35
36/// Message direction allows you to distinguish from where the message has come from. Often there is a need to find out who
37/// created a message to respond properly. Imagine that we have a NumericUpDown input field for a property, and we're using
38/// some data source to feed data into the input field. When we change something in the input field by typing, it creates a
39/// message with new value. On the other hand, we often need to put new value in the input field from some code, in this case
40/// we're again creating a message. But how to understand from which "side" message has come from? Was it filled in by user,
41/// and we should create a command  to change value in the data source, or it was created from syncing code just to pass
42/// new value to UI? This problem is solved by setting a direction to a message. Also, it solves another problem: often we
43/// need to respond to a message only if it did some changes. In this case, at first we fire a message with ToWidget direction,
44/// widget catches it and checks if changes are needed, and if so, it "rethrows" message with direction FromWidget. Listeners
45/// are "subscribed" to FromWidget messages only and won't respond to ToWidget messages.
46#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Hash, Eq)]
47pub enum MessageDirection {
48    /// Used to indicate a request for changes in a widget.
49    ToWidget,
50
51    /// Used to indicate response from the widget if anything has actually changed.
52    FromWidget,
53}
54
55impl MessageDirection {
56    /// Reverses direction.
57    pub fn reverse(self) -> Self {
58        match self {
59            Self::ToWidget => Self::FromWidget,
60            Self::FromWidget => Self::ToWidget,
61        }
62    }
63}
64
65/// A trait, that is used by every messages used in the user interface. It contains utility methods that are used
66/// for downcasting and equality comparison.
67pub trait BaseMessageData: 'static + Debug + Any + Send {
68    /// Casts `self` as [`Any`] reference.
69    fn as_any(&self) -> &dyn Any;
70
71    /// Compares this message data with some other.
72    fn compare(&self, other: &dyn BaseMessageData) -> bool;
73
74    /// Clones self as boxed value.
75    fn clone_box(&self) -> Box<dyn MessageData>;
76}
77
78impl<T> BaseMessageData for T
79where
80    T: 'static + Debug + PartialEq + Any + Send + Clone + MessageData,
81{
82    fn as_any(&self) -> &dyn Any {
83        self
84    }
85
86    fn compare(&self, other: &dyn BaseMessageData) -> bool {
87        other
88            .as_any()
89            .downcast_ref::<T>()
90            .map(|other| other == self)
91            .unwrap_or_default()
92    }
93
94    fn clone_box(&self) -> Box<dyn MessageData> {
95        Box::new(self.clone())
96    }
97}
98
99/// A trait for any message that can be put to the UI message queue.
100pub trait MessageData: BaseMessageData {
101    /// Returns `true` when the message starts a new layout pass before being passed to its
102    /// destination.
103    fn need_perform_layout(&self) -> bool {
104        false
105    }
106}
107
108/// Defines a way of how the message will behave in the widget tree after it was delivered to
109/// the destination node.
110#[derive(Default, Copy, Clone, Debug, PartialEq)]
111pub enum RoutingStrategy {
112    /// A message will be passed to every ancestor widget in the hierarchy until the root.
113    #[default]
114    BubbleUp,
115    /// A message will be passed directly to a widget directly and won't be passed to any other
116    /// widget (message preview mechanism will still be used).
117    Direct,
118}
119
120/// Delivery mode
121#[derive(Default, Copy, Clone, Debug, PartialEq)]
122pub enum DeliveryMode {
123    /// The message will be at first processed by the widgets (via [`crate::control::Control::handle_routed_message`] and [`crate::control::Control::preview_message`]
124    /// methods) and then will be returned to the caller of [`UserInterface::poll_message_queue`] for further
125    /// processing. This is the default mode.
126    #[default]
127    FullCycle,
128
129    /// The message will never escape the internal message queue. The [`UserInterface::poll_message_queue`]
130    /// will never return such message, and the message will only be processed by the widgets (via
131    /// [`crate::control::Control::handle_routed_message`] and [`crate::control::Control::preview_message`] methods).
132    /// This mode is used to break message loops at the synchronization stage when the UI state is
133    /// synchronized with a data.
134    SyncOnly,
135}
136
137/// Message is a basic communication element that is used to deliver information to widget or to user code.
138///
139/// ## Motivation
140///
141/// This UI library uses message passing mechanism to communicate with widgets. This is a very simple
142/// and reliable mechanism that effectively decouples widgets from each other. There is no direct
143/// way of modifying something during runtime, you have to use messages to change the state of ui elements.
144///
145/// ## Direction
146///
147/// Each message marked with "Direction" field, which means supported routes for message. For example
148/// [`crate::button::ButtonMessage::Click`] has "Direction: To/From UI" which means that it can be
149/// sent either from internals of library or from user code. However [`crate::widget::WidgetMessage::Focus`]
150/// has "Direction: From UI" which means that only internal library code can send such messages without
151/// a risk of breaking anything.
152///
153/// ## Threading
154///
155/// UiMessage is [`Send`], it can be sent from another thread to a user interface.
156///
157/// ## Examples
158///
159/// ```rust
160/// use fyrox_ui::{
161///     core::pool::Handle, message::MessageDirection, message::UiMessage, UiNode,
162///     UserInterface, message::MessageData,
163/// };
164///
165/// // Message must be debuggable and comparable.
166/// #[derive(Debug, PartialEq, Clone)]
167/// enum MyWidgetMessage {
168///     DoSomething,
169///     Foo(u32),
170///     Bar { foo: u32, baz: u8 },
171/// }
172/// impl MessageData for MyWidgetMessage{}
173///
174/// fn using_messages(my_widget: Handle<UiNode>, ui: &UserInterface) {
175///     // Send MyWidgetMessage::DoSomething
176///     ui.send(my_widget, MyWidgetMessage::DoSomething);
177///     // Send MyWidgetMessage::Foo
178///     ui.send(my_widget, MyWidgetMessage::Foo(5));
179///     // Send MyWidgetMessage::Bar
180///     ui.send(my_widget, MyWidgetMessage::Bar {foo: 1, baz: 2});
181/// }
182/// ```
183///
184pub struct UiMessage {
185    /// Useful flag to check if a message was already handled. It could be used to mark messages as "handled" to prevent
186    /// any further responses to them. It is especially useful in bubble message routing, when a message is passed through
187    /// the entire chain of parent nodes starting from current. In this, you can mark a message as "handled" and also check
188    /// if it is handled or not. For example, this is used in [`crate::tree::Tree`] implementation, to prevent double-click
189    /// to close all the parent trees from current.
190    pub handled: Cell<bool>,
191
192    /// Actual message data. Use [`UiMessage::data`] method to try to downcast the internal data to a specific type.
193    pub data: Box<dyn MessageData>,
194
195    /// Handle of node that will receive message. Please note that **all** nodes in hierarchy will also receive this message,
196    /// order is "up-on-tree" (so-called "bubble" message routing).
197    pub destination: Handle<UiNode>,
198
199    /// Indicates the direction of the message. See [`MessageDirection`] docs for more info.
200    pub direction: MessageDirection,
201
202    /// Defines a way of how the message will behave in the widget tree after it was delivered to
203    /// the destination node. Default is bubble routing. See [`RoutingStrategy`] for more info.
204    pub routing_strategy: RoutingStrategy,
205
206    /// Message delivery mode. See [`DeliveryMode`] docs for more info.
207    pub delivery_mode: DeliveryMode,
208
209    /// A custom user flags. Use it if `handled` flag is not enough.
210    pub flags: u64,
211}
212
213/// Compares the new value with the existing one, and if they do not match, sets the new value to it
214/// and sends the given message back to the message queue with the opposite direction. This function
215/// is useful to reduce boilerplate code when reacting to widget messages.
216pub fn compare_and_set<T>(
217    value: &mut T,
218    new_value: &T,
219    message: &UiMessage,
220    ui: &UserInterface,
221) -> bool
222where
223    T: PartialEq + Clone,
224{
225    if value != new_value {
226        *value = new_value.clone();
227        ui.send_message(message.reverse());
228        true
229    } else {
230        false
231    }
232}
233
234impl Debug for UiMessage {
235    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236        write!(
237            f,
238            "UiMessage({}:({})",
239            match self.direction {
240                MessageDirection::ToWidget => "To",
241                MessageDirection::FromWidget => "From",
242            },
243            self.destination
244        )?;
245        if self.handled.get() {
246            write!(f, ",handled")?;
247        }
248        if self.flags != 0 {
249            write!(f, ",flags:{}", self.flags)?;
250        }
251        match self.delivery_mode {
252            DeliveryMode::FullCycle => {
253                write!(f, ",full cycle")?;
254            }
255            DeliveryMode::SyncOnly => {
256                write!(f, ",sync only")?;
257            }
258        }
259        write!(f, "):{:?}", self.data)
260    }
261}
262
263impl Clone for UiMessage {
264    fn clone(&self) -> Self {
265        Self {
266            handled: self.handled.clone(),
267            data: self.data.clone_box(),
268            destination: self.destination,
269            direction: self.direction,
270            routing_strategy: self.routing_strategy,
271            delivery_mode: Default::default(),
272            flags: self.flags,
273        }
274    }
275}
276
277impl PartialEq for UiMessage {
278    fn eq(&self, other: &Self) -> bool {
279        self.handled == other.handled
280            && self.data.compare(&*other.data)
281            && self.destination == other.destination
282            && self.routing_strategy == other.routing_strategy
283            && self.direction == other.direction
284            && self.flags == other.flags
285    }
286}
287
288impl UiMessage {
289    /// Creates new UI message with desired data.
290    pub fn with_data<T: MessageData>(data: T) -> Self {
291        Self {
292            handled: Cell::new(false),
293            data: Box::new(data),
294            destination: Default::default(),
295            direction: MessageDirection::ToWidget,
296            routing_strategy: Default::default(),
297            delivery_mode: Default::default(),
298            flags: 0,
299        }
300    }
301
302    /// Creates a new UI message with the given data for the specified widget.
303    pub fn for_widget(
304        handle: Handle<impl ObjectOrVariant<UiNode>>,
305        data: impl MessageData,
306    ) -> Self {
307        Self::with_data(data)
308            .with_destination(handle.transmute())
309            .with_direction(MessageDirection::ToWidget)
310    }
311
312    /// Creates a new UI message with the given data to be posted from the name of the specified
313    /// widget.
314    pub fn from_widget(
315        handle: Handle<impl ObjectOrVariant<UiNode>>,
316        data: impl MessageData,
317    ) -> Self {
318        Self::with_data(data)
319            .with_destination(handle.transmute())
320            .with_direction(MessageDirection::FromWidget)
321    }
322
323    /// Sets the desired destination of the message.
324    pub fn with_destination(mut self, destination: Handle<UiNode>) -> Self {
325        self.destination = destination;
326        self
327    }
328
329    /// Sets the desired direction of the message.
330    pub fn with_direction(mut self, direction: MessageDirection) -> Self {
331        self.direction = direction;
332        self
333    }
334
335    /// Sets the desired handled flag of the message.
336    pub fn with_handled(self, handled: bool) -> Self {
337        self.handled.set(handled);
338        self
339    }
340
341    /// Sets the desired routing strategy.
342    pub fn with_routing_strategy(mut self, routing_strategy: RoutingStrategy) -> Self {
343        self.routing_strategy = routing_strategy;
344        self
345    }
346
347    /// Sets the desired delivery mode for the message.
348    pub fn with_delivery_mode(mut self, delivery_mode: DeliveryMode) -> Self {
349        self.delivery_mode = delivery_mode;
350        self
351    }
352
353    /// Sets the desired flags of the message.
354    pub fn with_flags(mut self, flags: u64) -> Self {
355        self.flags = flags;
356        self
357    }
358
359    /// Creates a new copy of the message with reversed direction. Typical use case is to re-send messages to create "response"
360    /// in a widget. For example, you have a float input field, and it has a Value message. When the input field receives a Value message
361    /// with [`MessageDirection::ToWidget`] it checks if value needs to be changed and if it does, it re-sends the same message, but with
362    /// reversed direction back to message queue so every "listener" can reach properly. The input field won't react at
363    /// [`MessageDirection::FromWidget`] message so there will be no infinite message loop.
364    #[must_use = "method creates new value which must be used"]
365    pub fn reverse(&self) -> Self {
366        Self {
367            handled: self.handled.clone(),
368            data: self.data.clone_box(),
369            destination: self.destination,
370            direction: self.direction.reverse(),
371            routing_strategy: self.routing_strategy,
372            delivery_mode: self.delivery_mode,
373            flags: self.flags,
374        }
375    }
376
377    /// Checks if the message comes from the specified widget (via [`Self::is_from`]) and the data
378    /// type matches the given type and returns a reference to the data.
379    ///
380    /// ## Example
381    ///
382    /// ```rust
383    /// # use fyrox_core::pool::Handle;
384    /// # use fyrox_ui::message::{MessageDirection, MessageData, UiMessage};
385    /// # use fyrox_ui::UiNode;
386    /// # let widget_handle = Handle::<UiNode>::NONE;
387    /// # #[derive(Debug, Clone, PartialEq)]
388    /// # struct MyMessage;
389    /// # impl MessageData for MyMessage {}
390    /// # let message = UiMessage::with_data(MyMessage);
391    /// if let Some(data) = message.data_from::<MyMessage>(widget_handle) {
392    ///     // Do something
393    /// }
394    /// ```
395    ///
396    /// This method call is essentially a shortcut for:
397    ///
398    /// ```rust
399    /// # use fyrox_core::pool::Handle;
400    /// # use fyrox_ui::message::{MessageData, MessageDirection, UiMessage};
401    /// # use fyrox_ui::UiNode;
402    /// # let widget_handle = Handle::<UiNode>::NONE;
403    /// # #[derive(Debug, Clone, PartialEq)]
404    /// # struct MyMessage;
405    /// # impl MessageData for MyMessage {}
406    /// # let message = UiMessage::with_data(MyMessage);
407    /// if message.destination() == widget_handle && message.direction() == MessageDirection::FromWidget {
408    ///     if let Some(data) = message.data::<MyMessage>() {
409    ///         // Do something
410    ///     }
411    /// }
412    /// ```
413    pub fn data_from<T: MessageData>(
414        &self,
415        handle: Handle<impl ObjectOrVariant<UiNode>>,
416    ) -> Option<&T> {
417        if self.is_from(handle) {
418            self.data()
419        } else {
420            None
421        }
422    }
423
424    /// Checks if the message was sent to the specified widget (via [`Self::is_for`]) and the data
425    /// type matches the given type and returns a reference to the data.
426    ///
427    /// ## Example
428    ///
429    /// ```rust
430    /// # use fyrox_core::pool::Handle;
431    /// # use fyrox_ui::message::{MessageDirection, MessageData, UiMessage};
432    /// # use fyrox_ui::UiNode;
433    /// # let widget_handle = Handle::<UiNode>::NONE;
434    /// # #[derive(Debug, Clone, PartialEq)]
435    /// # struct MyMessage;
436    /// # impl MessageData for MyMessage {}
437    /// # let message = UiMessage::with_data(MyMessage);
438    /// if let Some(data) = message.data_for::<MyMessage>(widget_handle) {
439    ///     // Do something
440    /// }
441    /// ```
442    ///
443    /// This method call is essentially a shortcut for:
444    ///
445    /// ```rust
446    /// # use fyrox_core::pool::Handle;
447    /// # use fyrox_ui::message::{MessageData, MessageDirection, UiMessage};
448    /// # use fyrox_ui::UiNode;
449    /// # let widget_handle = Handle::<UiNode>::NONE;
450    /// # #[derive(Debug, Clone, PartialEq)]
451    /// # struct MyMessage;
452    /// # impl MessageData for MyMessage {}
453    /// # let message = UiMessage::with_data(MyMessage);
454    /// if message.destination() == widget_handle && message.direction() == MessageDirection::ToWidget {
455    ///     if let Some(data) = message.data::<MyMessage>() {
456    ///         // Do something
457    ///     }
458    /// }
459    /// ```
460    pub fn data_for<T: MessageData>(
461        &self,
462        handle: Handle<impl ObjectOrVariant<UiNode>>,
463    ) -> Option<&T> {
464        if self.is_for(handle) {
465            self.data()
466        } else {
467            None
468        }
469    }
470
471    /// Checks whether the message destination node handle matches the given one and the message
472    /// direction is [`MessageDirection::FromWidget`].
473    pub fn is_from(&self, handle: Handle<impl ObjectOrVariant<UiNode>>) -> bool {
474        self.destination == handle && self.direction == MessageDirection::FromWidget
475    }
476
477    /// Checks whether the message destination node handle matches the given one and the message
478    /// direction is [`MessageDirection::ToWidget`].
479    pub fn is_for(&self, handle: Handle<impl ObjectOrVariant<UiNode>>) -> bool {
480        self.destination == handle && self.direction == MessageDirection::ToWidget
481    }
482
483    /// Returns destination widget handle of the message.
484    pub fn destination(&self) -> Handle<UiNode> {
485        self.destination
486    }
487
488    /// Tries to downcast current data of the message to a particular type.
489    pub fn data<T: MessageData>(&self) -> Option<&T> {
490        (*self.data).as_any().downcast_ref::<T>()
491    }
492
493    /// Sets handled flag.
494    pub fn set_handled(&self, handled: bool) {
495        self.handled.set(handled);
496    }
497
498    /// Returns handled flag.
499    pub fn handled(&self) -> bool {
500        self.handled.get()
501    }
502
503    /// Returns direction of the message.
504    pub fn direction(&self) -> MessageDirection {
505        self.direction
506    }
507
508    /// Returns perform layout flag.
509    pub fn need_perform_layout(&self) -> bool {
510        self.data.need_perform_layout()
511    }
512
513    /// Checks if the message has particular flags.
514    pub fn has_flags(&self, flags: u64) -> bool {
515        self.flags & flags != 0
516    }
517}
518
519/// Mouse button state.
520#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
521pub enum ButtonState {
522    /// Pressed state.
523    Pressed,
524    /// Released state.
525    Released,
526}
527
528/// A set of possible mouse buttons.
529#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Default, Visit, Reflect)]
530pub enum MouseButton {
531    /// Left mouse button.
532    #[default]
533    Left,
534    /// Right mouse button.
535    Right,
536    /// Middle mouse button.
537    Middle,
538    /// Back mouse button.
539    Back,
540    /// Forward mouse button.
541    Forward,
542    /// Any other mouse button.
543    Other(u16),
544}
545
546/// A set of possible touch phases
547#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
548pub enum TouchPhase {
549    /// Touch started
550    Started,
551    /// Touch and drag
552    Moved,
553    /// Touch ended
554    Ended,
555    /// Touch cancelled
556    Cancelled,
557}
558
559/// Describes the force of a touch event
560#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
561pub enum Force {
562    /// On iOS, the force is calibrated so that the same number corresponds to
563    /// roughly the same amount of pressure on the screen regardless of the
564    /// device.
565    Calibrated {
566        /// The force of the touch, where a value of 1.0 represents the force of
567        /// an average touch (predetermined by the system, not user-specific).
568        ///
569        /// The force reported by Apple Pencil is measured along the axis of the
570        /// pencil. If you want a force perpendicular to the device, you need to
571        /// calculate this value using the `altitude_angle` value.
572        force: [u8; 8],
573        /// The maximum possible force for a touch.
574        ///
575        /// The value of this field is sufficiently high to provide a wide
576        /// dynamic range for values of the `force` field.
577        max_possible_force: [u8; 8],
578        /// The altitude (in radians) of the stylus.
579        ///
580        /// A value of 0 radians indicates that the stylus is parallel to the
581        /// surface. The value of this property is Pi/2 when the stylus is
582        /// perpendicular to the surface.
583        altitude_angle: Option<[u8; 8]>,
584    },
585    /// If the platform reports the force as normalized, we have no way of
586    /// knowing how much pressure 1.0 corresponds to – we know it's the maximum
587    /// amount of force, but as to how much force, you might either have to
588    /// press really, really hard, or not hard at all, depending on the device.
589    Normalized([u8; 8]),
590}
591
592impl Force {
593    /// Returns the force normalized to the range between 0.0 and 1.0 inclusive.
594    ///
595    /// Instead of normalizing the force, you should prefer to handle
596    /// [`Force::Calibrated`] so that the amount of force the user has to apply is
597    /// consistent across devices.
598    pub fn normalized(&self) -> f64 {
599        match self {
600            Force::Calibrated {
601                force,
602                max_possible_force,
603                altitude_angle,
604            } => {
605                let force = match altitude_angle {
606                    Some(altitude_angle) => {
607                        f64::from_be_bytes(*force) / f64::from_be_bytes(*altitude_angle).sin()
608                    }
609                    None => f64::from_be_bytes(*force),
610                };
611                force / f64::from_be_bytes(*max_possible_force)
612            }
613            Force::Normalized(force) => f64::from_be_bytes(*force),
614        }
615    }
616}
617
618/// An event that an OS sends to a window, that is then can be used to "feed" the user interface so it can do some actions.
619#[derive(Debug)]
620pub enum OsEvent {
621    /// Mouse input event.
622    MouseInput {
623        /// Mouse button.
624        button: MouseButton,
625        /// Mouse button state.
626        state: ButtonState,
627    },
628    /// Cursor event.
629    CursorMoved {
630        /// New position of the cursor.
631        position: Vector2<f32>,
632    },
633    /// Keyboard input event.
634    KeyboardInput {
635        /// Code of a key.
636        button: KeyCode,
637        /// Key state.
638        state: ButtonState,
639        /// Text of the key.
640        text: String,
641    },
642    /// Keyboard modifier event (used for key combinations such as Ctrl+A, Ctrl+C, etc).
643    KeyboardModifiers(KeyboardModifiers),
644    /// Mouse wheel event, with a tuple that stores the (x, y) offsets.
645    MouseWheel(f32, f32),
646    /// Touch event.
647    Touch {
648        /// Phase of the touch event
649        phase: TouchPhase,
650        /// Screen location of touch event
651        location: Vector2<f32>,
652        /// Pressure exerted during force event
653        force: Option<Force>,
654        /// Unique touch event identifier to distinguish between fingers, for example
655        id: u64,
656    },
657}
658
659/// A set of possible keyboard modifiers.
660#[derive(
661    Debug,
662    Hash,
663    Ord,
664    PartialOrd,
665    PartialEq,
666    Eq,
667    Clone,
668    Copy,
669    Default,
670    Serialize,
671    Deserialize,
672    Reflect,
673    Visit,
674)]
675pub struct KeyboardModifiers {
676    /// `Alt` key is pressed.
677    pub alt: bool,
678    /// `Shift` key is pressed.
679    pub shift: bool,
680    /// `Ctrl` key is pressed.
681    pub control: bool,
682    /// `System` key is pressed.
683    pub system: bool,
684}
685
686impl KeyboardModifiers {
687    /// Checks if the modifiers is empty (nothing is pressed).
688    pub fn is_none(self) -> bool {
689        !self.shift && !self.control && !self.alt && !self.system
690    }
691}
692
693/// Code of a key on keyboard. Shamelessly taken from `winit` source code to match their key codes with
694/// `fyrox-ui`'s.
695#[derive(
696    Debug,
697    Hash,
698    Ord,
699    PartialOrd,
700    PartialEq,
701    Eq,
702    Clone,
703    Copy,
704    AsRefStr,
705    EnumString,
706    VariantNames,
707    Serialize,
708    Deserialize,
709    Reflect,
710    Visit,
711    Default,
712)]
713#[repr(u32)]
714#[allow(missing_docs)]
715pub enum KeyCode {
716    /// This variant is used when the key cannot be translated to any other variant.
717    #[default]
718    Unknown,
719    /// <kbd>`</kbd> on a US keyboard. This is also called a backtick or grave.
720    /// This is the <kbd>半角</kbd>/<kbd>全角</kbd>/<kbd>漢字</kbd>
721    /// (hankaku/zenkaku/kanji) key on Japanese keyboards
722    Backquote,
723    /// Used for both the US <kbd>\\</kbd> (on the 101-key layout) and also for the key
724    /// located between the <kbd>"</kbd> and <kbd>Enter</kbd> keys on row C of the 102-,
725    /// 104- and 106-key layouts.
726    /// Labeled <kbd>#</kbd> on a UK (102) keyboard.
727    Backslash,
728    /// <kbd>[</kbd> on a US keyboard.
729    BracketLeft,
730    /// <kbd>]</kbd> on a US keyboard.
731    BracketRight,
732    /// <kbd>,</kbd> on a US keyboard.
733    Comma,
734    /// <kbd>0</kbd> on a US keyboard.
735    Digit0,
736    /// <kbd>1</kbd> on a US keyboard.
737    Digit1,
738    /// <kbd>2</kbd> on a US keyboard.
739    Digit2,
740    /// <kbd>3</kbd> on a US keyboard.
741    Digit3,
742    /// <kbd>4</kbd> on a US keyboard.
743    Digit4,
744    /// <kbd>5</kbd> on a US keyboard.
745    Digit5,
746    /// <kbd>6</kbd> on a US keyboard.
747    Digit6,
748    /// <kbd>7</kbd> on a US keyboard.
749    Digit7,
750    /// <kbd>8</kbd> on a US keyboard.
751    Digit8,
752    /// <kbd>9</kbd> on a US keyboard.
753    Digit9,
754    /// <kbd>=</kbd> on a US keyboard.
755    Equal,
756    /// Located between the left <kbd>Shift</kbd> and <kbd>Z</kbd> keys.
757    /// Labeled <kbd>\\</kbd> on a UK keyboard.
758    IntlBackslash,
759    /// Located between the <kbd>/</kbd> and right <kbd>Shift</kbd> keys.
760    /// Labeled <kbd>\\</kbd> (ro) on a Japanese keyboard.
761    IntlRo,
762    /// Located between the <kbd>=</kbd> and <kbd>Backspace</kbd> keys.
763    /// Labeled <kbd>¥</kbd> (yen) on a Japanese keyboard. <kbd>\\</kbd> on a
764    /// Russian keyboard.
765    IntlYen,
766    /// <kbd>a</kbd> on a US keyboard.
767    /// Labeled <kbd>q</kbd> on an AZERTY (e.g., French) keyboard.
768    KeyA,
769    /// <kbd>b</kbd> on a US keyboard.
770    KeyB,
771    /// <kbd>c</kbd> on a US keyboard.
772    KeyC,
773    /// <kbd>d</kbd> on a US keyboard.
774    KeyD,
775    /// <kbd>e</kbd> on a US keyboard.
776    KeyE,
777    /// <kbd>f</kbd> on a US keyboard.
778    KeyF,
779    /// <kbd>g</kbd> on a US keyboard.
780    KeyG,
781    /// <kbd>h</kbd> on a US keyboard.
782    KeyH,
783    /// <kbd>i</kbd> on a US keyboard.
784    KeyI,
785    /// <kbd>j</kbd> on a US keyboard.
786    KeyJ,
787    /// <kbd>k</kbd> on a US keyboard.
788    KeyK,
789    /// <kbd>l</kbd> on a US keyboard.
790    KeyL,
791    /// <kbd>m</kbd> on a US keyboard.
792    KeyM,
793    /// <kbd>n</kbd> on a US keyboard.
794    KeyN,
795    /// <kbd>o</kbd> on a US keyboard.
796    KeyO,
797    /// <kbd>p</kbd> on a US keyboard.
798    KeyP,
799    /// <kbd>q</kbd> on a US keyboard.
800    /// Labeled <kbd>a</kbd> on an AZERTY (e.g., French) keyboard.
801    KeyQ,
802    /// <kbd>r</kbd> on a US keyboard.
803    KeyR,
804    /// <kbd>s</kbd> on a US keyboard.
805    KeyS,
806    /// <kbd>t</kbd> on a US keyboard.
807    KeyT,
808    /// <kbd>u</kbd> on a US keyboard.
809    KeyU,
810    /// <kbd>v</kbd> on a US keyboard.
811    KeyV,
812    /// <kbd>w</kbd> on a US keyboard.
813    /// Labeled <kbd>z</kbd> on an AZERTY (e.g., French) keyboard.
814    KeyW,
815    /// <kbd>x</kbd> on a US keyboard.
816    KeyX,
817    /// <kbd>y</kbd> on a US keyboard.
818    /// Labeled <kbd>z</kbd> on a QWERTZ (e.g., German) keyboard.
819    KeyY,
820    /// <kbd>z</kbd> on a US keyboard.
821    /// Labeled <kbd>w</kbd> on an AZERTY (e.g., French) keyboard, and <kbd>y</kbd> on a
822    /// QWERTZ (e.g., German) keyboard.
823    KeyZ,
824    /// <kbd>-</kbd> on a US keyboard.
825    Minus,
826    /// <kbd>.</kbd> on a US keyboard.
827    Period,
828    /// <kbd>'</kbd> on a US keyboard.
829    Quote,
830    /// <kbd>;</kbd> on a US keyboard.
831    Semicolon,
832    /// <kbd>/</kbd> on a US keyboard.
833    Slash,
834    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
835    AltLeft,
836    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
837    /// This is labeled <kbd>AltGr</kbd> on many keyboard layouts.
838    AltRight,
839    /// <kbd>Backspace</kbd> or <kbd>⌫</kbd>.
840    /// Labeled <kbd>Delete</kbd> on Apple keyboards.
841    Backspace,
842    /// <kbd>CapsLock</kbd> or <kbd>⇪</kbd>
843    CapsLock,
844    /// The application context menu key, which is typically found between the right
845    /// <kbd>Super</kbd> key and the right <kbd>Control</kbd> key.
846    ContextMenu,
847    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
848    ControlLeft,
849    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
850    ControlRight,
851    /// <kbd>Enter</kbd> or <kbd>↵</kbd>. Labeled <kbd>Return</kbd> on Apple keyboards.
852    Enter,
853    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
854    SuperLeft,
855    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
856    SuperRight,
857    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
858    ShiftLeft,
859    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
860    ShiftRight,
861    /// <kbd> </kbd> (space)
862    Space,
863    /// <kbd>Tab</kbd> or <kbd>⇥</kbd>
864    Tab,
865    /// Japanese: <kbd>変</kbd> (henkan)
866    Convert,
867    /// Japanese: <kbd>カタカナ</kbd>/<kbd>ひらがな</kbd>/<kbd>ローマ字</kbd> (katakana/hiragana/romaji)
868    KanaMode,
869    /// Korean: HangulMode <kbd>한/영</kbd> (han/yeong)
870    ///
871    /// Japanese (Mac keyboard): <kbd>か</kbd> (kana)
872    Lang1,
873    /// Korean: Hanja <kbd>한</kbd> (hanja)
874    ///
875    /// Japanese (Mac keyboard): <kbd>英</kbd> (eisu)
876    Lang2,
877    /// Japanese (word-processing keyboard): Katakana
878    Lang3,
879    /// Japanese (word-processing keyboard): Hiragana
880    Lang4,
881    /// Japanese (word-processing keyboard): Zenkaku/Hankaku
882    Lang5,
883    /// Japanese: <kbd>無変換</kbd> (muhenkan)
884    NonConvert,
885    /// <kbd>⌦</kbd>. The forward delete key.
886    /// Note that on Apple keyboards, the key labelled <kbd>Delete</kbd> on the main part of
887    /// the keyboard is encoded as [`Backspace`].
888    ///
889    /// [`Backspace`]: Self::Backspace
890    Delete,
891    /// <kbd>Page Down</kbd>, <kbd>End</kbd>, or <kbd>↘</kbd>
892    End,
893    /// <kbd>Help</kbd>. Not present on standard PC keyboards.
894    Help,
895    /// <kbd>Home</kbd> or <kbd>↖</kbd>
896    Home,
897    /// <kbd>Insert</kbd> or <kbd>Ins</kbd>. Not present on Apple keyboards.
898    Insert,
899    /// <kbd>Page Down</kbd>, <kbd>PgDn</kbd>, or <kbd>⇟</kbd>
900    PageDown,
901    /// <kbd>Page Up</kbd>, <kbd>PgUp</kbd>, or <kbd>⇞</kbd>
902    PageUp,
903    /// <kbd>↓</kbd>
904    ArrowDown,
905    /// <kbd>←</kbd>
906    ArrowLeft,
907    /// <kbd>→</kbd>
908    ArrowRight,
909    /// <kbd>↑</kbd>
910    ArrowUp,
911    /// On the Mac, this is used for the numpad <kbd>Clear</kbd> key.
912    NumLock,
913    /// <kbd>0 Ins</kbd> on a keyboard. <kbd>0</kbd> on a phone or remote control
914    Numpad0,
915    /// <kbd>1 End</kbd> on a keyboard. <kbd>1</kbd> or <kbd>1 QZ</kbd> on a phone or remote control
916    Numpad1,
917    /// <kbd>2 ↓</kbd> on a keyboard. <kbd>2 ABC</kbd> on a phone or remote control
918    Numpad2,
919    /// <kbd>3 PgDn</kbd> on a keyboard. <kbd>3 DEF</kbd> on a phone or remote control
920    Numpad3,
921    /// <kbd>4 ←</kbd> on a keyboard. <kbd>4 GHI</kbd> on a phone or remote control
922    Numpad4,
923    /// <kbd>5</kbd> on a keyboard. <kbd>5 JKL</kbd> on a phone or remote control
924    Numpad5,
925    /// <kbd>6 →</kbd> on a keyboard. <kbd>6 MNO</kbd> on a phone or remote control
926    Numpad6,
927    /// <kbd>7 Home</kbd> on a keyboard. <kbd>7 PQRS</kbd> or <kbd>7 PRS</kbd> on a phone
928    /// or remote control
929    Numpad7,
930    /// <kbd>8 ↑</kbd> on a keyboard. <kbd>8 TUV</kbd> on a phone or remote control
931    Numpad8,
932    /// <kbd>9 PgUp</kbd> on a keyboard. <kbd>9 WXYZ</kbd> or <kbd>9 WXY</kbd> on a phone
933    /// or remote control
934    Numpad9,
935    /// <kbd>+</kbd>
936    NumpadAdd,
937    /// Found on the Microsoft Natural Keyboard.
938    NumpadBackspace,
939    /// <kbd>C</kbd> or <kbd>A</kbd> (All Clear). Also for use with numpads that have a
940    /// <kbd>Clear</kbd> key that is separate from the <kbd>NumLock</kbd> key. On the Mac, the
941    /// numpad <kbd>Clear</kbd> key is encoded as [`NumLock`].
942    ///
943    /// [`NumLock`]: Self::NumLock
944    NumpadClear,
945    /// <kbd>C</kbd> (Clear Entry)
946    NumpadClearEntry,
947    /// <kbd>,</kbd> (thousands separator). For locales where the thousands separator
948    /// is a "." (e.g., Brazil), this key may generate a <kbd>.</kbd>.
949    NumpadComma,
950    /// <kbd>. Del</kbd>. For locales where the decimal separator is "," (e.g.,
951    /// Brazil), this key may generate a <kbd>,</kbd>.
952    NumpadDecimal,
953    /// <kbd>/</kbd>
954    NumpadDivide,
955    NumpadEnter,
956    /// <kbd>=</kbd>
957    NumpadEqual,
958    /// <kbd>#</kbd> on a phone or remote control device. This key is typically found
959    /// below the <kbd>9</kbd> key and to the right of the <kbd>0</kbd> key.
960    NumpadHash,
961    /// <kbd>M</kbd> Add current entry to the value stored in memory.
962    NumpadMemoryAdd,
963    /// <kbd>M</kbd> Clear the value stored in memory.
964    NumpadMemoryClear,
965    /// <kbd>M</kbd> Replace the current entry with the value stored in memory.
966    NumpadMemoryRecall,
967    /// <kbd>M</kbd> Replace the value stored in memory with the current entry.
968    NumpadMemoryStore,
969    /// <kbd>M</kbd> Subtract current entry from the value stored in memory.
970    NumpadMemorySubtract,
971    /// <kbd>*</kbd> on a keyboard. For use with numpads that provide mathematical
972    /// operations (<kbd>+</kbd>, <kbd>-</kbd> <kbd>*</kbd> and <kbd>/</kbd>).
973    ///
974    /// Use `NumpadStar` for the <kbd>*</kbd> key on phones and remote controls.
975    NumpadMultiply,
976    /// <kbd>(</kbd> Found on the Microsoft Natural Keyboard.
977    NumpadParenLeft,
978    /// <kbd>)</kbd> Found on the Microsoft Natural Keyboard.
979    NumpadParenRight,
980    /// <kbd>*</kbd> on a phone or remote control device.
981    ///
982    /// This key is typically found below the <kbd>7</kbd> key and to the left of
983    /// the <kbd>0</kbd> key.
984    ///
985    /// Use <kbd>"NumpadMultiply"</kbd> for the <kbd>*</kbd> key on
986    /// numeric keypads.
987    NumpadStar,
988    /// <kbd>-</kbd>
989    NumpadSubtract,
990    /// <kbd>Esc</kbd> or <kbd>⎋</kbd>
991    Escape,
992    /// <kbd>Fn</kbd> This is typically a hardware key that does not generate a separate code.
993    Fn,
994    /// <kbd>FLock</kbd> or <kbd>FnLock</kbd>. Function Lock key. Found on the Microsoft
995    /// Natural Keyboard.
996    FnLock,
997    /// <kbd>PrtScr SysRq</kbd> or <kbd>Print Screen</kbd>
998    PrintScreen,
999    /// <kbd>Scroll Lock</kbd>
1000    ScrollLock,
1001    /// <kbd>Pause Break</kbd>
1002    Pause,
1003    /// Some laptops place this key to the left of the <kbd>↑</kbd> key.
1004    ///
1005    /// This also the "back" button (triangle) on Android.
1006    BrowserBack,
1007    BrowserFavorites,
1008    /// Some laptops place this key to the right of the <kbd>↑</kbd> key.
1009    BrowserForward,
1010    /// The "home" button on Android.
1011    BrowserHome,
1012    BrowserRefresh,
1013    BrowserSearch,
1014    BrowserStop,
1015    /// <kbd>Eject</kbd> or <kbd>⏏</kbd>. This key is placed in the function section on some Apple
1016    /// keyboards.
1017    Eject,
1018    /// Sometimes labelled <kbd>My Computer</kbd> on the keyboard
1019    LaunchApp1,
1020    /// Sometimes labelled <kbd>Calculator</kbd> on the keyboard
1021    LaunchApp2,
1022    LaunchMail,
1023    MediaPlayPause,
1024    MediaSelect,
1025    MediaStop,
1026    MediaTrackNext,
1027    MediaTrackPrevious,
1028    /// This key is placed in the function section on some Apple keyboards, replacing the
1029    /// <kbd>Eject</kbd> key.
1030    Power,
1031    Sleep,
1032    AudioVolumeDown,
1033    AudioVolumeMute,
1034    AudioVolumeUp,
1035    WakeUp,
1036    // Legacy modifier key. Also called "Super" in certain places.
1037    Meta,
1038    // Legacy modifier key.
1039    Hyper,
1040    Turbo,
1041    Abort,
1042    Resume,
1043    Suspend,
1044    /// Found on Sun’s USB keyboard.
1045    Again,
1046    /// Found on Sun’s USB keyboard.
1047    Copy,
1048    /// Found on Sun’s USB keyboard.
1049    Cut,
1050    /// Found on Sun’s USB keyboard.
1051    Find,
1052    /// Found on Sun’s USB keyboard.
1053    Open,
1054    /// Found on Sun’s USB keyboard.
1055    Paste,
1056    /// Found on Sun’s USB keyboard.
1057    Props,
1058    /// Found on Sun’s USB keyboard.
1059    Select,
1060    /// Found on Sun’s USB keyboard.
1061    Undo,
1062    /// Use for dedicated <kbd>ひらがな</kbd> key found on some Japanese word processing keyboards.
1063    Hiragana,
1064    /// Use for dedicated <kbd>カタカナ</kbd> key found on some Japanese word processing keyboards.
1065    Katakana,
1066    /// General-purpose function key.
1067    /// Usually found at the top of the keyboard.
1068    F1,
1069    /// General-purpose function key.
1070    /// Usually found at the top of the keyboard.
1071    F2,
1072    /// General-purpose function key.
1073    /// Usually found at the top of the keyboard.
1074    F3,
1075    /// General-purpose function key.
1076    /// Usually found at the top of the keyboard.
1077    F4,
1078    /// General-purpose function key.
1079    /// Usually found at the top of the keyboard.
1080    F5,
1081    /// General-purpose function key.
1082    /// Usually found at the top of the keyboard.
1083    F6,
1084    /// General-purpose function key.
1085    /// Usually found at the top of the keyboard.
1086    F7,
1087    /// General-purpose function key.
1088    /// Usually found at the top of the keyboard.
1089    F8,
1090    /// General-purpose function key.
1091    /// Usually found at the top of the keyboard.
1092    F9,
1093    /// General-purpose function key.
1094    /// Usually found at the top of the keyboard.
1095    F10,
1096    /// General-purpose function key.
1097    /// Usually found at the top of the keyboard.
1098    F11,
1099    /// General-purpose function key.
1100    /// Usually found at the top of the keyboard.
1101    F12,
1102    /// General-purpose function key.
1103    /// Usually found at the top of the keyboard.
1104    F13,
1105    /// General-purpose function key.
1106    /// Usually found at the top of the keyboard.
1107    F14,
1108    /// General-purpose function key.
1109    /// Usually found at the top of the keyboard.
1110    F15,
1111    /// General-purpose function key.
1112    /// Usually found at the top of the keyboard.
1113    F16,
1114    /// General-purpose function key.
1115    /// Usually found at the top of the keyboard.
1116    F17,
1117    /// General-purpose function key.
1118    /// Usually found at the top of the keyboard.
1119    F18,
1120    /// General-purpose function key.
1121    /// Usually found at the top of the keyboard.
1122    F19,
1123    /// General-purpose function key.
1124    /// Usually found at the top of the keyboard.
1125    F20,
1126    /// General-purpose function key.
1127    /// Usually found at the top of the keyboard.
1128    F21,
1129    /// General-purpose function key.
1130    /// Usually found at the top of the keyboard.
1131    F22,
1132    /// General-purpose function key.
1133    /// Usually found at the top of the keyboard.
1134    F23,
1135    /// General-purpose function key.
1136    /// Usually found at the top of the keyboard.
1137    F24,
1138    /// General-purpose function key.
1139    F25,
1140    /// General-purpose function key.
1141    F26,
1142    /// General-purpose function key.
1143    F27,
1144    /// General-purpose function key.
1145    F28,
1146    /// General-purpose function key.
1147    F29,
1148    /// General-purpose function key.
1149    F30,
1150    /// General-purpose function key.
1151    F31,
1152    /// General-purpose function key.
1153    F32,
1154    /// General-purpose function key.
1155    F33,
1156    /// General-purpose function key.
1157    F34,
1158    /// General-purpose function key.
1159    F35,
1160}
1161
1162impl KeyCode {
1163    /// Attempts to convert the key code to its respective character.
1164    pub fn to_char(self) -> Option<char> {
1165        match self {
1166            KeyCode::Backquote => Some('`'),
1167            KeyCode::Backslash => Some('\\'),
1168            KeyCode::BracketLeft => Some('['),
1169            KeyCode::BracketRight => Some(']'),
1170            KeyCode::Comma => Some(','),
1171            KeyCode::Digit0 => Some('0'),
1172            KeyCode::Digit1 => Some('1'),
1173            KeyCode::Digit2 => Some('2'),
1174            KeyCode::Digit3 => Some('3'),
1175            KeyCode::Digit4 => Some('4'),
1176            KeyCode::Digit5 => Some('5'),
1177            KeyCode::Digit6 => Some('6'),
1178            KeyCode::Digit7 => Some('7'),
1179            KeyCode::Digit8 => Some('8'),
1180            KeyCode::Digit9 => Some('9'),
1181            KeyCode::Equal => Some('='),
1182            KeyCode::KeyA => Some('A'),
1183            KeyCode::KeyB => Some('B'),
1184            KeyCode::KeyC => Some('C'),
1185            KeyCode::KeyD => Some('D'),
1186            KeyCode::KeyE => Some('E'),
1187            KeyCode::KeyF => Some('F'),
1188            KeyCode::KeyG => Some('G'),
1189            KeyCode::KeyH => Some('H'),
1190            KeyCode::KeyI => Some('I'),
1191            KeyCode::KeyJ => Some('J'),
1192            KeyCode::KeyK => Some('K'),
1193            KeyCode::KeyL => Some('L'),
1194            KeyCode::KeyM => Some('M'),
1195            KeyCode::KeyN => Some('N'),
1196            KeyCode::KeyO => Some('O'),
1197            KeyCode::KeyP => Some('P'),
1198            KeyCode::KeyQ => Some('Q'),
1199            KeyCode::KeyR => Some('R'),
1200            KeyCode::KeyS => Some('S'),
1201            KeyCode::KeyT => Some('T'),
1202            KeyCode::KeyU => Some('U'),
1203            KeyCode::KeyV => Some('V'),
1204            KeyCode::KeyW => Some('W'),
1205            KeyCode::KeyX => Some('X'),
1206            KeyCode::KeyY => Some('Y'),
1207            KeyCode::KeyZ => Some('Z'),
1208            KeyCode::Minus => Some('-'),
1209            KeyCode::Period => Some('.'),
1210            KeyCode::Quote => Some('\''),
1211            KeyCode::Semicolon => Some(';'),
1212            KeyCode::Slash => Some('/'),
1213            KeyCode::Enter => Some('\n'),
1214            KeyCode::Space => Some(' '),
1215            KeyCode::Tab => Some('\t'),
1216            KeyCode::Numpad0 => Some('0'),
1217            KeyCode::Numpad1 => Some('1'),
1218            KeyCode::Numpad2 => Some('2'),
1219            KeyCode::Numpad3 => Some('3'),
1220            KeyCode::Numpad4 => Some('4'),
1221            KeyCode::Numpad5 => Some('5'),
1222            KeyCode::Numpad6 => Some('6'),
1223            KeyCode::Numpad7 => Some('7'),
1224            KeyCode::Numpad8 => Some('8'),
1225            KeyCode::Numpad9 => Some('9'),
1226            KeyCode::NumpadAdd => Some('+'),
1227            KeyCode::NumpadComma => Some('.'),
1228            KeyCode::NumpadDecimal => Some(','),
1229            KeyCode::NumpadDivide => Some('/'),
1230            KeyCode::NumpadEnter => Some('\n'),
1231            KeyCode::NumpadEqual => Some('='),
1232            KeyCode::NumpadHash => Some('#'),
1233            KeyCode::NumpadMultiply => Some('*'),
1234            KeyCode::NumpadParenLeft => Some('('),
1235            KeyCode::NumpadParenRight => Some(')'),
1236            KeyCode::NumpadStar => Some('*'),
1237            KeyCode::NumpadSubtract => Some('-'),
1238            _ => None,
1239        }
1240    }
1241}
1242
1243impl TryFrom<char> for KeyCode {
1244    type Error = &'static str;
1245
1246    fn try_from(value: char) -> Result<Self, Self::Error> {
1247        match value {
1248            '-' | '_' => Ok(Self::Minus),
1249            '+' | '=' => Ok(Self::NumpadAdd),
1250            ' ' => Ok(Self::Space),
1251            '\\' | '|' => Ok(Self::Backslash),
1252            '/' | '?' => Ok(Self::Slash),
1253            '.' | '>' => Ok(Self::Period),
1254            ',' | '<' => Ok(Self::Comma),
1255            '\'' | '"' => Ok(Self::Quote),
1256            ';' | ':' => Ok(Self::Semicolon),
1257            '`' | '~' => Ok(Self::Backquote),
1258            '0' | ')' => Ok(Self::Digit0),
1259            '1' | '!' => Ok(Self::Digit1),
1260            '2' | '@' => Ok(Self::Digit2),
1261            '3' | '#' => Ok(Self::Digit3),
1262            '4' | '$' => Ok(Self::Digit4),
1263            '5' | '%' => Ok(Self::Digit5),
1264            '6' | '^' => Ok(Self::Digit6),
1265            '7' | '&' => Ok(Self::Digit7),
1266            '8' | '*' => Ok(Self::Digit8),
1267            '9' | '(' => Ok(Self::Digit9),
1268            'a' | 'A' => Ok(Self::KeyA),
1269            'b' | 'B' => Ok(Self::KeyB),
1270            'c' | 'C' => Ok(Self::KeyC),
1271            'd' | 'D' => Ok(Self::KeyD),
1272            'e' | 'E' => Ok(Self::KeyE),
1273            'f' | 'F' => Ok(Self::KeyF),
1274            'g' | 'G' => Ok(Self::KeyG),
1275            'h' | 'H' => Ok(Self::KeyH),
1276            'i' | 'I' => Ok(Self::KeyI),
1277            'j' | 'J' => Ok(Self::KeyJ),
1278            'k' | 'K' => Ok(Self::KeyK),
1279            'l' | 'L' => Ok(Self::KeyL),
1280            'm' | 'M' => Ok(Self::KeyM),
1281            'n' | 'N' => Ok(Self::KeyN),
1282            'o' | 'O' => Ok(Self::KeyO),
1283            'p' | 'P' => Ok(Self::KeyP),
1284            'q' | 'Q' => Ok(Self::KeyQ),
1285            'r' | 'R' => Ok(Self::KeyR),
1286            's' | 'S' => Ok(Self::KeyS),
1287            't' | 'T' => Ok(Self::KeyT),
1288            'u' | 'U' => Ok(Self::KeyU),
1289            'v' | 'V' => Ok(Self::KeyV),
1290            'w' | 'W' => Ok(Self::KeyW),
1291            'x' | 'X' => Ok(Self::KeyX),
1292            'y' | 'Y' => Ok(Self::KeyY),
1293            'z' | 'Z' => Ok(Self::KeyZ),
1294            '[' | '{' => Ok(Self::BracketLeft),
1295            ']' | '}' => Ok(Self::BracketRight),
1296            _ => Err("unsupported"),
1297        }
1298    }
1299}
1300
1301/// A fixed set of cursor icons that available on most OSes.
1302#[derive(
1303    Debug,
1304    Copy,
1305    Clone,
1306    PartialEq,
1307    Eq,
1308    Hash,
1309    Default,
1310    Visit,
1311    Reflect,
1312    AsRefStr,
1313    EnumString,
1314    VariantNames,
1315)]
1316pub enum CursorIcon {
1317    /// The platform-dependent default cursor. Often rendered as arrow.
1318    #[default]
1319    Default,
1320
1321    /// A context menu is available for the object under the cursor. Often
1322    /// rendered as an arrow with a small menu-like graphic next to it.
1323    ContextMenu,
1324
1325    /// Help is available for the object under the cursor. Often rendered as a
1326    /// question mark or a balloon.
1327    Help,
1328
1329    /// The cursor is a pointer that indicates a link. Often rendered as the
1330    /// backside of a hand with the index finger extended.
1331    Pointer,
1332
1333    /// A progress indicator. The program is performing some processing, but is
1334    /// different from [`CursorIcon::Wait`] in that the user may still interact
1335    /// with the program.
1336    Progress,
1337
1338    /// Indicates that the program is busy and the user should wait. Often
1339    /// rendered as a watch or hourglass.
1340    Wait,
1341
1342    /// Indicates that a cell or set of cells may be selected. Often rendered as
1343    /// a thick plus-sign with a dot in the middle.
1344    Cell,
1345
1346    /// A simple crosshair (e.g., short line segments resembling a "+" sign).
1347    /// Often used to indicate a two-dimensional bitmap selection mode.
1348    Crosshair,
1349
1350    /// Indicates text that may be selected. Often rendered as an I-beam.
1351    Text,
1352
1353    /// Indicates vertical-text that may be selected. Often rendered as a
1354    /// horizontal I-beam.
1355    VerticalText,
1356
1357    /// Indicates an alias of/shortcut to something is to be created. Often
1358    /// rendered as an arrow with a small curved arrow next to it.
1359    Alias,
1360
1361    /// Indicates something is to be copied. Often rendered as an arrow with a
1362    /// small plus sign next to it.
1363    Copy,
1364
1365    /// Indicates something is to be moved.
1366    Move,
1367
1368    /// Indicates that the dragged item cannot be dropped at the current cursor
1369    /// location. Often rendered as a hand or pointer with a small circle with a
1370    /// line through it.
1371    NoDrop,
1372
1373    /// Indicates that the requested action will not be carried out. Often
1374    /// rendered as a circle with a line through it.
1375    NotAllowed,
1376
1377    /// Indicates that something can be grabbed (dragged to be moved). Often
1378    /// rendered as the backside of an open hand.
1379    Grab,
1380
1381    /// Indicates that something is being grabbed (dragged to be moved). Often
1382    /// rendered as the backside of a hand with fingers closed mostly out of
1383    /// view.
1384    Grabbing,
1385
1386    /// The east border to be moved.
1387    EResize,
1388
1389    /// The north border to be moved.
1390    NResize,
1391
1392    /// The north-east corner to be moved.
1393    NeResize,
1394
1395    /// The north-west corner to be moved.
1396    NwResize,
1397
1398    /// The south border to be moved.
1399    SResize,
1400
1401    /// The south-east corner to be moved.
1402    SeResize,
1403
1404    /// The south-west corner to be moved.
1405    SwResize,
1406
1407    /// The west border to be moved.
1408    WResize,
1409
1410    /// The east and west borders to be moved.
1411    EwResize,
1412
1413    /// The south and north borders to be moved.
1414    NsResize,
1415
1416    /// The north-east and south-west corners to be moved.
1417    NeswResize,
1418
1419    /// The north-west and south-east corners to be moved.
1420    NwseResize,
1421
1422    /// Indicates that the item/column can be resized horizontally. Often
1423    /// rendered as arrows pointing left and right with a vertical bar
1424    /// separating them.
1425    ColResize,
1426
1427    /// Indicates that the item/row can be resized vertically. Often rendered as
1428    /// arrows pointing up and down with a horizontal bar separating them.
1429    RowResize,
1430
1431    /// Indicates that the something can be scrolled in any direction. Often
1432    /// rendered as arrows pointing up, down, left, and right with a dot in the
1433    /// middle.
1434    AllScroll,
1435
1436    /// Indicates that something can be zoomed in. Often rendered as a
1437    /// magnifying glass with a "+" in the center of the glass.
1438    ZoomIn,
1439
1440    /// Indicates that something can be zoomed in. Often rendered as a
1441    /// magnifying glass with a "-" in the center of the glass.
1442    ZoomOut,
1443}
1444
1445uuid_provider!(CursorIcon = "da7f3a5f-9d26-460a-8e46-38da25f8a8db");