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");