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.try_send_response(message);
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    /// Checks if the message is intended for syncing.
519    pub fn is_sync(&self) -> bool {
520        self.delivery_mode == DeliveryMode::SyncOnly
521    }
522}
523
524/// Mouse button state.
525#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
526pub enum ButtonState {
527    /// Pressed state.
528    Pressed,
529    /// Released state.
530    Released,
531}
532
533/// A set of possible mouse buttons.
534#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Default, Visit, Reflect)]
535pub enum MouseButton {
536    /// Left mouse button.
537    #[default]
538    Left,
539    /// Right mouse button.
540    Right,
541    /// Middle mouse button.
542    Middle,
543    /// Back mouse button.
544    Back,
545    /// Forward mouse button.
546    Forward,
547    /// Any other mouse button.
548    Other(u16),
549}
550
551/// A set of possible touch phases
552#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
553pub enum TouchPhase {
554    /// Touch started
555    Started,
556    /// Touch and drag
557    Moved,
558    /// Touch ended
559    Ended,
560    /// Touch cancelled
561    Cancelled,
562}
563
564/// Describes the force of a touch event
565#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Visit, Reflect)]
566pub enum Force {
567    /// On iOS, the force is calibrated so that the same number corresponds to
568    /// roughly the same amount of pressure on the screen regardless of the
569    /// device.
570    Calibrated {
571        /// The force of the touch, where a value of 1.0 represents the force of
572        /// an average touch (predetermined by the system, not user-specific).
573        ///
574        /// The force reported by Apple Pencil is measured along the axis of the
575        /// pencil. If you want a force perpendicular to the device, you need to
576        /// calculate this value using the `altitude_angle` value.
577        force: [u8; 8],
578        /// The maximum possible force for a touch.
579        ///
580        /// The value of this field is sufficiently high to provide a wide
581        /// dynamic range for values of the `force` field.
582        max_possible_force: [u8; 8],
583        /// The altitude (in radians) of the stylus.
584        ///
585        /// A value of 0 radians indicates that the stylus is parallel to the
586        /// surface. The value of this property is Pi/2 when the stylus is
587        /// perpendicular to the surface.
588        altitude_angle: Option<[u8; 8]>,
589    },
590    /// If the platform reports the force as normalized, we have no way of
591    /// knowing how much pressure 1.0 corresponds to – we know it's the maximum
592    /// amount of force, but as to how much force, you might either have to
593    /// press really, really hard, or not hard at all, depending on the device.
594    Normalized([u8; 8]),
595}
596
597impl Force {
598    /// Returns the force normalized to the range between 0.0 and 1.0 inclusive.
599    ///
600    /// Instead of normalizing the force, you should prefer to handle
601    /// [`Force::Calibrated`] so that the amount of force the user has to apply is
602    /// consistent across devices.
603    pub fn normalized(&self) -> f64 {
604        match self {
605            Force::Calibrated {
606                force,
607                max_possible_force,
608                altitude_angle,
609            } => {
610                let force = match altitude_angle {
611                    Some(altitude_angle) => {
612                        f64::from_be_bytes(*force) / f64::from_be_bytes(*altitude_angle).sin()
613                    }
614                    None => f64::from_be_bytes(*force),
615                };
616                force / f64::from_be_bytes(*max_possible_force)
617            }
618            Force::Normalized(force) => f64::from_be_bytes(*force),
619        }
620    }
621}
622
623/// 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.
624#[derive(Debug)]
625pub enum OsEvent {
626    /// Mouse input event.
627    MouseInput {
628        /// Mouse button.
629        button: MouseButton,
630        /// Mouse button state.
631        state: ButtonState,
632    },
633    /// Cursor event.
634    CursorMoved {
635        /// New position of the cursor.
636        position: Vector2<f32>,
637    },
638    /// Keyboard input event.
639    KeyboardInput {
640        /// Code of a key.
641        button: KeyCode,
642        /// Key state.
643        state: ButtonState,
644        /// Text of the key.
645        text: String,
646    },
647    /// Keyboard modifier event (used for key combinations such as Ctrl+A, Ctrl+C, etc).
648    KeyboardModifiers(KeyboardModifiers),
649    /// Mouse wheel event, with a tuple that stores the (x, y) offsets.
650    MouseWheel(f32, f32),
651    /// Touch event.
652    Touch {
653        /// Phase of the touch event
654        phase: TouchPhase,
655        /// Screen location of touch event
656        location: Vector2<f32>,
657        /// Pressure exerted during force event
658        force: Option<Force>,
659        /// Unique touch event identifier to distinguish between fingers, for example
660        id: u64,
661    },
662}
663
664/// A set of possible keyboard modifiers.
665#[derive(
666    Debug,
667    Hash,
668    Ord,
669    PartialOrd,
670    PartialEq,
671    Eq,
672    Clone,
673    Copy,
674    Default,
675    Serialize,
676    Deserialize,
677    Reflect,
678    Visit,
679)]
680pub struct KeyboardModifiers {
681    /// `Alt` key is pressed.
682    pub alt: bool,
683    /// `Shift` key is pressed.
684    pub shift: bool,
685    /// `Ctrl` key is pressed.
686    pub control: bool,
687    /// `System` key is pressed.
688    pub system: bool,
689}
690
691impl KeyboardModifiers {
692    /// Checks if the modifiers is empty (nothing is pressed).
693    pub fn is_none(self) -> bool {
694        !self.shift && !self.control && !self.alt && !self.system
695    }
696}
697
698/// Code of a key on keyboard. Shamelessly taken from `winit` source code to match their key codes with
699/// `fyrox-ui`'s.
700#[derive(
701    Debug,
702    Hash,
703    Ord,
704    PartialOrd,
705    PartialEq,
706    Eq,
707    Clone,
708    Copy,
709    AsRefStr,
710    EnumString,
711    VariantNames,
712    Serialize,
713    Deserialize,
714    Reflect,
715    Visit,
716    Default,
717)]
718#[repr(u32)]
719#[allow(missing_docs)]
720pub enum KeyCode {
721    /// This variant is used when the key cannot be translated to any other variant.
722    #[default]
723    Unknown,
724    /// <kbd>`</kbd> on a US keyboard. This is also called a backtick or grave.
725    /// This is the <kbd>半角</kbd>/<kbd>全角</kbd>/<kbd>漢字</kbd>
726    /// (hankaku/zenkaku/kanji) key on Japanese keyboards
727    Backquote,
728    /// Used for both the US <kbd>\\</kbd> (on the 101-key layout) and also for the key
729    /// located between the <kbd>"</kbd> and <kbd>Enter</kbd> keys on row C of the 102-,
730    /// 104- and 106-key layouts.
731    /// Labeled <kbd>#</kbd> on a UK (102) keyboard.
732    Backslash,
733    /// <kbd>[</kbd> on a US keyboard.
734    BracketLeft,
735    /// <kbd>]</kbd> on a US keyboard.
736    BracketRight,
737    /// <kbd>,</kbd> on a US keyboard.
738    Comma,
739    /// <kbd>0</kbd> on a US keyboard.
740    Digit0,
741    /// <kbd>1</kbd> on a US keyboard.
742    Digit1,
743    /// <kbd>2</kbd> on a US keyboard.
744    Digit2,
745    /// <kbd>3</kbd> on a US keyboard.
746    Digit3,
747    /// <kbd>4</kbd> on a US keyboard.
748    Digit4,
749    /// <kbd>5</kbd> on a US keyboard.
750    Digit5,
751    /// <kbd>6</kbd> on a US keyboard.
752    Digit6,
753    /// <kbd>7</kbd> on a US keyboard.
754    Digit7,
755    /// <kbd>8</kbd> on a US keyboard.
756    Digit8,
757    /// <kbd>9</kbd> on a US keyboard.
758    Digit9,
759    /// <kbd>=</kbd> on a US keyboard.
760    Equal,
761    /// Located between the left <kbd>Shift</kbd> and <kbd>Z</kbd> keys.
762    /// Labeled <kbd>\\</kbd> on a UK keyboard.
763    IntlBackslash,
764    /// Located between the <kbd>/</kbd> and right <kbd>Shift</kbd> keys.
765    /// Labeled <kbd>\\</kbd> (ro) on a Japanese keyboard.
766    IntlRo,
767    /// Located between the <kbd>=</kbd> and <kbd>Backspace</kbd> keys.
768    /// Labeled <kbd>¥</kbd> (yen) on a Japanese keyboard. <kbd>\\</kbd> on a
769    /// Russian keyboard.
770    IntlYen,
771    /// <kbd>a</kbd> on a US keyboard.
772    /// Labeled <kbd>q</kbd> on an AZERTY (e.g., French) keyboard.
773    KeyA,
774    /// <kbd>b</kbd> on a US keyboard.
775    KeyB,
776    /// <kbd>c</kbd> on a US keyboard.
777    KeyC,
778    /// <kbd>d</kbd> on a US keyboard.
779    KeyD,
780    /// <kbd>e</kbd> on a US keyboard.
781    KeyE,
782    /// <kbd>f</kbd> on a US keyboard.
783    KeyF,
784    /// <kbd>g</kbd> on a US keyboard.
785    KeyG,
786    /// <kbd>h</kbd> on a US keyboard.
787    KeyH,
788    /// <kbd>i</kbd> on a US keyboard.
789    KeyI,
790    /// <kbd>j</kbd> on a US keyboard.
791    KeyJ,
792    /// <kbd>k</kbd> on a US keyboard.
793    KeyK,
794    /// <kbd>l</kbd> on a US keyboard.
795    KeyL,
796    /// <kbd>m</kbd> on a US keyboard.
797    KeyM,
798    /// <kbd>n</kbd> on a US keyboard.
799    KeyN,
800    /// <kbd>o</kbd> on a US keyboard.
801    KeyO,
802    /// <kbd>p</kbd> on a US keyboard.
803    KeyP,
804    /// <kbd>q</kbd> on a US keyboard.
805    /// Labeled <kbd>a</kbd> on an AZERTY (e.g., French) keyboard.
806    KeyQ,
807    /// <kbd>r</kbd> on a US keyboard.
808    KeyR,
809    /// <kbd>s</kbd> on a US keyboard.
810    KeyS,
811    /// <kbd>t</kbd> on a US keyboard.
812    KeyT,
813    /// <kbd>u</kbd> on a US keyboard.
814    KeyU,
815    /// <kbd>v</kbd> on a US keyboard.
816    KeyV,
817    /// <kbd>w</kbd> on a US keyboard.
818    /// Labeled <kbd>z</kbd> on an AZERTY (e.g., French) keyboard.
819    KeyW,
820    /// <kbd>x</kbd> on a US keyboard.
821    KeyX,
822    /// <kbd>y</kbd> on a US keyboard.
823    /// Labeled <kbd>z</kbd> on a QWERTZ (e.g., German) keyboard.
824    KeyY,
825    /// <kbd>z</kbd> on a US keyboard.
826    /// Labeled <kbd>w</kbd> on an AZERTY (e.g., French) keyboard, and <kbd>y</kbd> on a
827    /// QWERTZ (e.g., German) keyboard.
828    KeyZ,
829    /// <kbd>-</kbd> on a US keyboard.
830    Minus,
831    /// <kbd>.</kbd> on a US keyboard.
832    Period,
833    /// <kbd>'</kbd> on a US keyboard.
834    Quote,
835    /// <kbd>;</kbd> on a US keyboard.
836    Semicolon,
837    /// <kbd>/</kbd> on a US keyboard.
838    Slash,
839    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
840    AltLeft,
841    /// <kbd>Alt</kbd>, <kbd>Option</kbd>, or <kbd>⌥</kbd>.
842    /// This is labeled <kbd>AltGr</kbd> on many keyboard layouts.
843    AltRight,
844    /// <kbd>Backspace</kbd> or <kbd>⌫</kbd>.
845    /// Labeled <kbd>Delete</kbd> on Apple keyboards.
846    Backspace,
847    /// <kbd>CapsLock</kbd> or <kbd>⇪</kbd>
848    CapsLock,
849    /// The application context menu key, which is typically found between the right
850    /// <kbd>Super</kbd> key and the right <kbd>Control</kbd> key.
851    ContextMenu,
852    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
853    ControlLeft,
854    /// <kbd>Control</kbd> or <kbd>⌃</kbd>
855    ControlRight,
856    /// <kbd>Enter</kbd> or <kbd>↵</kbd>. Labeled <kbd>Return</kbd> on Apple keyboards.
857    Enter,
858    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
859    SuperLeft,
860    /// The Windows, <kbd>⌘</kbd>, <kbd>Command</kbd>, or other OS symbol key.
861    SuperRight,
862    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
863    ShiftLeft,
864    /// <kbd>Shift</kbd> or <kbd>⇧</kbd>
865    ShiftRight,
866    /// <kbd> </kbd> (space)
867    Space,
868    /// <kbd>Tab</kbd> or <kbd>⇥</kbd>
869    Tab,
870    /// Japanese: <kbd>変</kbd> (henkan)
871    Convert,
872    /// Japanese: <kbd>カタカナ</kbd>/<kbd>ひらがな</kbd>/<kbd>ローマ字</kbd> (katakana/hiragana/romaji)
873    KanaMode,
874    /// Korean: HangulMode <kbd>한/영</kbd> (han/yeong)
875    ///
876    /// Japanese (Mac keyboard): <kbd>か</kbd> (kana)
877    Lang1,
878    /// Korean: Hanja <kbd>한</kbd> (hanja)
879    ///
880    /// Japanese (Mac keyboard): <kbd>英</kbd> (eisu)
881    Lang2,
882    /// Japanese (word-processing keyboard): Katakana
883    Lang3,
884    /// Japanese (word-processing keyboard): Hiragana
885    Lang4,
886    /// Japanese (word-processing keyboard): Zenkaku/Hankaku
887    Lang5,
888    /// Japanese: <kbd>無変換</kbd> (muhenkan)
889    NonConvert,
890    /// <kbd>⌦</kbd>. The forward delete key.
891    /// Note that on Apple keyboards, the key labelled <kbd>Delete</kbd> on the main part of
892    /// the keyboard is encoded as [`Backspace`].
893    ///
894    /// [`Backspace`]: Self::Backspace
895    Delete,
896    /// <kbd>Page Down</kbd>, <kbd>End</kbd>, or <kbd>↘</kbd>
897    End,
898    /// <kbd>Help</kbd>. Not present on standard PC keyboards.
899    Help,
900    /// <kbd>Home</kbd> or <kbd>↖</kbd>
901    Home,
902    /// <kbd>Insert</kbd> or <kbd>Ins</kbd>. Not present on Apple keyboards.
903    Insert,
904    /// <kbd>Page Down</kbd>, <kbd>PgDn</kbd>, or <kbd>⇟</kbd>
905    PageDown,
906    /// <kbd>Page Up</kbd>, <kbd>PgUp</kbd>, or <kbd>⇞</kbd>
907    PageUp,
908    /// <kbd>↓</kbd>
909    ArrowDown,
910    /// <kbd>←</kbd>
911    ArrowLeft,
912    /// <kbd>→</kbd>
913    ArrowRight,
914    /// <kbd>↑</kbd>
915    ArrowUp,
916    /// On the Mac, this is used for the numpad <kbd>Clear</kbd> key.
917    NumLock,
918    /// <kbd>0 Ins</kbd> on a keyboard. <kbd>0</kbd> on a phone or remote control
919    Numpad0,
920    /// <kbd>1 End</kbd> on a keyboard. <kbd>1</kbd> or <kbd>1 QZ</kbd> on a phone or remote control
921    Numpad1,
922    /// <kbd>2 ↓</kbd> on a keyboard. <kbd>2 ABC</kbd> on a phone or remote control
923    Numpad2,
924    /// <kbd>3 PgDn</kbd> on a keyboard. <kbd>3 DEF</kbd> on a phone or remote control
925    Numpad3,
926    /// <kbd>4 ←</kbd> on a keyboard. <kbd>4 GHI</kbd> on a phone or remote control
927    Numpad4,
928    /// <kbd>5</kbd> on a keyboard. <kbd>5 JKL</kbd> on a phone or remote control
929    Numpad5,
930    /// <kbd>6 →</kbd> on a keyboard. <kbd>6 MNO</kbd> on a phone or remote control
931    Numpad6,
932    /// <kbd>7 Home</kbd> on a keyboard. <kbd>7 PQRS</kbd> or <kbd>7 PRS</kbd> on a phone
933    /// or remote control
934    Numpad7,
935    /// <kbd>8 ↑</kbd> on a keyboard. <kbd>8 TUV</kbd> on a phone or remote control
936    Numpad8,
937    /// <kbd>9 PgUp</kbd> on a keyboard. <kbd>9 WXYZ</kbd> or <kbd>9 WXY</kbd> on a phone
938    /// or remote control
939    Numpad9,
940    /// <kbd>+</kbd>
941    NumpadAdd,
942    /// Found on the Microsoft Natural Keyboard.
943    NumpadBackspace,
944    /// <kbd>C</kbd> or <kbd>A</kbd> (All Clear). Also for use with numpads that have a
945    /// <kbd>Clear</kbd> key that is separate from the <kbd>NumLock</kbd> key. On the Mac, the
946    /// numpad <kbd>Clear</kbd> key is encoded as [`NumLock`].
947    ///
948    /// [`NumLock`]: Self::NumLock
949    NumpadClear,
950    /// <kbd>C</kbd> (Clear Entry)
951    NumpadClearEntry,
952    /// <kbd>,</kbd> (thousands separator). For locales where the thousands separator
953    /// is a "." (e.g., Brazil), this key may generate a <kbd>.</kbd>.
954    NumpadComma,
955    /// <kbd>. Del</kbd>. For locales where the decimal separator is "," (e.g.,
956    /// Brazil), this key may generate a <kbd>,</kbd>.
957    NumpadDecimal,
958    /// <kbd>/</kbd>
959    NumpadDivide,
960    NumpadEnter,
961    /// <kbd>=</kbd>
962    NumpadEqual,
963    /// <kbd>#</kbd> on a phone or remote control device. This key is typically found
964    /// below the <kbd>9</kbd> key and to the right of the <kbd>0</kbd> key.
965    NumpadHash,
966    /// <kbd>M</kbd> Add current entry to the value stored in memory.
967    NumpadMemoryAdd,
968    /// <kbd>M</kbd> Clear the value stored in memory.
969    NumpadMemoryClear,
970    /// <kbd>M</kbd> Replace the current entry with the value stored in memory.
971    NumpadMemoryRecall,
972    /// <kbd>M</kbd> Replace the value stored in memory with the current entry.
973    NumpadMemoryStore,
974    /// <kbd>M</kbd> Subtract current entry from the value stored in memory.
975    NumpadMemorySubtract,
976    /// <kbd>*</kbd> on a keyboard. For use with numpads that provide mathematical
977    /// operations (<kbd>+</kbd>, <kbd>-</kbd> <kbd>*</kbd> and <kbd>/</kbd>).
978    ///
979    /// Use `NumpadStar` for the <kbd>*</kbd> key on phones and remote controls.
980    NumpadMultiply,
981    /// <kbd>(</kbd> Found on the Microsoft Natural Keyboard.
982    NumpadParenLeft,
983    /// <kbd>)</kbd> Found on the Microsoft Natural Keyboard.
984    NumpadParenRight,
985    /// <kbd>*</kbd> on a phone or remote control device.
986    ///
987    /// This key is typically found below the <kbd>7</kbd> key and to the left of
988    /// the <kbd>0</kbd> key.
989    ///
990    /// Use <kbd>"NumpadMultiply"</kbd> for the <kbd>*</kbd> key on
991    /// numeric keypads.
992    NumpadStar,
993    /// <kbd>-</kbd>
994    NumpadSubtract,
995    /// <kbd>Esc</kbd> or <kbd>⎋</kbd>
996    Escape,
997    /// <kbd>Fn</kbd> This is typically a hardware key that does not generate a separate code.
998    Fn,
999    /// <kbd>FLock</kbd> or <kbd>FnLock</kbd>. Function Lock key. Found on the Microsoft
1000    /// Natural Keyboard.
1001    FnLock,
1002    /// <kbd>PrtScr SysRq</kbd> or <kbd>Print Screen</kbd>
1003    PrintScreen,
1004    /// <kbd>Scroll Lock</kbd>
1005    ScrollLock,
1006    /// <kbd>Pause Break</kbd>
1007    Pause,
1008    /// Some laptops place this key to the left of the <kbd>↑</kbd> key.
1009    ///
1010    /// This also the "back" button (triangle) on Android.
1011    BrowserBack,
1012    BrowserFavorites,
1013    /// Some laptops place this key to the right of the <kbd>↑</kbd> key.
1014    BrowserForward,
1015    /// The "home" button on Android.
1016    BrowserHome,
1017    BrowserRefresh,
1018    BrowserSearch,
1019    BrowserStop,
1020    /// <kbd>Eject</kbd> or <kbd>⏏</kbd>. This key is placed in the function section on some Apple
1021    /// keyboards.
1022    Eject,
1023    /// Sometimes labelled <kbd>My Computer</kbd> on the keyboard
1024    LaunchApp1,
1025    /// Sometimes labelled <kbd>Calculator</kbd> on the keyboard
1026    LaunchApp2,
1027    LaunchMail,
1028    MediaPlayPause,
1029    MediaSelect,
1030    MediaStop,
1031    MediaTrackNext,
1032    MediaTrackPrevious,
1033    /// This key is placed in the function section on some Apple keyboards, replacing the
1034    /// <kbd>Eject</kbd> key.
1035    Power,
1036    Sleep,
1037    AudioVolumeDown,
1038    AudioVolumeMute,
1039    AudioVolumeUp,
1040    WakeUp,
1041    // Legacy modifier key. Also called "Super" in certain places.
1042    Meta,
1043    // Legacy modifier key.
1044    Hyper,
1045    Turbo,
1046    Abort,
1047    Resume,
1048    Suspend,
1049    /// Found on Sun’s USB keyboard.
1050    Again,
1051    /// Found on Sun’s USB keyboard.
1052    Copy,
1053    /// Found on Sun’s USB keyboard.
1054    Cut,
1055    /// Found on Sun’s USB keyboard.
1056    Find,
1057    /// Found on Sun’s USB keyboard.
1058    Open,
1059    /// Found on Sun’s USB keyboard.
1060    Paste,
1061    /// Found on Sun’s USB keyboard.
1062    Props,
1063    /// Found on Sun’s USB keyboard.
1064    Select,
1065    /// Found on Sun’s USB keyboard.
1066    Undo,
1067    /// Use for dedicated <kbd>ひらがな</kbd> key found on some Japanese word processing keyboards.
1068    Hiragana,
1069    /// Use for dedicated <kbd>カタカナ</kbd> key found on some Japanese word processing keyboards.
1070    Katakana,
1071    /// General-purpose function key.
1072    /// Usually found at the top of the keyboard.
1073    F1,
1074    /// General-purpose function key.
1075    /// Usually found at the top of the keyboard.
1076    F2,
1077    /// General-purpose function key.
1078    /// Usually found at the top of the keyboard.
1079    F3,
1080    /// General-purpose function key.
1081    /// Usually found at the top of the keyboard.
1082    F4,
1083    /// General-purpose function key.
1084    /// Usually found at the top of the keyboard.
1085    F5,
1086    /// General-purpose function key.
1087    /// Usually found at the top of the keyboard.
1088    F6,
1089    /// General-purpose function key.
1090    /// Usually found at the top of the keyboard.
1091    F7,
1092    /// General-purpose function key.
1093    /// Usually found at the top of the keyboard.
1094    F8,
1095    /// General-purpose function key.
1096    /// Usually found at the top of the keyboard.
1097    F9,
1098    /// General-purpose function key.
1099    /// Usually found at the top of the keyboard.
1100    F10,
1101    /// General-purpose function key.
1102    /// Usually found at the top of the keyboard.
1103    F11,
1104    /// General-purpose function key.
1105    /// Usually found at the top of the keyboard.
1106    F12,
1107    /// General-purpose function key.
1108    /// Usually found at the top of the keyboard.
1109    F13,
1110    /// General-purpose function key.
1111    /// Usually found at the top of the keyboard.
1112    F14,
1113    /// General-purpose function key.
1114    /// Usually found at the top of the keyboard.
1115    F15,
1116    /// General-purpose function key.
1117    /// Usually found at the top of the keyboard.
1118    F16,
1119    /// General-purpose function key.
1120    /// Usually found at the top of the keyboard.
1121    F17,
1122    /// General-purpose function key.
1123    /// Usually found at the top of the keyboard.
1124    F18,
1125    /// General-purpose function key.
1126    /// Usually found at the top of the keyboard.
1127    F19,
1128    /// General-purpose function key.
1129    /// Usually found at the top of the keyboard.
1130    F20,
1131    /// General-purpose function key.
1132    /// Usually found at the top of the keyboard.
1133    F21,
1134    /// General-purpose function key.
1135    /// Usually found at the top of the keyboard.
1136    F22,
1137    /// General-purpose function key.
1138    /// Usually found at the top of the keyboard.
1139    F23,
1140    /// General-purpose function key.
1141    /// Usually found at the top of the keyboard.
1142    F24,
1143    /// General-purpose function key.
1144    F25,
1145    /// General-purpose function key.
1146    F26,
1147    /// General-purpose function key.
1148    F27,
1149    /// General-purpose function key.
1150    F28,
1151    /// General-purpose function key.
1152    F29,
1153    /// General-purpose function key.
1154    F30,
1155    /// General-purpose function key.
1156    F31,
1157    /// General-purpose function key.
1158    F32,
1159    /// General-purpose function key.
1160    F33,
1161    /// General-purpose function key.
1162    F34,
1163    /// General-purpose function key.
1164    F35,
1165}
1166
1167impl KeyCode {
1168    /// Attempts to convert the key code to its respective character.
1169    pub fn to_char(self) -> Option<char> {
1170        match self {
1171            KeyCode::Backquote => Some('`'),
1172            KeyCode::Backslash => Some('\\'),
1173            KeyCode::BracketLeft => Some('['),
1174            KeyCode::BracketRight => Some(']'),
1175            KeyCode::Comma => Some(','),
1176            KeyCode::Digit0 => Some('0'),
1177            KeyCode::Digit1 => Some('1'),
1178            KeyCode::Digit2 => Some('2'),
1179            KeyCode::Digit3 => Some('3'),
1180            KeyCode::Digit4 => Some('4'),
1181            KeyCode::Digit5 => Some('5'),
1182            KeyCode::Digit6 => Some('6'),
1183            KeyCode::Digit7 => Some('7'),
1184            KeyCode::Digit8 => Some('8'),
1185            KeyCode::Digit9 => Some('9'),
1186            KeyCode::Equal => Some('='),
1187            KeyCode::KeyA => Some('A'),
1188            KeyCode::KeyB => Some('B'),
1189            KeyCode::KeyC => Some('C'),
1190            KeyCode::KeyD => Some('D'),
1191            KeyCode::KeyE => Some('E'),
1192            KeyCode::KeyF => Some('F'),
1193            KeyCode::KeyG => Some('G'),
1194            KeyCode::KeyH => Some('H'),
1195            KeyCode::KeyI => Some('I'),
1196            KeyCode::KeyJ => Some('J'),
1197            KeyCode::KeyK => Some('K'),
1198            KeyCode::KeyL => Some('L'),
1199            KeyCode::KeyM => Some('M'),
1200            KeyCode::KeyN => Some('N'),
1201            KeyCode::KeyO => Some('O'),
1202            KeyCode::KeyP => Some('P'),
1203            KeyCode::KeyQ => Some('Q'),
1204            KeyCode::KeyR => Some('R'),
1205            KeyCode::KeyS => Some('S'),
1206            KeyCode::KeyT => Some('T'),
1207            KeyCode::KeyU => Some('U'),
1208            KeyCode::KeyV => Some('V'),
1209            KeyCode::KeyW => Some('W'),
1210            KeyCode::KeyX => Some('X'),
1211            KeyCode::KeyY => Some('Y'),
1212            KeyCode::KeyZ => Some('Z'),
1213            KeyCode::Minus => Some('-'),
1214            KeyCode::Period => Some('.'),
1215            KeyCode::Quote => Some('\''),
1216            KeyCode::Semicolon => Some(';'),
1217            KeyCode::Slash => Some('/'),
1218            KeyCode::Enter => Some('\n'),
1219            KeyCode::Space => Some(' '),
1220            KeyCode::Tab => Some('\t'),
1221            KeyCode::Numpad0 => Some('0'),
1222            KeyCode::Numpad1 => Some('1'),
1223            KeyCode::Numpad2 => Some('2'),
1224            KeyCode::Numpad3 => Some('3'),
1225            KeyCode::Numpad4 => Some('4'),
1226            KeyCode::Numpad5 => Some('5'),
1227            KeyCode::Numpad6 => Some('6'),
1228            KeyCode::Numpad7 => Some('7'),
1229            KeyCode::Numpad8 => Some('8'),
1230            KeyCode::Numpad9 => Some('9'),
1231            KeyCode::NumpadAdd => Some('+'),
1232            KeyCode::NumpadComma => Some('.'),
1233            KeyCode::NumpadDecimal => Some(','),
1234            KeyCode::NumpadDivide => Some('/'),
1235            KeyCode::NumpadEnter => Some('\n'),
1236            KeyCode::NumpadEqual => Some('='),
1237            KeyCode::NumpadHash => Some('#'),
1238            KeyCode::NumpadMultiply => Some('*'),
1239            KeyCode::NumpadParenLeft => Some('('),
1240            KeyCode::NumpadParenRight => Some(')'),
1241            KeyCode::NumpadStar => Some('*'),
1242            KeyCode::NumpadSubtract => Some('-'),
1243            _ => None,
1244        }
1245    }
1246}
1247
1248impl TryFrom<char> for KeyCode {
1249    type Error = &'static str;
1250
1251    fn try_from(value: char) -> Result<Self, Self::Error> {
1252        match value {
1253            '-' | '_' => Ok(Self::Minus),
1254            '+' | '=' => Ok(Self::NumpadAdd),
1255            ' ' => Ok(Self::Space),
1256            '\\' | '|' => Ok(Self::Backslash),
1257            '/' | '?' => Ok(Self::Slash),
1258            '.' | '>' => Ok(Self::Period),
1259            ',' | '<' => Ok(Self::Comma),
1260            '\'' | '"' => Ok(Self::Quote),
1261            ';' | ':' => Ok(Self::Semicolon),
1262            '`' | '~' => Ok(Self::Backquote),
1263            '0' | ')' => Ok(Self::Digit0),
1264            '1' | '!' => Ok(Self::Digit1),
1265            '2' | '@' => Ok(Self::Digit2),
1266            '3' | '#' => Ok(Self::Digit3),
1267            '4' | '$' => Ok(Self::Digit4),
1268            '5' | '%' => Ok(Self::Digit5),
1269            '6' | '^' => Ok(Self::Digit6),
1270            '7' | '&' => Ok(Self::Digit7),
1271            '8' | '*' => Ok(Self::Digit8),
1272            '9' | '(' => Ok(Self::Digit9),
1273            'a' | 'A' => Ok(Self::KeyA),
1274            'b' | 'B' => Ok(Self::KeyB),
1275            'c' | 'C' => Ok(Self::KeyC),
1276            'd' | 'D' => Ok(Self::KeyD),
1277            'e' | 'E' => Ok(Self::KeyE),
1278            'f' | 'F' => Ok(Self::KeyF),
1279            'g' | 'G' => Ok(Self::KeyG),
1280            'h' | 'H' => Ok(Self::KeyH),
1281            'i' | 'I' => Ok(Self::KeyI),
1282            'j' | 'J' => Ok(Self::KeyJ),
1283            'k' | 'K' => Ok(Self::KeyK),
1284            'l' | 'L' => Ok(Self::KeyL),
1285            'm' | 'M' => Ok(Self::KeyM),
1286            'n' | 'N' => Ok(Self::KeyN),
1287            'o' | 'O' => Ok(Self::KeyO),
1288            'p' | 'P' => Ok(Self::KeyP),
1289            'q' | 'Q' => Ok(Self::KeyQ),
1290            'r' | 'R' => Ok(Self::KeyR),
1291            's' | 'S' => Ok(Self::KeyS),
1292            't' | 'T' => Ok(Self::KeyT),
1293            'u' | 'U' => Ok(Self::KeyU),
1294            'v' | 'V' => Ok(Self::KeyV),
1295            'w' | 'W' => Ok(Self::KeyW),
1296            'x' | 'X' => Ok(Self::KeyX),
1297            'y' | 'Y' => Ok(Self::KeyY),
1298            'z' | 'Z' => Ok(Self::KeyZ),
1299            '[' | '{' => Ok(Self::BracketLeft),
1300            ']' | '}' => Ok(Self::BracketRight),
1301            _ => Err("unsupported"),
1302        }
1303    }
1304}
1305
1306/// A fixed set of cursor icons that available on most OSes.
1307#[derive(
1308    Debug,
1309    Copy,
1310    Clone,
1311    PartialEq,
1312    Eq,
1313    Hash,
1314    Default,
1315    Visit,
1316    Reflect,
1317    AsRefStr,
1318    EnumString,
1319    VariantNames,
1320)]
1321pub enum CursorIcon {
1322    /// The platform-dependent default cursor. Often rendered as arrow.
1323    #[default]
1324    Default,
1325
1326    /// A context menu is available for the object under the cursor. Often
1327    /// rendered as an arrow with a small menu-like graphic next to it.
1328    ContextMenu,
1329
1330    /// Help is available for the object under the cursor. Often rendered as a
1331    /// question mark or a balloon.
1332    Help,
1333
1334    /// The cursor is a pointer that indicates a link. Often rendered as the
1335    /// backside of a hand with the index finger extended.
1336    Pointer,
1337
1338    /// A progress indicator. The program is performing some processing, but is
1339    /// different from [`CursorIcon::Wait`] in that the user may still interact
1340    /// with the program.
1341    Progress,
1342
1343    /// Indicates that the program is busy and the user should wait. Often
1344    /// rendered as a watch or hourglass.
1345    Wait,
1346
1347    /// Indicates that a cell or set of cells may be selected. Often rendered as
1348    /// a thick plus-sign with a dot in the middle.
1349    Cell,
1350
1351    /// A simple crosshair (e.g., short line segments resembling a "+" sign).
1352    /// Often used to indicate a two-dimensional bitmap selection mode.
1353    Crosshair,
1354
1355    /// Indicates text that may be selected. Often rendered as an I-beam.
1356    Text,
1357
1358    /// Indicates vertical-text that may be selected. Often rendered as a
1359    /// horizontal I-beam.
1360    VerticalText,
1361
1362    /// Indicates an alias of/shortcut to something is to be created. Often
1363    /// rendered as an arrow with a small curved arrow next to it.
1364    Alias,
1365
1366    /// Indicates something is to be copied. Often rendered as an arrow with a
1367    /// small plus sign next to it.
1368    Copy,
1369
1370    /// Indicates something is to be moved.
1371    Move,
1372
1373    /// Indicates that the dragged item cannot be dropped at the current cursor
1374    /// location. Often rendered as a hand or pointer with a small circle with a
1375    /// line through it.
1376    NoDrop,
1377
1378    /// Indicates that the requested action will not be carried out. Often
1379    /// rendered as a circle with a line through it.
1380    NotAllowed,
1381
1382    /// Indicates that something can be grabbed (dragged to be moved). Often
1383    /// rendered as the backside of an open hand.
1384    Grab,
1385
1386    /// Indicates that something is being grabbed (dragged to be moved). Often
1387    /// rendered as the backside of a hand with fingers closed mostly out of
1388    /// view.
1389    Grabbing,
1390
1391    /// The east border to be moved.
1392    EResize,
1393
1394    /// The north border to be moved.
1395    NResize,
1396
1397    /// The north-east corner to be moved.
1398    NeResize,
1399
1400    /// The north-west corner to be moved.
1401    NwResize,
1402
1403    /// The south border to be moved.
1404    SResize,
1405
1406    /// The south-east corner to be moved.
1407    SeResize,
1408
1409    /// The south-west corner to be moved.
1410    SwResize,
1411
1412    /// The west border to be moved.
1413    WResize,
1414
1415    /// The east and west borders to be moved.
1416    EwResize,
1417
1418    /// The south and north borders to be moved.
1419    NsResize,
1420
1421    /// The north-east and south-west corners to be moved.
1422    NeswResize,
1423
1424    /// The north-west and south-east corners to be moved.
1425    NwseResize,
1426
1427    /// Indicates that the item/column can be resized horizontally. Often
1428    /// rendered as arrows pointing left and right with a vertical bar
1429    /// separating them.
1430    ColResize,
1431
1432    /// Indicates that the item/row can be resized vertically. Often rendered as
1433    /// arrows pointing up and down with a horizontal bar separating them.
1434    RowResize,
1435
1436    /// Indicates that the something can be scrolled in any direction. Often
1437    /// rendered as arrows pointing up, down, left, and right with a dot in the
1438    /// middle.
1439    AllScroll,
1440
1441    /// Indicates that something can be zoomed in. Often rendered as a
1442    /// magnifying glass with a "+" in the center of the glass.
1443    ZoomIn,
1444
1445    /// Indicates that something can be zoomed in. Often rendered as a
1446    /// magnifying glass with a "-" in the center of the glass.
1447    ZoomOut,
1448}
1449
1450uuid_provider!(CursorIcon = "da7f3a5f-9d26-460a-8e46-38da25f8a8db");