trait based event system

This commit is contained in:
Evan Almloff committed 2023-08-25 17:02:48 -05:00
1 parent a72718134b
commit 299b123446
28 files changed
+2407 -734

No files matched your search

+127 -120
View File
@@ -1,9 +1,7 @@
use crate::input_data::{decode_key_location, encode_key_location};
use dioxus_core::Event;
use keyboard_types::{Code, Key, Location, Modifiers};
use std::convert::TryInto;
use std::fmt::{Debug, Formatter};
use std::str::FromStr;
use std::fmt::Debug;
#[cfg(feature = "serialize")]
fn resilient_deserialize_code<'de, D>(deserializer: D) -> Result<Code, D::Error>
@@ -16,57 +14,136 @@ where
}
pub type KeyboardEvent = Event<KeyboardData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, PartialEq, Eq)]
pub struct KeyboardData {
#[deprecated(
since = "0.3.0",
note = "This may not work in all environments. Use key() instead."
)]
pub char_code: u32,
inner: Box<dyn HasKeyboardData>,
}
/// Identify which "key" was entered.
#[deprecated(since = "0.3.0", note = "use key() instead")]
pub key: String,
impl<E: HasKeyboardData> From<E> for KeyboardData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
/// Get the key code as an enum Variant.
#[deprecated(
since = "0.3.0",
note = "This may not work in all environments. Use code() instead."
)]
pub key_code: KeyCode,
impl std::fmt::Debug for KeyboardData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("KeyboardData")
.field("key", &self.key())
.field("code", &self.code())
.field("modifiers", &self.modifiers())
.field("location", &self.location())
.field("is_auto_repeating", &self.is_auto_repeating())
.finish()
}
}
/// the physical key on the keyboard
#[cfg_attr(
feature = "serialize",
serde(deserialize_with = "resilient_deserialize_code")
)]
impl PartialEq for KeyboardData {
fn eq(&self, other: &Self) -> bool {
self.key() == other.key()
&& self.code() == other.code()
&& self.modifiers() == other.modifiers()
&& self.location() == other.location()
&& self.is_auto_repeating() == other.is_auto_repeating()
}
}
impl KeyboardData {
/// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
pub fn key(&self) -> Key {
self.inner.key()
}
/// A physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value that isn't altered by keyboard layout or the state of the modifier keys.
pub fn code(&self) -> Code {
self.inner.code()
}
/// The set of modifier keys which were pressed when the event occurred
pub fn modifiers(&self) -> Modifiers {
self.inner.modifiers()
}
/// The location of the key on the keyboard or other input device.
pub fn location(&self) -> Location {
self.inner.location()
}
/// `true` iff the key is being held down such that it is automatically repeating.
pub fn is_auto_repeating(&self) -> bool {
self.inner.is_auto_repeating()
}
/// Downcast this KeyboardData to a concrete type.
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
#[derive(serde::Serialize, serde::Deserialize)]
struct SerializedKeyboardData {
auto_repeating: bool,
#[serde(deserialize_with = "resilient_deserialize_code")]
code: Code,
key: Key,
location: Location,
modifiers: Modifiers,
}
/// Indicate if the `alt` modifier key was pressed during this keyboard event
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub alt_key: bool,
#[cfg(feature = "serialize")]
impl From<&KeyboardData> for SerializedKeyboardData {
fn from(data: &KeyboardData) -> Self {
Self {
auto_repeating: data.is_auto_repeating(),
code: data.code(),
key: data.key(),
location: data.location(),
modifiers: data.modifiers(),
}
}
}
/// Indicate if the `ctrl` modifier key was pressed during this keyboard event
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub ctrl_key: bool,
#[cfg(feature = "serialize")]
impl HasKeyboardData for SerializedKeyboardData {
fn key(&self) -> Key {
self.key.clone()
}
/// Indicate if the `meta` modifier key was pressed during this keyboard event
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub meta_key: bool,
fn code(&self) -> Code {
self.code
}
/// Indicate if the `shift` modifier key was pressed during this keyboard event
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub shift_key: bool,
fn modifiers(&self) -> Modifiers {
self.modifiers
}
#[deprecated(since = "0.3.0", note = "use location() instead")]
pub location: usize,
fn location(&self) -> Location {
self.location
}
#[deprecated(since = "0.3.0", note = "use is_auto_repeating() instead")]
pub repeat: bool,
fn is_auto_repeating(&self) -> bool {
self.auto_repeating
}
#[deprecated(since = "0.3.0", note = "use code() or key() instead")]
pub which: usize,
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for KeyboardData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedKeyboardData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for KeyboardData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedKeyboardData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
impl_event! {
@@ -82,94 +159,24 @@ impl_event! {
onkeyup
}
impl KeyboardData {
pub fn new(
key: Key,
code: Code,
location: Location,
is_auto_repeating: bool,
modifiers: Modifiers,
) -> Self {
#[allow(deprecated)]
KeyboardData {
char_code: key.legacy_charcode(),
key: key.to_string(),
key_code: KeyCode::from_raw_code(
key.legacy_keycode()
.try_into()
.expect("could not convert keycode to u8"),
),
code,
alt_key: modifiers.contains(Modifiers::ALT),
ctrl_key: modifiers.contains(Modifiers::CONTROL),
meta_key: modifiers.contains(Modifiers::META),
shift_key: modifiers.contains(Modifiers::SHIFT),
location: encode_key_location(location),
repeat: is_auto_repeating,
which: key
.legacy_charcode()
.try_into()
.expect("could not convert charcode to usize"),
}
}
pub trait HasKeyboardData: std::any::Any {
/// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
pub fn key(&self) -> Key {
#[allow(deprecated)]
FromStr::from_str(&self.key).unwrap_or(Key::Unidentified)
}
fn key(&self) -> Key;
/// A physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value that isn't altered by keyboard layout or the state of the modifier keys.
pub fn code(&self) -> Code {
self.code
}
fn code(&self) -> Code;
/// The set of modifier keys which were pressed when the event occurred
pub fn modifiers(&self) -> Modifiers {
let mut modifiers = Modifiers::empty();
#[allow(deprecated)]
{
if self.alt_key {
modifiers.insert(Modifiers::ALT);
}
if self.ctrl_key {
modifiers.insert(Modifiers::CONTROL);
}
if self.meta_key {
modifiers.insert(Modifiers::META);
}
if self.shift_key {
modifiers.insert(Modifiers::SHIFT);
}
}
modifiers
}
fn modifiers(&self) -> Modifiers;
/// The location of the key on the keyboard or other input device.
pub fn location(&self) -> Location {
#[allow(deprecated)]
decode_key_location(self.location)
}
fn location(&self) -> Location;
/// `true` iff the key is being held down such that it is automatically repeating.
pub fn is_auto_repeating(&self) -> bool {
#[allow(deprecated)]
self.repeat
}
}
fn is_auto_repeating(&self) -> bool;
impl Debug for KeyboardData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("KeyboardData")
.field("key", &self.key())
.field("code", &self.code())
.field("modifiers", &self.modifiers())
.field("location", &self.location())
.field("is_auto_repeating", &self.is_auto_repeating())
.finish()
}
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
#[cfg(feature = "serialize")]