Merge branch 'master' into add-file-data-drag-event

This commit is contained in:
Evan Almloff committed 2024-01-08 14:16:09 -06:00
commit 56798b3d1c
407 files changed
+16602 -11298

No files matched your search

+125 -5
View File
@@ -2,12 +2,132 @@ use dioxus_core::Event;
pub type AnimationEvent = Event<AnimationData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct AnimationData {
pub animation_name: String,
pub pseudo_element: String,
pub elapsed_time: f32,
inner: Box<dyn HasAnimationData>,
}
impl AnimationData {
/// Create a new AnimationData
pub fn new(inner: impl HasAnimationData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// The name of the animation
pub fn animation_name(&self) -> String {
self.inner.animation_name()
}
/// The name of the pseudo-element the animation runs on
pub fn pseudo_element(&self) -> String {
self.inner.pseudo_element()
}
/// The amount of time the animation has been running
pub fn elapsed_time(&self) -> f32 {
self.inner.elapsed_time()
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_ref().as_any().downcast_ref::<T>()
}
}
impl<E: HasAnimationData> From<E> for AnimationData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for AnimationData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AnimationData")
.field("animation_name", &self.animation_name())
.field("pseudo_element", &self.pseudo_element())
.field("elapsed_time", &self.elapsed_time())
.finish()
}
}
impl PartialEq for AnimationData {
fn eq(&self, other: &Self) -> bool {
self.animation_name() == other.animation_name()
&& self.pseudo_element() == other.pseudo_element()
&& self.elapsed_time() == other.elapsed_time()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of AnimationData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedAnimationData {
animation_name: String,
pseudo_element: String,
elapsed_time: f32,
}
#[cfg(feature = "serialize")]
impl From<&AnimationData> for SerializedAnimationData {
fn from(data: &AnimationData) -> Self {
Self {
animation_name: data.animation_name(),
pseudo_element: data.pseudo_element(),
elapsed_time: data.elapsed_time(),
}
}
}
#[cfg(feature = "serialize")]
impl HasAnimationData for SerializedAnimationData {
fn animation_name(&self) -> String {
self.animation_name.clone()
}
fn pseudo_element(&self) -> String {
self.pseudo_element.clone()
}
fn elapsed_time(&self) -> f32 {
self.elapsed_time
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for AnimationData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedAnimationData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for AnimationData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedAnimationData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
/// A trait for any object that has the data for an animation event
pub trait HasAnimationData: std::any::Any {
/// The name of the animation
fn animation_name(&self) -> String;
/// The name of the pseudo-element the animation runs on
fn pseudo_element(&self) -> String;
/// The amount of time the animation has been running
fn elapsed_time(&self) -> f32;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
+75 -3
View File
@@ -1,10 +1,82 @@
use dioxus_core::Event;
pub type ClipboardEvent = Event<ClipboardData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClipboardData {
// DOMDataTransfer clipboardData
inner: Box<dyn HasClipboardData>,
}
impl<E: HasClipboardData> From<E> for ClipboardData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for ClipboardData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClipboardData").finish()
}
}
impl PartialEq for ClipboardData {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl ClipboardData {
/// Create a new ClipboardData
pub fn new(inner: impl HasClipboardData) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_ref().as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of ClipboardData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedClipboardData {}
#[cfg(feature = "serialize")]
impl From<&ClipboardData> for SerializedClipboardData {
fn from(_: &ClipboardData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasClipboardData for SerializedClipboardData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for ClipboardData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedClipboardData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for ClipboardData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedClipboardData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasClipboardData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event![
+91 -3
View File
@@ -1,10 +1,98 @@
use dioxus_core::Event;
pub type CompositionEvent = Event<CompositionData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompositionData {
pub data: String,
inner: Box<dyn HasCompositionData>,
}
impl std::fmt::Debug for CompositionData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CompositionData")
.field("data", &self.data())
.finish()
}
}
impl<E: HasCompositionData> From<E> for CompositionData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl PartialEq for CompositionData {
fn eq(&self, other: &Self) -> bool {
self.data() == other.data()
}
}
impl CompositionData {
/// Create a new CompositionData
pub fn new(inner: impl HasCompositionData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// The characters generated by the input method that raised the event
pub fn data(&self) -> String {
self.inner.data()
}
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of CompositionData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedCompositionData {
data: String,
}
#[cfg(feature = "serialize")]
impl From<&CompositionData> for SerializedCompositionData {
fn from(data: &CompositionData) -> Self {
Self { data: data.data() }
}
}
#[cfg(feature = "serialize")]
impl HasCompositionData for SerializedCompositionData {
fn data(&self) -> String {
self.data.clone()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for CompositionData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedCompositionData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for CompositionData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedCompositionData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
/// A trait for any object that has the data for a composition event
pub trait HasCompositionData: std::any::Any {
/// The characters generated by the input method that raised the event
fn data(&self) -> String;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
+173 -19
View File
@@ -1,5 +1,12 @@
use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
use crate::input_data::{MouseButton, MouseButtonSet};
use crate::prelude::*;
use crate::FileEngine;
use crate::MouseData;
use dioxus_core::Event;
use keyboard_types::Modifiers;
use crate::HasMouseData;
use dioxus_core::Event;
use std::fmt::Debug;
@@ -10,38 +17,185 @@ pub type DragEvent = Event<DragData>;
/// placing a pointer device (such as a mouse) on the touch surface and then dragging the pointer to a new location
/// (such as another DOM element). Applications are free to interpret a drag and drop interaction in an
/// application-specific way.
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone)]
pub struct DragData {
/// Inherit mouse data
pub mouse: MouseData,
#[cfg_attr(
feature = "serialize",
serde(
default,
skip_serializing,
deserialize_with = "crate::events::deserialize_file_engine"
)
)]
pub files: Option<std::sync::Arc<dyn FileEngine>>,
inner: Box<dyn HasDragData>,
}
impl Debug for DragData {
impl<E: HasDragData + 'static> From<E> for DragData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for DragData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DragData")
.field("mouse", &self.mouse)
.field("coordinates", &self.coordinates())
.field("modifiers", &self.modifiers())
.field("held_buttons", &self.held_buttons())
.field("trigger_button", &self.trigger_button())
.finish()
}
}
impl PartialEq for DragData {
fn eq(&self, other: &Self) -> bool {
self.mouse == other.mouse
self.coordinates() == other.coordinates()
&& self.modifiers() == other.modifiers()
&& self.held_buttons() == other.held_buttons()
&& self.trigger_button() == other.trigger_button()
}
}
impl Eq for DragData {}
impl DragData {
/// Create a new DragData
pub fn new(inner: impl HasDragData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event data to a specific type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
/// Get the files of the form event
pub fn files(&self) -> Option<std::sync::Arc<dyn FileEngine>> {
self.inner.files()
}
}
impl InteractionLocation for DragData {
fn client_coordinates(&self) -> ClientPoint {
self.inner.client_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.inner.page_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.inner.screen_coordinates()
}
}
impl InteractionElementOffset for DragData {
fn element_coordinates(&self) -> ElementPoint {
self.inner.element_coordinates()
}
fn coordinates(&self) -> Coordinates {
self.inner.coordinates()
}
}
impl ModifiersInteraction for DragData {
fn modifiers(&self) -> Modifiers {
self.inner.modifiers()
}
}
impl PointerInteraction for DragData {
fn held_buttons(&self) -> MouseButtonSet {
self.inner.held_buttons()
}
// todo the following is kind of bad; should we just return None when the trigger_button is unreliable (and frankly irrelevant)? i guess we would need the event_type here
fn trigger_button(&self) -> Option<MouseButton> {
self.inner.trigger_button()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of DragData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedDragData {
mouse: crate::point_interaction::SerializedPointInteraction,
}
#[cfg(feature = "serialize")]
impl From<&DragData> for SerializedDragData {
fn from(data: &DragData) -> Self {
Self {
mouse: crate::point_interaction::SerializedPointInteraction::from(data),
}
}
}
#[cfg(feature = "serialize")]
impl HasDragData for SerializedDragData {}
#[cfg(feature = "serialize")]
impl HasMouseData for SerializedDragData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl InteractionLocation for SerializedDragData {
fn client_coordinates(&self) -> ClientPoint {
self.mouse.client_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.mouse.page_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.mouse.screen_coordinates()
}
}
#[cfg(feature = "serialize")]
impl InteractionElementOffset for SerializedDragData {
fn element_coordinates(&self) -> ElementPoint {
self.mouse.element_coordinates()
}
fn coordinates(&self) -> Coordinates {
self.mouse.coordinates()
}
}
#[cfg(feature = "serialize")]
impl ModifiersInteraction for SerializedDragData {
fn modifiers(&self) -> Modifiers {
self.mouse.modifiers()
}
}
#[cfg(feature = "serialize")]
impl PointerInteraction for SerializedDragData {
fn held_buttons(&self) -> MouseButtonSet {
self.mouse.held_buttons()
}
fn trigger_button(&self) -> Option<MouseButton> {
self.mouse.trigger_button()
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for DragData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedDragData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for DragData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedDragData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
/// A trait for any object that has the data for a drag event
pub trait HasDragData: HasMouseData {}
impl_event! {
DragData;
+76 -3
View File
@@ -2,9 +2,82 @@ use dioxus_core::Event;
pub type FocusEvent = Event<FocusData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FocusData {/* DOMEventInner: Send + SyncTarget relatedTarget */}
pub struct FocusData {
inner: Box<dyn HasFocusData>,
}
impl<E: HasFocusData> From<E> for FocusData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for FocusData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FocusData").finish()
}
}
impl PartialEq for FocusData {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl FocusData {
/// Create a new FocusData
pub fn new(inner: impl HasFocusData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event data to a specific type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of FocusData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Default)]
pub struct SerializedFocusData {}
#[cfg(feature = "serialize")]
impl From<&FocusData> for SerializedFocusData {
fn from(_: &FocusData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasFocusData for SerializedFocusData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for FocusData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedFocusData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for FocusData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedFocusData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasFocusData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
FocusData;
+179 -72
View File
@@ -4,100 +4,207 @@ use dioxus_core::Event;
pub type FormEvent = Event<FormData>;
/// A form value that may either be a list of values or a single value
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
// this will serialize Text(String) -> String and VecText(Vec<String>) to Vec<String>
serde(untagged)
)]
#[derive(Debug, Clone, PartialEq)]
pub enum FormValue {
Text(String),
VecText(Vec<String>),
}
/* DOMEvent: Send + SyncTarget relatedTarget */
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone)]
pub struct FormData {
pub value: String,
pub values: HashMap<String, Vec<String>>,
#[cfg_attr(
feature = "serialize",
serde(
default,
skip_serializing,
deserialize_with = "deserialize_file_engine"
)
)]
pub files: Option<std::sync::Arc<dyn FileEngine>>,
inner: Box<dyn HasFormData>,
}
#[cfg(feature = "serialize")]
#[derive(serde::Serialize, serde::Deserialize)]
struct SerializedFileEngine {
files: HashMap<String, Vec<u8>>,
}
#[cfg(feature = "serialize")]
#[async_trait::async_trait(?Send)]
impl FileEngine for SerializedFileEngine {
fn files(&self) -> Vec<String> {
self.files.keys().cloned().collect()
impl<E: HasFormData> From<E> for FormData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
async fn read_file(&self, file: &str) -> Option<Vec<u8>> {
self.files.get(file).cloned()
}
async fn read_file_to_string(&self, file: &str) -> Option<String> {
self.read_file(file)
.await
.map(|bytes| String::from_utf8_lossy(&bytes).to_string())
}
async fn get_native_file(&self, file: &str) -> Option<Box<dyn Any>> {
self.read_file(file)
.await
.map(|val| Box::new(val) as Box<dyn Any>)
}
}
#[cfg(feature = "serialize")]
pub(crate) fn deserialize_file_engine<'de, D>(
deserializer: D,
) -> Result<Option<std::sync::Arc<dyn FileEngine>>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::Deserialize;
let Ok(file_engine) = SerializedFileEngine::deserialize(deserializer) else {
return Ok(None);
};
let file_engine = std::sync::Arc::new(file_engine);
Ok(Some(file_engine))
}
impl PartialEq for FormData {
fn eq(&self, other: &Self) -> bool {
self.value == other.value && self.values == other.values
self.value() == other.value() && self.values() == other.values()
}
}
impl Debug for FormData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FormEvent")
.field("value", &self.value)
.field("values", &self.values)
.field("value", &self.value())
.field("values", &self.values())
.finish()
}
}
#[async_trait::async_trait(?Send)]
pub trait FileEngine {
// get a list of file names
fn files(&self) -> Vec<String>;
impl FormData {
/// Create a new form event
pub fn new(event: impl HasFormData + 'static) -> Self {
Self {
inner: Box::new(event),
}
}
// read a file to bytes
async fn read_file(&self, file: &str) -> Option<Vec<u8>>;
/// Get the value of the form event
pub fn value(&self) -> String {
self.inner.value()
}
// read a file to string
async fn read_file_to_string(&self, file: &str) -> Option<String>;
/// Get the values of the form event
pub fn values(&self) -> HashMap<String, FormValue> {
self.inner.values()
}
// returns a file in platform's native representation
async fn get_native_file(&self, file: &str) -> Option<Box<dyn Any>>;
/// Get the files of the form event
pub fn files(&self) -> Option<std::sync::Arc<dyn FileEngine>> {
self.inner.files()
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
/// An object that has all the data for a form event
pub trait HasFormData: HasFileData + std::any::Any {
fn value(&self) -> String {
Default::default()
}
fn values(&self) -> HashMap<String, FormValue> {
Default::default()
}
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl FormData {
#[cfg(feature = "serialize")]
/// Parse the values into a struct with one field per value
pub fn parsed_values<T>(&self) -> Result<T, serde_json::Error>
where
T: serde::de::DeserializeOwned,
{
use serde::Serialize;
fn convert_hashmap_to_json<K, V>(hashmap: &HashMap<K, V>) -> serde_json::Result<String>
where
K: Serialize + std::hash::Hash + Eq,
V: Serialize,
{
serde_json::to_string(hashmap)
}
let parsed_json =
convert_hashmap_to_json(&self.values()).expect("Failed to parse values to JSON");
serde_json::from_str(&parsed_json)
}
}
#[cfg(feature = "serialize")]
/// A serialized form data object
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedFormData {
value: String,
values: HashMap<String, FormValue>,
files: Option<SerializedFileEngine>,
}
#[cfg(feature = "serialize")]
impl SerializedFormData {
/// Create a new serialized form data object
pub fn new(
value: String,
values: HashMap<String, FormValue>,
files: Option<SerializedFileEngine>,
) -> Self {
Self {
value,
values,
files,
}
}
/// Create a new serialized form data object from a traditional form data object
pub async fn async_from(data: &FormData) -> Self {
Self {
value: data.value(),
values: data.values(),
files: match data.files() {
Some(files) => {
let mut resolved_files = HashMap::new();
for file in files.files() {
let bytes = files.read_file(&file).await;
resolved_files.insert(file, bytes.unwrap_or_default());
}
Some(SerializedFileEngine {
files: resolved_files,
})
}
None => None,
},
}
}
fn from_lossy(data: &FormData) -> Self {
Self {
value: data.value(),
values: data.values(),
files: None,
}
}
}
#[cfg(feature = "serialize")]
impl HasFormData for SerializedFormData {
fn value(&self) -> String {
self.value.clone()
}
fn values(&self) -> HashMap<String, FormValue> {
self.values.clone()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl HasFileData for SerializedFormData {
fn files(&self) -> Option<std::sync::Arc<dyn FileEngine>> {
self.files
.as_ref()
.map(|files| std::sync::Arc::new(files.clone()) as _)
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for FormData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedFormData::from_lossy(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for FormData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedFormData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
impl_event! {
+90 -4
View File
@@ -1,11 +1,97 @@
use dioxus_core::Event;
pub type ImageEvent = Event<ImageData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImageData {
#[cfg_attr(feature = "serialize", serde(default))]
pub load_error: bool,
inner: Box<dyn HasImageData>,
}
impl<E: HasImageData> From<E> for ImageData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for ImageData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ImageData")
.field("load_error", &self.load_error())
.finish()
}
}
impl PartialEq for ImageData {
fn eq(&self, other: &Self) -> bool {
self.load_error() == other.load_error()
}
}
impl ImageData {
/// Create a new ImageData
pub fn new(e: impl HasImageData) -> Self {
Self { inner: Box::new(e) }
}
/// If the renderer encountered an error while loading the image
pub fn load_error(&self) -> bool {
self.inner.load_error()
}
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of ImageData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedImageData {
load_error: bool,
}
#[cfg(feature = "serialize")]
impl From<&ImageData> for SerializedImageData {
fn from(data: &ImageData) -> Self {
Self {
load_error: data.load_error(),
}
}
}
#[cfg(feature = "serialize")]
impl HasImageData for SerializedImageData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn load_error(&self) -> bool {
self.load_error
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for ImageData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedImageData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for ImageData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedImageData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
/// A trait for any object that has the data for an image event
pub trait HasImageData: std::any::Any {
/// If the renderer encountered an error while loading the image
fn load_error(&self) -> bool;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
+193 -123
View File
@@ -1,9 +1,8 @@
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;
use crate::prelude::ModifiersInteraction;
#[cfg(feature = "serialize")]
fn resilient_deserialize_code<'de, D>(deserializer: D) -> Result<Code, D::Error>
@@ -16,57 +15,199 @@ 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 {
/// Create a new KeyboardData
pub fn new(inner: impl HasKeyboardData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// 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 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>()
}
}
impl ModifiersInteraction for KeyboardData {
fn modifiers(&self) -> Modifiers {
self.inner.modifiers()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of KeyboardData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedKeyboardData {
char_code: u32,
key: String,
key_code: KeyCode,
#[serde(deserialize_with = "resilient_deserialize_code")]
code: Code,
alt_key: bool,
ctrl_key: bool,
meta_key: bool,
shift_key: bool,
location: usize,
repeat: bool,
which: usize,
}
/// 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 SerializedKeyboardData {
/// Create a new SerializedKeyboardData
pub fn new(
key: Key,
code: Code,
location: Location,
is_auto_repeating: bool,
modifiers: Modifiers,
) -> Self {
Self {
char_code: key.legacy_charcode(),
key: key.to_string(),
key_code: KeyCode::from_raw_code(
std::convert::TryInto::try_into(key.legacy_keycode())
.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: crate::input_data::encode_key_location(location),
repeat: is_auto_repeating,
which: std::convert::TryInto::try_into(key.legacy_charcode())
.expect("could not convert charcode to usize"),
}
}
}
/// 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 From<&KeyboardData> for SerializedKeyboardData {
fn from(data: &KeyboardData) -> Self {
Self::new(
data.key(),
data.code(),
data.location(),
data.is_auto_repeating(),
data.modifiers(),
)
}
}
/// 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,
#[cfg(feature = "serialize")]
impl HasKeyboardData for SerializedKeyboardData {
fn key(&self) -> Key {
std::str::FromStr::from_str(&self.key).unwrap_or(Key::Unidentified)
}
/// 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 code(&self) -> Code {
self.code
}
#[deprecated(since = "0.3.0", note = "use location() instead")]
pub location: usize,
fn location(&self) -> Location {
crate::input_data::decode_key_location(self.location)
}
#[deprecated(since = "0.3.0", note = "use is_auto_repeating() instead")]
pub repeat: bool,
fn is_auto_repeating(&self) -> bool {
self.repeat
}
#[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 ModifiersInteraction for SerializedKeyboardData {
fn modifiers(&self) -> Modifiers {
let mut modifiers = Modifiers::empty();
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
}
}
#[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 +223,21 @@ 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: ModifiersInteraction + 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
}
/// 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 code(&self) -> Code;
/// 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")]
@@ -178,6 +246,8 @@ impl<'de> serde::Deserialize<'de> for KeyCode {
where
D: serde::Deserializer<'de>,
{
use std::convert::TryInto;
// We could be deserializing a unicode character, so we need to use u64 even if the output only takes u8
let value = u64::deserialize(deserializer)?;
+77 -4
View File
@@ -1,9 +1,82 @@
use dioxus_core::Event;
pub type MediaEvent = Event<MediaData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MediaData {}
pub struct MediaData {
inner: Box<dyn HasMediaData>,
}
impl<E: HasMediaData> From<E> for MediaData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for MediaData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MediaData").finish()
}
}
impl PartialEq for MediaData {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl MediaData {
/// Create a new MediaData
pub fn new(inner: impl HasMediaData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of MediaData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedMediaData {}
#[cfg(feature = "serialize")]
impl From<&MediaData> for SerializedMediaData {
fn from(_: &MediaData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasMediaData for SerializedMediaData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for MediaData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedMediaData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for MediaData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedMediaData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasMediaData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
MediaData;
@@ -29,7 +102,7 @@ impl_event! [
///ended
onended
// todo: this conflicts with image events
// todo: this conflicts with Media events
// neither have data, so it's okay
// ///error
// onerror
+21 -15
View File
@@ -3,22 +3,18 @@
use euclid::Rect;
use std::{
any::Any,
fmt::{Display, Formatter},
future::Future,
pin::Pin,
rc::Rc,
};
/// An Element that has been rendered and allows reading and modifying information about it.
///
/// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
// we can not use async_trait here because it does not create a trait that is object safe
pub trait RenderedElementBacking {
/// Get the renderer specific element for the given id
fn get_raw_element(&self) -> MountedResult<&dyn Any> {
Err(MountedError::NotSupported)
}
pub trait RenderedElementBacking: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
/// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
#[allow(clippy::type_complexity)]
@@ -40,7 +36,11 @@ pub trait RenderedElementBacking {
}
}
impl RenderedElementBacking for () {}
impl RenderedElementBacking for () {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
/// The way that scrolling should be performed
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
@@ -57,22 +57,23 @@ pub enum ScrollBehavior {
///
/// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
pub struct MountedData {
inner: Rc<dyn RenderedElementBacking>,
inner: Box<dyn RenderedElementBacking>,
}
impl<E: RenderedElementBacking> From<E> for MountedData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl MountedData {
/// Create a new MountedData
pub fn new(registry: impl RenderedElementBacking + 'static) -> Self {
Self {
inner: Rc::new(registry),
inner: Box::new(registry),
}
}
/// Get the renderer specific element for the given id
pub fn get_raw_element(&self) -> MountedResult<&dyn Any> {
self.inner.get_raw_element()
}
/// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
pub async fn get_client_rect(&self) -> MountedResult<Rect<f64, f64>> {
self.inner.get_client_rect().await
@@ -90,6 +91,11 @@ impl MountedData {
pub fn set_focus(&self, focus: bool) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
self.inner.set_focus(focus)
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
use dioxus_core::Event;
+176 -180
View File
@@ -1,91 +1,47 @@
use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
use crate::input_data::{
decode_mouse_button_set, encode_mouse_button_set, MouseButton, MouseButtonSet,
};
use crate::input_data::{MouseButton, MouseButtonSet};
use crate::prelude::*;
use dioxus_core::Event;
use keyboard_types::Modifiers;
use std::fmt::{Debug, Formatter};
pub type MouseEvent = Event<MouseData>;
/// A synthetic event that wraps a web-style [`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Default, PartialEq, Eq)]
/// Data associated with a mouse event
///
/// Do not use the deprecated fields; they may change or become private in the future.
pub struct MouseData {
/// True if the alt key was down when the mouse event was fired.
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub alt_key: bool,
inner: Box<dyn HasMouseData>,
}
/// The button number that was pressed (if applicable) when the mouse event was fired.
#[deprecated(since = "0.3.0", note = "use trigger_button() instead")]
pub button: i16,
impl<E: HasMouseData + 'static> From<E> for MouseData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
/// Indicates which buttons are pressed on the mouse (or other input device) when a mouse event is triggered.
///
/// Each button that can be pressed is represented by a given number (see below). If more than one button is pressed, the button values are added together to produce a new number. For example, if the secondary (2) and auxiliary (4) buttons are pressed simultaneously, the value is 6 (i.e., 2 + 4).
///
/// - 1: Primary button (usually the left button)
/// - 2: Secondary button (usually the right button)
/// - 4: Auxiliary button (usually the mouse wheel button or middle button)
/// - 8: 4th button (typically the "Browser Back" button)
/// - 16 : 5th button (typically the "Browser Forward" button)
#[deprecated(since = "0.3.0", note = "use held_buttons() instead")]
pub buttons: u16,
impl std::fmt::Debug for MouseData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MouseData")
.field("coordinates", &self.coordinates())
.field("modifiers", &self.modifiers())
.field("held_buttons", &self.held_buttons())
.field("trigger_button", &self.trigger_button())
.finish()
}
}
/// The horizontal coordinate within the application's viewport at which the event occurred (as opposed to the coordinate within the page).
///
/// For example, clicking on the left edge of the viewport will always result in a mouse event with a clientX value of 0, regardless of whether the page is scrolled horizontally.
#[deprecated(since = "0.3.0", note = "use client_coordinates() instead")]
pub client_x: i32,
impl<E: HasMouseData> PartialEq<E> for MouseData {
fn eq(&self, other: &E) -> bool {
self.coordinates() == other.coordinates()
&& self.modifiers() == other.modifiers()
&& self.held_buttons() == other.held_buttons()
&& self.trigger_button() == other.trigger_button()
}
}
/// The vertical coordinate within the application's viewport at which the event occurred (as opposed to the coordinate within the page).
///
/// For example, clicking on the top edge of the viewport will always result in a mouse event with a clientY value of 0, regardless of whether the page is scrolled vertically.
#[deprecated(since = "0.3.0", note = "use client_coordinates() instead")]
pub client_y: i32,
/// True if the control key was down when the mouse event was fired.
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub ctrl_key: bool,
/// True if the meta key was down when the mouse event was fired.
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub meta_key: bool,
/// The offset in the X coordinate of the mouse pointer between that event and the padding edge of the target node.
#[deprecated(since = "0.3.0", note = "use element_coordinates() instead")]
pub offset_x: i32,
/// The offset in the Y coordinate of the mouse pointer between that event and the padding edge of the target node.
#[deprecated(since = "0.3.0", note = "use element_coordinates() instead")]
pub offset_y: i32,
/// The X (horizontal) coordinate (in pixels) of the mouse, relative to the left edge of the entire document. This includes any portion of the document not currently visible.
///
/// Being based on the edge of the document as it is, this property takes into account any horizontal scrolling of the page. For example, if the page is scrolled such that 200 pixels of the left side of the document are scrolled out of view, and the mouse is clicked 100 pixels inward from the left edge of the view, the value returned by pageX will be 300.
#[deprecated(since = "0.3.0", note = "use page_coordinates() instead")]
pub page_x: i32,
/// The Y (vertical) coordinate in pixels of the event relative to the whole document.
///
/// See `page_x`.
#[deprecated(since = "0.3.0", note = "use page_coordinates() instead")]
pub page_y: i32,
/// The X coordinate of the mouse pointer in global (screen) coordinates.
#[deprecated(since = "0.3.0", note = "use screen_coordinates() instead")]
pub screen_x: i32,
/// The Y coordinate of the mouse pointer in global (screen) coordinates.
#[deprecated(since = "0.3.0", note = "use screen_coordinates() instead")]
pub screen_y: i32,
/// True if the shift key was down when the mouse event was fired.
#[deprecated(since = "0.3.0", note = "use modifiers() instead")]
pub shift_key: bool,
/// A trait for any object that has the data for a mouse event
pub trait HasMouseData: PointerInteraction {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! {
@@ -119,12 +75,11 @@ impl_event! {
/// oncontextmenu
oncontextmenu
/// ondoubleclick
ondoubleclick
/// ondoubleclick
#[deprecated(since = "0.5.0", note = "use ondoubleclick instead")]
ondblclick
ondoubleclick: "ondblclick"
/// onmousedown
onmousedown
@@ -150,131 +105,172 @@ impl_event! {
}
impl MouseData {
/// Construct MouseData with the specified properties
///
/// Note: the current implementation truncates coordinates. In the future, when we change the internal representation, it may also support a fractional part.
pub fn new(
coordinates: Coordinates,
trigger_button: Option<MouseButton>,
held_buttons: MouseButtonSet,
modifiers: Modifiers,
) -> Self {
let alt_key = modifiers.contains(Modifiers::ALT);
let ctrl_key = modifiers.contains(Modifiers::CONTROL);
let meta_key = modifiers.contains(Modifiers::META);
let shift_key = modifiers.contains(Modifiers::SHIFT);
let [client_x, client_y]: [i32; 2] = coordinates.client().cast().into();
let [offset_x, offset_y]: [i32; 2] = coordinates.element().cast().into();
let [page_x, page_y]: [i32; 2] = coordinates.page().cast().into();
let [screen_x, screen_y]: [i32; 2] = coordinates.screen().cast().into();
#[allow(deprecated)]
/// Create a new instance of MouseData
pub fn new(inner: impl HasMouseData + 'static) -> Self {
Self {
alt_key,
ctrl_key,
meta_key,
shift_key,
button: trigger_button.map_or(0, |b| b.into_web_code()),
buttons: encode_mouse_button_set(held_buttons),
client_x,
client_y,
offset_x,
offset_y,
page_x,
page_y,
screen_x,
screen_y,
inner: Box::new(inner),
}
}
/// The event's coordinates relative to the application's viewport (as opposed to the coordinate within the page).
///
/// For example, clicking in the top left corner of the viewport will always result in a mouse event with client coordinates (0., 0.), regardless of whether the page is scrolled horizontally.
pub fn client_coordinates(&self) -> ClientPoint {
#[allow(deprecated)]
ClientPoint::new(self.client_x.into(), self.client_y.into())
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl InteractionLocation for MouseData {
fn client_coordinates(&self) -> ClientPoint {
self.inner.client_coordinates()
}
/// The event's coordinates relative to the padding edge of the target element
///
/// For example, clicking in the top left corner of an element will result in element coordinates (0., 0.)
pub fn element_coordinates(&self) -> ElementPoint {
#[allow(deprecated)]
ElementPoint::new(self.offset_x.into(), self.offset_y.into())
fn page_coordinates(&self) -> PagePoint {
self.inner.page_coordinates()
}
/// The event's coordinates relative to the entire document. This includes any portion of the document not currently visible.
///
/// For example, if the page is scrolled 200 pixels to the right and 300 pixels down, clicking in the top left corner of the viewport would result in page coordinates (200., 300.)
pub fn page_coordinates(&self) -> PagePoint {
#[allow(deprecated)]
PagePoint::new(self.page_x.into(), self.page_y.into())
fn screen_coordinates(&self) -> ScreenPoint {
self.inner.screen_coordinates()
}
}
impl InteractionElementOffset for MouseData {
fn element_coordinates(&self) -> ElementPoint {
self.inner.element_coordinates()
}
/// The event's coordinates relative to the entire screen. This takes into account the window's offset.
pub fn screen_coordinates(&self) -> ScreenPoint {
#[allow(deprecated)]
ScreenPoint::new(self.screen_x.into(), self.screen_y.into())
}
pub fn coordinates(&self) -> Coordinates {
Coordinates::new(
self.screen_coordinates(),
self.client_coordinates(),
self.element_coordinates(),
self.page_coordinates(),
)
fn coordinates(&self) -> Coordinates {
self.inner.coordinates()
}
}
impl ModifiersInteraction for MouseData {
/// 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 {
self.inner.modifiers()
}
}
impl PointerInteraction for MouseData {
/// The set of mouse buttons which were held when the event occurred.
pub fn held_buttons(&self) -> MouseButtonSet {
#[allow(deprecated)]
decode_mouse_button_set(self.buttons)
fn held_buttons(&self) -> MouseButtonSet {
self.inner.held_buttons()
}
/// The mouse button that triggered the event
///
// todo the following is kind of bad; should we just return None when the trigger_button is unreliable (and frankly irrelevant)? i guess we would need the event_type here
/// This is only guaranteed to indicate which button was pressed during events caused by pressing or releasing a button. As such, it is not reliable for events such as mouseenter, mouseleave, mouseover, mouseout, or mousemove. For example, a value of MouseButton::Primary may also indicate that no button was pressed.
pub fn trigger_button(&self) -> Option<MouseButton> {
#[allow(deprecated)]
Some(MouseButton::from_web_code(self.button))
fn trigger_button(&self) -> Option<MouseButton> {
self.inner.trigger_button()
}
}
impl Debug for MouseData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MouseData")
.field("coordinates", &self.coordinates())
.field("modifiers", &self.modifiers())
.field("held_buttons", &self.held_buttons())
.field("trigger_button", &self.trigger_button())
.finish()
impl PartialEq for MouseData {
fn eq(&self, other: &Self) -> bool {
self.coordinates() == other.coordinates()
&& self.modifiers() == other.modifiers()
&& self.held_buttons() == other.held_buttons()
&& self.trigger_button() == other.trigger_button()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of [`MouseData`]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Default)]
pub struct SerializedMouseData {
/// Common data for all pointer/mouse events
#[serde(flatten)]
point_data: crate::point_interaction::SerializedPointInteraction,
}
#[cfg(feature = "serialize")]
impl SerializedMouseData {
/// Create a new instance of SerializedMouseData
pub fn new(
trigger_button: Option<MouseButton>,
held_buttons: MouseButtonSet,
coordinates: Coordinates,
modifiers: Modifiers,
) -> Self {
Self {
point_data: crate::point_interaction::SerializedPointInteraction::new(
trigger_button,
held_buttons,
coordinates,
modifiers,
),
}
}
}
#[cfg(feature = "serialize")]
impl From<&MouseData> for SerializedMouseData {
fn from(e: &MouseData) -> Self {
Self {
point_data: crate::point_interaction::SerializedPointInteraction::from(e),
}
}
}
#[cfg(feature = "serialize")]
impl HasMouseData for SerializedMouseData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl InteractionLocation for SerializedMouseData {
fn client_coordinates(&self) -> ClientPoint {
self.point_data.client_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.point_data.page_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.point_data.screen_coordinates()
}
}
#[cfg(feature = "serialize")]
impl InteractionElementOffset for SerializedMouseData {
fn element_coordinates(&self) -> ElementPoint {
self.point_data.element_coordinates()
}
}
#[cfg(feature = "serialize")]
impl ModifiersInteraction for SerializedMouseData {
fn modifiers(&self) -> Modifiers {
self.point_data.modifiers()
}
}
#[cfg(feature = "serialize")]
impl PointerInteraction for SerializedMouseData {
fn held_buttons(&self) -> MouseButtonSet {
self.point_data.held_buttons()
}
fn trigger_button(&self) -> Option<MouseButton> {
self.point_data.trigger_button()
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for MouseData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedMouseData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for MouseData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedMouseData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
+350 -26
View File
@@ -1,33 +1,107 @@
use dioxus_core::Event;
use keyboard_types::Modifiers;
use crate::{geometry::*, input_data::*, prelude::*};
/// A synthetic event that wraps a web-style [`PointerEvent`](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
pub type PointerEvent = Event<PointerData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct PointerData {
// Mouse only
pub alt_key: bool,
pub button: i16,
pub buttons: u16,
pub client_x: i32,
pub client_y: i32,
pub ctrl_key: bool,
pub meta_key: bool,
pub page_x: i32,
pub page_y: i32,
pub screen_x: i32,
pub screen_y: i32,
pub shift_key: bool,
pub pointer_id: i32,
pub width: i32,
pub height: i32,
pub pressure: f32,
pub tangential_pressure: f32,
pub tilt_x: i32,
pub tilt_y: i32,
pub twist: i32,
pub pointer_type: String,
pub is_primary: bool,
// pub get_modifier_state: bool,
inner: Box<dyn HasPointerData>,
}
impl PointerData {
/// Create a new PointerData
pub fn new(data: impl HasPointerData + 'static) -> Self {
Self::from(data)
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl<E: HasPointerData + 'static> From<E> for PointerData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for PointerData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PointerData")
.field("pointer_id", &self.pointer_id())
.field("width", &self.width())
.field("height", &self.height())
.field("pressure", &self.pressure())
.field("tangential_pressure", &self.tangential_pressure())
.field("tilt_x", &self.tilt_x())
.field("tilt_y", &self.tilt_y())
.field("twist", &self.twist())
.field("pointer_type", &self.pointer_type())
.field("is_primary", &self.is_primary())
.field("coordinates", &self.coordinates())
.field("modifiers", &self.modifiers())
.field("held_buttons", &self.held_buttons())
.field("trigger_button", &self.trigger_button())
.finish()
}
}
impl PartialEq for PointerData {
fn eq(&self, other: &Self) -> bool {
self.pointer_id() == other.pointer_id()
&& self.width() == other.width()
&& self.height() == other.height()
&& self.pressure() == other.pressure()
&& self.tangential_pressure() == other.tangential_pressure()
&& self.tilt_x() == other.tilt_x()
&& self.tilt_y() == other.tilt_y()
&& self.twist() == other.twist()
&& self.pointer_type() == other.pointer_type()
&& self.is_primary() == other.is_primary()
&& self.coordinates() == other.coordinates()
&& self.modifiers() == other.modifiers()
&& self.held_buttons() == other.held_buttons()
&& self.trigger_button() == other.trigger_button()
}
}
/// A trait for any object that has the data for a pointer event
pub trait HasPointerData: PointerInteraction {
/// Gets the unique identifier of the pointer causing the event.
fn pointer_id(&self) -> i32;
/// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
fn width(&self) -> i32;
/// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
fn height(&self) -> i32;
/// Gets the normalized pressure of the pointer input in the range of 0 to 1,
fn pressure(&self) -> f32;
/// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
fn tangential_pressure(&self) -> f32;
/// Gets the plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
fn tilt_x(&self) -> i32;
/// Gets the plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
fn tilt_y(&self) -> i32;
/// Gets the clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
fn twist(&self) -> i32;
/// Gets the device type that caused the event (mouse, pen, touch, etc.).
fn pointer_type(&self) -> String;
/// Gets if the pointer represents the primary pointer of this pointer type.
fn is_primary(&self) -> bool;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event![
@@ -62,3 +136,253 @@ impl_event![
/// pointerout
onpointerout
];
impl PointerData {
/// Gets the unique identifier of the pointer causing the event.
pub fn pointer_id(&self) -> i32 {
self.inner.pointer_id()
}
/// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
pub fn width(&self) -> i32 {
self.inner.width()
}
/// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
pub fn height(&self) -> i32 {
self.inner.height()
}
/// Gets the normalized pressure of the pointer input in the range of 0 to 1,
pub fn pressure(&self) -> f32 {
self.inner.pressure()
}
/// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
pub fn tangential_pressure(&self) -> f32 {
self.inner.tangential_pressure()
}
/// Gets the plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
pub fn tilt_x(&self) -> i32 {
self.inner.tilt_x()
}
/// Gets the plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
pub fn tilt_y(&self) -> i32 {
self.inner.tilt_y()
}
/// Gets the clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
pub fn twist(&self) -> i32 {
self.inner.twist()
}
/// Gets the device type that caused the event (mouse, pen, touch, etc.).
pub fn pointer_type(&self) -> String {
self.inner.pointer_type()
}
/// Gets if the pointer represents the primary pointer of this pointer type.
pub fn is_primary(&self) -> bool {
self.inner.is_primary()
}
}
impl InteractionLocation for PointerData {
fn client_coordinates(&self) -> ClientPoint {
self.inner.client_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.inner.screen_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.inner.page_coordinates()
}
}
impl InteractionElementOffset for PointerData {
fn element_coordinates(&self) -> ElementPoint {
self.inner.element_coordinates()
}
}
impl ModifiersInteraction for PointerData {
fn modifiers(&self) -> Modifiers {
self.inner.modifiers()
}
}
impl PointerInteraction for PointerData {
fn held_buttons(&self) -> MouseButtonSet {
self.inner.held_buttons()
}
fn trigger_button(&self) -> Option<MouseButton> {
self.inner.trigger_button()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of PointerData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedPointerData {
/// Common data for all pointer/mouse events
#[serde(flatten)]
point_data: crate::point_interaction::SerializedPointInteraction,
/// The unique identifier of the pointer causing the event.
pointer_id: i32,
/// The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
width: i32,
/// The height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
height: i32,
/// The normalized pressure of the pointer input in the range of 0 to 1,
pressure: f32,
/// The normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
tangential_pressure: f32,
/// The plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
tilt_x: i32,
/// The plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
tilt_y: i32,
/// The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
twist: i32,
/// Indicates the device type that caused the event (mouse, pen, touch, etc.).
pointer_type: String,
/// Indicates if the pointer represents the primary pointer of this pointer type.
is_primary: bool,
}
#[cfg(feature = "serialize")]
impl HasPointerData for SerializedPointerData {
fn pointer_id(&self) -> i32 {
self.pointer_id
}
fn width(&self) -> i32 {
self.width
}
fn height(&self) -> i32 {
self.height
}
fn pressure(&self) -> f32 {
self.pressure
}
fn tangential_pressure(&self) -> f32 {
self.tangential_pressure
}
fn tilt_x(&self) -> i32 {
self.tilt_x
}
fn tilt_y(&self) -> i32 {
self.tilt_y
}
fn twist(&self) -> i32 {
self.twist
}
fn pointer_type(&self) -> String {
self.pointer_type.clone()
}
fn is_primary(&self) -> bool {
self.is_primary
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl InteractionLocation for SerializedPointerData {
fn client_coordinates(&self) -> ClientPoint {
self.point_data.client_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.point_data.screen_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.point_data.page_coordinates()
}
}
#[cfg(feature = "serialize")]
impl InteractionElementOffset for SerializedPointerData {
fn element_coordinates(&self) -> ElementPoint {
self.point_data.element_coordinates()
}
}
#[cfg(feature = "serialize")]
impl ModifiersInteraction for SerializedPointerData {
fn modifiers(&self) -> Modifiers {
self.point_data.modifiers()
}
}
#[cfg(feature = "serialize")]
impl PointerInteraction for SerializedPointerData {
fn held_buttons(&self) -> MouseButtonSet {
self.point_data.held_buttons()
}
fn trigger_button(&self) -> Option<MouseButton> {
self.point_data.trigger_button()
}
}
#[cfg(feature = "serialize")]
impl From<&PointerData> for SerializedPointerData {
fn from(data: &PointerData) -> Self {
Self {
point_data: data.into(),
pointer_id: data.pointer_id(),
width: data.width(),
height: data.height(),
pressure: data.pressure(),
tangential_pressure: data.tangential_pressure(),
tilt_x: data.tilt_x(),
tilt_y: data.tilt_y(),
twist: data.twist(),
pointer_type: data.pointer_type().to_string(),
is_primary: data.is_primary(),
}
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for PointerData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedPointerData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for PointerData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedPointerData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
+77 -3
View File
@@ -1,9 +1,83 @@
use dioxus_core::Event;
pub type ScrollEvent = Event<ScrollData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScrollData {}
pub struct ScrollData {
inner: Box<dyn HasScrollData>,
}
impl<E: HasScrollData> From<E> for ScrollData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl ScrollData {
/// Create a new ScrollData
pub fn new(inner: impl HasScrollData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl std::fmt::Debug for ScrollData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ScrollData").finish()
}
}
impl PartialEq for ScrollData {
fn eq(&self, _other: &Self) -> bool {
true
}
}
#[cfg(feature = "serialize")]
/// A serialized version of ScrollData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedScrollData {}
#[cfg(feature = "serialize")]
impl From<&ScrollData> for SerializedScrollData {
fn from(_: &ScrollData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasScrollData for SerializedScrollData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for ScrollData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedScrollData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for ScrollData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedScrollData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasScrollData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! {
ScrollData;
+77 -3
View File
@@ -1,9 +1,83 @@
use dioxus_core::Event;
pub type SelectionEvent = Event<SelectionData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SelectionData {}
pub struct SelectionData {
inner: Box<dyn HasSelectionData>,
}
impl SelectionData {
/// Create a new SelectionData
pub fn new(inner: impl HasSelectionData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl<E: HasSelectionData> From<E> for SelectionData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for SelectionData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SelectionData").finish()
}
}
impl PartialEq for SelectionData {
fn eq(&self, _other: &Self) -> bool {
true
}
}
#[cfg(feature = "serialize")]
/// A serialized version of SelectionData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedSelectionData {}
#[cfg(feature = "serialize")]
impl From<&SelectionData> for SerializedSelectionData {
fn from(_: &SelectionData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasSelectionData for SerializedSelectionData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for SelectionData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedSelectionData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for SelectionData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedSelectionData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasSelectionData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! [
SelectionData;
+77 -3
View File
@@ -1,9 +1,83 @@
use dioxus_core::Event;
pub type ToggleEvent = Event<ToggleData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToggleData {}
pub struct ToggleData {
inner: Box<dyn HasToggleData>,
}
impl<E: HasToggleData> From<E> for ToggleData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for ToggleData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ToggleData").finish()
}
}
impl PartialEq for ToggleData {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl ToggleData {
/// Create a new ToggleData
pub fn new(inner: impl HasToggleData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of ToggleData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedToggleData {}
#[cfg(feature = "serialize")]
impl From<&ToggleData> for SerializedToggleData {
fn from(_: &ToggleData) -> Self {
Self {}
}
}
#[cfg(feature = "serialize")]
impl HasToggleData for SerializedToggleData {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for ToggleData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedToggleData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for ToggleData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedToggleData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasToggleData: std::any::Any {
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! {
ToggleData;
+346 -10
View File
@@ -1,17 +1,353 @@
use dioxus_core::Event;
use keyboard_types::Modifiers;
use crate::geometry::*;
use crate::prelude::{InteractionLocation, ModifiersInteraction};
pub type TouchEvent = Event<TouchData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TouchData {
pub alt_key: bool,
pub ctrl_key: bool,
pub meta_key: bool,
pub shift_key: bool,
// get_modifier_state: bool,
// changedTouches: DOMTouchList,
// targetTouches: DOMTouchList,
// touches: DOMTouchList,
inner: Box<dyn HasTouchData>,
}
impl<E: HasTouchData> From<E> for TouchData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for TouchData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TouchData")
.field("modifiers", &self.modifiers())
.field("touches", &self.touches())
.field("touches_changed", &self.touches_changed())
.field("target_touches", &self.target_touches())
.finish()
}
}
impl PartialEq for TouchData {
fn eq(&self, other: &Self) -> bool {
self.modifiers() == other.modifiers()
}
}
impl TouchData {
/// Create a new TouchData
pub fn new(inner: impl HasTouchData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Get the pointers that are currently down
pub fn touches(&self) -> Vec<TouchPoint> {
self.inner.touches()
}
/// Get the touches that have changed since the last event
pub fn touches_changed(&self) -> Vec<TouchPoint> {
self.inner.touches_changed()
}
/// Get the touches that started and stayed on the element that triggered this event
pub fn target_touches(&self) -> Vec<TouchPoint> {
self.inner.target_touches()
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl ModifiersInteraction for TouchData {
fn modifiers(&self) -> Modifiers {
self.inner.modifiers()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of TouchData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedTouchData {
alt_key: bool,
ctrl_key: bool,
meta_key: bool,
shift_key: bool,
touches: Vec<SerializedTouchPoint>,
changed_touches: Vec<SerializedTouchPoint>,
target_touches: Vec<SerializedTouchPoint>,
}
#[cfg(feature = "serialize")]
impl From<&TouchData> for SerializedTouchData {
fn from(data: &TouchData) -> Self {
let modifiers = data.modifiers();
Self {
alt_key: modifiers.contains(Modifiers::ALT),
ctrl_key: modifiers.contains(Modifiers::CONTROL),
meta_key: modifiers.contains(Modifiers::META),
shift_key: modifiers.contains(Modifiers::SHIFT),
touches: data.touches().iter().map(|t| t.into()).collect(),
changed_touches: data.touches_changed().iter().map(|t| t.into()).collect(),
target_touches: data.target_touches().iter().map(|t| t.into()).collect(),
}
}
}
#[cfg(feature = "serialize")]
impl ModifiersInteraction for SerializedTouchData {
fn modifiers(&self) -> Modifiers {
let mut modifiers = Modifiers::default();
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
}
}
#[cfg(feature = "serialize")]
impl HasTouchData for SerializedTouchData {
fn touches(&self) -> Vec<TouchPoint> {
self.touches.clone().into_iter().map(Into::into).collect()
}
fn touches_changed(&self) -> Vec<TouchPoint> {
self.changed_touches
.clone()
.into_iter()
.map(Into::into)
.collect()
}
fn target_touches(&self) -> Vec<TouchPoint> {
self.target_touches
.clone()
.into_iter()
.map(Into::into)
.collect()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for TouchData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedTouchData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for TouchData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedTouchData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasTouchData: ModifiersInteraction + std::any::Any {
/// Get the touches that are currently down
fn touches(&self) -> Vec<TouchPoint>;
/// Get the touches that have changed since the last event
fn touches_changed(&self) -> Vec<TouchPoint>;
/// Get the touches that started and stayed on the element that triggered this event
fn target_touches(&self) -> Vec<TouchPoint>;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
pub struct TouchPoint {
inner: Box<dyn HasTouchPointData>,
}
impl<E: HasTouchPointData> From<E> for TouchPoint {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl TouchPoint {
/// Create a new TouchPoint
pub fn new(inner: impl HasTouchPointData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// A unique identifier for this touch point that will be the same for the duration of the touch
fn identifier(&self) -> i32 {
self.inner.identifier()
}
/// the pressure of the touch
fn force(&self) -> f64 {
self.inner.force()
}
/// the radius of the touch
fn radius(&self) -> ScreenPoint {
self.inner.radius()
}
/// the rotation of the touch in degrees between 0 and 90
fn rotation(&self) -> f64 {
self.inner.rotation()
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
impl std::fmt::Debug for TouchPoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TouchPoint")
.field("client_coordinates", &self.client_coordinates())
.field("page_coordinates", &self.page_coordinates())
.field("screen_coordinates", &self.screen_coordinates())
.field("identifier", &self.identifier())
.field("force", &self.force())
.field("radius", &self.radius())
.field("rotation", &self.rotation())
.finish()
}
}
impl InteractionLocation for TouchPoint {
fn client_coordinates(&self) -> ClientPoint {
self.inner.client_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.inner.page_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.inner.screen_coordinates()
}
}
/// A trait for touch point data
pub trait HasTouchPointData: InteractionLocation + std::any::Any {
/// A unique identifier for this touch point that will be the same for the duration of the touch
fn identifier(&self) -> i32;
/// the pressure of the touch
fn force(&self) -> f64;
/// the radius of the touch
fn radius(&self) -> ScreenPoint;
/// the rotation of the touch in degrees between 0 and 90
fn rotation(&self) -> f64;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
#[cfg(feature = "serialize")]
/// A serialized version of TouchPoint
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
struct SerializedTouchPoint {
identifier: i32,
client_x: f64,
client_y: f64,
page_x: f64,
page_y: f64,
screen_x: f64,
screen_y: f64,
force: f64,
radius_x: f64,
radius_y: f64,
rotation_angle: f64,
}
#[cfg(feature = "serialize")]
impl From<&TouchPoint> for SerializedTouchPoint {
fn from(point: &TouchPoint) -> Self {
let client_coordinates = point.client_coordinates();
let page_coordinates = point.page_coordinates();
let screen_coordinates = point.screen_coordinates();
Self {
identifier: point.identifier(),
client_x: client_coordinates.x,
client_y: client_coordinates.y,
page_x: page_coordinates.x,
page_y: page_coordinates.y,
screen_x: screen_coordinates.x,
screen_y: screen_coordinates.y,
force: point.force(),
radius_x: point.radius().x,
radius_y: point.radius().y,
rotation_angle: point.rotation(),
}
}
}
#[cfg(feature = "serialize")]
impl HasTouchPointData for SerializedTouchPoint {
/// A unique identifier for this touch point that will be the same for the duration of the touch
fn identifier(&self) -> i32 {
self.identifier
}
/// the pressure of the touch
fn force(&self) -> f64 {
self.force
}
/// the radius of the touch
fn radius(&self) -> ScreenPoint {
ScreenPoint::new(self.radius_x, self.radius_y)
}
/// the rotation of the touch in degrees between 0 and 90
fn rotation(&self) -> f64 {
self.rotation_angle
}
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl InteractionLocation for SerializedTouchPoint {
/// Gets the coordinates of the event relative to the browser viewport.
fn client_coordinates(&self) -> ClientPoint {
ClientPoint::new(self.client_x, self.client_y)
}
/// Gets the coordinates of the event relative to the screen.
fn screen_coordinates(&self) -> ScreenPoint {
ScreenPoint::new(self.screen_x, self.screen_y)
}
/// Gets the coordinates of the event relative to the page.
fn page_coordinates(&self) -> PagePoint {
PagePoint::new(self.page_x, self.page_y)
}
}
impl_event! {
+104 -5
View File
@@ -1,12 +1,111 @@
use dioxus_core::Event;
pub type TransitionEvent = Event<TransitionData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct TransitionData {
pub property_name: String,
pub pseudo_element: String,
pub elapsed_time: f32,
inner: Box<dyn HasTransitionData>,
}
impl<E: HasTransitionData> From<E> for TransitionData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for TransitionData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TransitionData")
.field("property_name", &self.inner.property_name())
.field("pseudo_element", &self.inner.pseudo_element())
.field("elapsed_time", &self.inner.elapsed_time())
.finish()
}
}
impl PartialEq for TransitionData {
fn eq(&self, other: &Self) -> bool {
self.inner.property_name() == other.inner.property_name()
&& self.inner.pseudo_element() == other.inner.pseudo_element()
&& self.inner.elapsed_time() == other.inner.elapsed_time()
}
}
impl TransitionData {
/// Create a new TransitionData
pub fn new(inner: impl HasTransitionData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of TransitionData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedTransitionData {
property_name: String,
pseudo_element: String,
elapsed_time: f32,
}
#[cfg(feature = "serialize")]
impl From<&TransitionData> for SerializedTransitionData {
fn from(data: &TransitionData) -> Self {
Self {
property_name: data.inner.property_name(),
pseudo_element: data.inner.pseudo_element(),
elapsed_time: data.inner.elapsed_time(),
}
}
}
#[cfg(feature = "serialize")]
impl HasTransitionData for SerializedTransitionData {
fn property_name(&self) -> String {
self.property_name.clone()
}
fn pseudo_element(&self) -> String {
self.pseudo_element.clone()
}
fn elapsed_time(&self) -> f32 {
self.elapsed_time
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for TransitionData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedTransitionData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for TransitionData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedTransitionData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
pub trait HasTransitionData: std::any::Any {
fn property_name(&self) -> String;
fn pseudo_element(&self) -> String;
fn elapsed_time(&self) -> f32;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
impl_event! {
+108 -57
View File
@@ -1,23 +1,118 @@
use dioxus_core::Event;
use euclid::UnknownUnit;
use std::fmt::{Debug, Formatter};
use std::fmt::Formatter;
use crate::geometry::{LinesVector, PagesVector, PixelsVector, WheelDelta};
use crate::geometry::WheelDelta;
pub type WheelEvent = Event<WheelData>;
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, PartialEq, Default)]
pub struct WheelData {
#[deprecated(since = "0.3.0", note = "use delta() instead")]
inner: Box<dyn HasWheelData>,
}
impl<E: HasWheelData> From<E> for WheelData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl std::fmt::Debug for WheelData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WheelData")
.field("delta", &self.delta())
.finish()
}
}
impl PartialEq for WheelData {
fn eq(&self, other: &Self) -> bool {
self.inner.delta() == other.inner.delta()
}
}
impl WheelData {
/// Create a new WheelData
pub fn new(inner: impl HasWheelData + 'static) -> Self {
Self {
inner: Box::new(inner),
}
}
/// The amount of wheel movement
#[allow(deprecated)]
pub fn delta(&self) -> WheelDelta {
self.inner.delta()
}
/// Downcast this event to a concrete event type
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
#[cfg(feature = "serialize")]
/// A serialized version of WheelData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedWheelData {
pub delta_mode: u32,
#[deprecated(since = "0.3.0", note = "use delta() instead")]
pub delta_x: f64,
#[deprecated(since = "0.3.0", note = "use delta() instead")]
pub delta_y: f64,
#[deprecated(since = "0.3.0", note = "use delta() instead")]
pub delta_z: f64,
}
#[cfg(feature = "serialize")]
impl SerializedWheelData {
/// Create a new SerializedWheelData
pub fn new(delta: WheelDelta) -> Self {
let delta_mode = match delta {
WheelDelta::Pixels(_) => 0,
WheelDelta::Lines(_) => 1,
WheelDelta::Pages(_) => 2,
};
let delta_raw = delta.strip_units();
Self {
delta_mode,
delta_x: delta_raw.x,
delta_y: delta_raw.y,
delta_z: delta_raw.z,
}
}
}
#[cfg(feature = "serialize")]
impl From<&WheelData> for SerializedWheelData {
fn from(data: &WheelData) -> Self {
Self::new(data.delta())
}
}
#[cfg(feature = "serialize")]
impl HasWheelData for SerializedWheelData {
fn delta(&self) -> WheelDelta {
WheelDelta::from_web_attributes(self.delta_mode, self.delta_x, self.delta_y, self.delta_z)
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg(feature = "serialize")]
impl serde::Serialize for WheelData {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
SerializedWheelData::from(self).serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de> serde::Deserialize<'de> for WheelData {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let data = SerializedWheelData::deserialize(deserializer)?;
Ok(Self {
inner: Box::new(data),
})
}
}
impl_event![
WheelData;
@@ -25,54 +120,10 @@ impl_event![
onwheel
];
impl WheelData {
/// Construct a new WheelData with the specified wheel movement delta
pub fn new(delta: WheelDelta) -> Self {
let (delta_mode, vector) = match delta {
WheelDelta::Pixels(v) => (0, v.cast_unit::<UnknownUnit>()),
WheelDelta::Lines(v) => (1, v.cast_unit::<UnknownUnit>()),
WheelDelta::Pages(v) => (2, v.cast_unit::<UnknownUnit>()),
};
#[allow(deprecated)]
WheelData {
delta_mode,
delta_x: vector.x,
delta_y: vector.y,
delta_z: vector.z,
}
}
/// Construct from the attributes of the web wheel event
pub fn from_web_attributes(delta_mode: u32, delta_x: f64, delta_y: f64, delta_z: f64) -> Self {
#[allow(deprecated)]
Self {
delta_mode,
delta_x,
delta_y,
delta_z,
}
}
pub trait HasWheelData: std::any::Any {
/// The amount of wheel movement
#[allow(deprecated)]
pub fn delta(&self) -> WheelDelta {
let x = self.delta_x;
let y = self.delta_y;
let z = self.delta_z;
match self.delta_mode {
0 => WheelDelta::Pixels(PixelsVector::new(x, y, z)),
1 => WheelDelta::Lines(LinesVector::new(x, y, z)),
2 => WheelDelta::Pages(PagesVector::new(x, y, z)),
_ => panic!("Invalid delta mode, {:?}", self.delta_mode),
}
}
}
fn delta(&self) -> WheelDelta;
impl Debug for WheelData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WheelData")
.field("delta", &self.delta())
.finish()
}
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}