ソースを参照

Add `From` trait to convert web_sys Events to html Data

Aster 3 年 前
コミット
8d42191d7a

+ 4 - 1
.gitignore

@@ -8,4 +8,7 @@ Cargo.lock
 !.vscode/tasks.json
 !.vscode/launch.json
 !.vscode/extensions.json
-tarpaulin-report.html
+tarpaulin-report.html
+
+# Jetbrain
+.idea/

+ 21 - 0
packages/html/Cargo.toml

@@ -14,7 +14,28 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
 dioxus-core = { path = "../core", version = "^0.1.9" }
 serde = { version = "1", features = ["derive"], optional = true }
 serde_repr = { version = "0.1", optional = true }
+wasm-bindgen = { version = "0.2.79", optional = true }
+
+[dependencies.web-sys]
+optional = true
+version = "0.3.56"
+features = [
+    "TouchEvent",
+    "MouseEvent",
+    "InputEvent",
+    "ClipboardEvent",
+    "KeyboardEvent",
+    "TouchEvent",
+    "WheelEvent",
+    "AnimationEvent",
+    "TransitionEvent",
+    "PointerEvent",
+    "FocusEvent",
+    "CompositionEvent",
+    "ClipboardEvent",
+]
 
 [features]
 default = []
 serialize = ["serde", "serde_repr"]
+wasm-bind = ["web-sys", "wasm-bindgen"]

+ 2 - 0
packages/html/src/lib.rs

@@ -16,6 +16,8 @@
 mod elements;
 mod events;
 mod global_attributes;
+#[cfg(feature = "wasm-bind")]
+mod web_sys_bind;
 
 pub use elements::*;
 pub use events::*;

+ 161 - 0
packages/html/src/web_sys_bind/events.rs

@@ -0,0 +1,161 @@
+use crate::on::{
+    AnimationData, CompositionData, KeyboardData, MouseData, PointerData, TouchData,
+    TransitionData, WheelData,
+};
+use crate::KeyCode;
+use wasm_bindgen::JsCast;
+use web_sys::{
+    AnimationEvent, CompositionEvent, Event, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent,
+    TransitionEvent, WheelEvent,
+};
+
+macro_rules! uncheck_convert {
+    ($t:ty, $d:ty) => {
+        impl From<Event> for $d {
+            #[inline]
+            fn from(e: Event) -> Self {
+                let e: $t = e.unchecked_into();
+                Self::from(&e)
+            }
+        }
+
+        impl From<&Event> for $d {
+            #[inline]
+            fn from(e: &Event) -> Self {
+                let e: &$t = e.unchecked_ref();
+                Self::from(e)
+            }
+        }
+    };
+    ($($t:ty => $d:ty),+ $(,)?) => {
+        $(uncheck_convert!($t, $d);)+
+    };
+}
+
+uncheck_convert![
+    CompositionEvent => CompositionData,
+    KeyboardEvent    => KeyboardData,
+    MouseEvent       => MouseData,
+    TouchEvent       => TouchData,
+    PointerEvent     => PointerData,
+    WheelEvent       => WheelData,
+    AnimationEvent   => AnimationData,
+    TransitionEvent  => TransitionData,
+];
+
+impl From<&CompositionEvent> for CompositionData {
+    fn from(e: &CompositionEvent) -> Self {
+        Self {
+            data: e.data().unwrap_or_default(),
+        }
+    }
+}
+
+impl From<&KeyboardEvent> for KeyboardData {
+    fn from(e: &KeyboardEvent) -> Self {
+        Self {
+            alt_key: e.alt_key(),
+            char_code: e.char_code(),
+            key: e.key(),
+            key_code: KeyCode::from_raw_code(e.key_code() as u8),
+            ctrl_key: e.ctrl_key(),
+            locale: "not implemented".to_string(),
+            location: e.location() as usize,
+            meta_key: e.meta_key(),
+            repeat: e.repeat(),
+            shift_key: e.shift_key(),
+            which: e.which() as usize,
+        }
+    }
+}
+
+impl From<&MouseEvent> for MouseData {
+    fn from(e: &MouseEvent) -> Self {
+        Self {
+            alt_key: e.alt_key(),
+            button: e.button(),
+            buttons: e.buttons(),
+            client_x: e.client_x(),
+            client_y: e.client_y(),
+            ctrl_key: e.ctrl_key(),
+            meta_key: e.meta_key(),
+            screen_x: e.screen_x(),
+            screen_y: e.screen_y(),
+            shift_key: e.shift_key(),
+            page_x: e.page_x(),
+            page_y: e.page_y(),
+        }
+    }
+}
+
+impl From<&TouchEvent> for TouchData {
+    fn from(e: &TouchEvent) -> Self {
+        Self {
+            alt_key: e.alt_key(),
+            ctrl_key: e.ctrl_key(),
+            meta_key: e.meta_key(),
+            shift_key: e.shift_key(),
+        }
+    }
+}
+
+impl From<&PointerEvent> for PointerData {
+    fn from(e: &PointerEvent) -> Self {
+        Self {
+            alt_key: e.alt_key(),
+            button: e.button(),
+            buttons: e.buttons(),
+            client_x: e.client_x(),
+            client_y: e.client_y(),
+            ctrl_key: e.ctrl_key(),
+            meta_key: e.meta_key(),
+            page_x: e.page_x(),
+            page_y: e.page_y(),
+            screen_x: e.screen_x(),
+            screen_y: e.screen_y(),
+            shift_key: e.shift_key(),
+            pointer_id: e.pointer_id(),
+            width: e.width(),
+            height: e.height(),
+            pressure: e.pressure(),
+            tangential_pressure: e.tangential_pressure(),
+            tilt_x: e.tilt_x(),
+            tilt_y: e.tilt_y(),
+            twist: e.twist(),
+            pointer_type: e.pointer_type(),
+            is_primary: e.is_primary(),
+            // get_modifier_state: evt.get_modifier_state(),
+        }
+    }
+}
+
+impl From<&WheelEvent> for WheelData {
+    fn from(e: &WheelEvent) -> Self {
+        Self {
+            delta_x: e.delta_x(),
+            delta_y: e.delta_y(),
+            delta_z: e.delta_z(),
+            delta_mode: e.delta_mode(),
+        }
+    }
+}
+
+impl From<&AnimationEvent> for AnimationData {
+    fn from(e: &AnimationEvent) -> Self {
+        Self {
+            elapsed_time: e.elapsed_time(),
+            animation_name: e.animation_name(),
+            pseudo_element: e.pseudo_element(),
+        }
+    }
+}
+
+impl From<&TransitionEvent> for TransitionData {
+    fn from(e: &TransitionEvent) -> Self {
+        Self {
+            elapsed_time: e.elapsed_time(),
+            property_name: e.property_name(),
+            pseudo_element: e.pseudo_element(),
+        }
+    }
+}

+ 1 - 0
packages/html/src/web_sys_bind/mod.rs

@@ -0,0 +1 @@
+mod events;

+ 1 - 1
packages/web/Cargo.toml

@@ -12,7 +12,7 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
 
 [dependencies]
 dioxus-core = { path = "../core", version = "^0.1.9" }
-dioxus-html = { path = "../html", version = "^0.1.6" }
+dioxus-html = { path = "../html", version = "^0.1.6", features = ["wasm-bind"] }
 js-sys = "0.3.56"
 wasm-bindgen = { version = "0.2.79", features = ["enable-interning"] }
 lazy_static = "1.4.0"

+ 7 - 90
packages/web/src/dom.rs

@@ -170,7 +170,6 @@ fn virtual_event_from_websys_event(
     target: Element,
 ) -> Arc<dyn Any + Send + Sync> {
     use dioxus_html::on::*;
-    use dioxus_html::KeyCode;
 
     match event.type_().as_str() {
         "copy" | "cut" | "paste" => Arc::new(ClipboardData {}),
@@ -180,22 +179,7 @@ fn virtual_event_from_websys_event(
                 data: evt.data().unwrap_or_default(),
             })
         }
-        "keydown" | "keypress" | "keyup" => {
-            let evt: &web_sys::KeyboardEvent = event.dyn_ref().unwrap();
-            Arc::new(KeyboardData {
-                alt_key: evt.alt_key(),
-                char_code: evt.char_code(),
-                key: evt.key(),
-                key_code: KeyCode::from_raw_code(evt.key_code() as u8),
-                ctrl_key: evt.ctrl_key(),
-                locale: "not implemented".to_string(),
-                location: evt.location() as usize,
-                meta_key: evt.meta_key(),
-                repeat: evt.repeat(),
-                shift_key: evt.shift_key(),
-                which: evt.which() as usize,
-            })
-        }
+        "keydown" | "keypress" | "keyup" => Arc::new(KeyboardData::from(event)),
         "focus" | "blur" => Arc::new(FocusData {}),
 
         // todo: these handlers might get really slow if the input box gets large and allocation pressure is heavy
@@ -272,88 +256,21 @@ fn virtual_event_from_websys_event(
         "click" | "contextmenu" | "doubleclick" | "drag" | "dragend" | "dragenter" | "dragexit"
         | "dragleave" | "dragover" | "dragstart" | "drop" | "mousedown" | "mouseenter"
         | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => {
-            let evt: &web_sys::MouseEvent = event.dyn_ref().unwrap();
-            Arc::new(MouseData {
-                alt_key: evt.alt_key(),
-                button: evt.button(),
-                buttons: evt.buttons(),
-                client_x: evt.client_x(),
-                client_y: evt.client_y(),
-                ctrl_key: evt.ctrl_key(),
-                meta_key: evt.meta_key(),
-                screen_x: evt.screen_x(),
-                screen_y: evt.screen_y(),
-                shift_key: evt.shift_key(),
-                page_x: evt.page_x(),
-                page_y: evt.page_y(),
-            })
+            Arc::new(MouseData::from(event))
         }
         "pointerdown" | "pointermove" | "pointerup" | "pointercancel" | "gotpointercapture"
         | "lostpointercapture" | "pointerenter" | "pointerleave" | "pointerover" | "pointerout" => {
-            let evt: &web_sys::PointerEvent = event.dyn_ref().unwrap();
-            Arc::new(PointerData {
-                alt_key: evt.alt_key(),
-                button: evt.button(),
-                buttons: evt.buttons(),
-                client_x: evt.client_x(),
-                client_y: evt.client_y(),
-                ctrl_key: evt.ctrl_key(),
-                meta_key: evt.meta_key(),
-                page_x: evt.page_x(),
-                page_y: evt.page_y(),
-                screen_x: evt.screen_x(),
-                screen_y: evt.screen_y(),
-                shift_key: evt.shift_key(),
-                pointer_id: evt.pointer_id(),
-                width: evt.width(),
-                height: evt.height(),
-                pressure: evt.pressure(),
-                tangential_pressure: evt.tangential_pressure(),
-                tilt_x: evt.tilt_x(),
-                tilt_y: evt.tilt_y(),
-                twist: evt.twist(),
-                pointer_type: evt.pointer_type(),
-                is_primary: evt.is_primary(),
-                // get_modifier_state: evt.get_modifier_state(),
-            })
+            Arc::new(PointerData::from(event))
         }
         "select" => Arc::new(SelectionData {}),
-        "touchcancel" | "touchend" | "touchmove" | "touchstart" => {
-            let evt: &web_sys::TouchEvent = event.dyn_ref().unwrap();
-            Arc::new(TouchData {
-                alt_key: evt.alt_key(),
-                ctrl_key: evt.ctrl_key(),
-                meta_key: evt.meta_key(),
-                shift_key: evt.shift_key(),
-            })
-        }
+        "touchcancel" | "touchend" | "touchmove" | "touchstart" => Arc::new(TouchData::from(event)),
 
         "scroll" => Arc::new(()),
-        "wheel" => {
-            let evt: &web_sys::WheelEvent = event.dyn_ref().unwrap();
-            Arc::new(WheelData {
-                delta_x: evt.delta_x(),
-                delta_y: evt.delta_y(),
-                delta_z: evt.delta_z(),
-                delta_mode: evt.delta_mode(),
-            })
-        }
+        "wheel" => Arc::new(WheelData::from(event)),
         "animationstart" | "animationend" | "animationiteration" => {
-            let evt: &web_sys::AnimationEvent = event.dyn_ref().unwrap();
-            Arc::new(AnimationData {
-                elapsed_time: evt.elapsed_time(),
-                animation_name: evt.animation_name(),
-                pseudo_element: evt.pseudo_element(),
-            })
-        }
-        "transitionend" => {
-            let evt: &web_sys::TransitionEvent = event.dyn_ref().unwrap();
-            Arc::new(TransitionData {
-                elapsed_time: evt.elapsed_time(),
-                property_name: evt.property_name(),
-                pseudo_element: evt.pseudo_element(),
-            })
+            Arc::new(AnimationData::from(event))
         }
+        "transitionend" => Arc::new(TransitionData::from(event)),
         "abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
         | "ended" | "error" | "loadeddata" | "loadedmetadata" | "loadstart" | "pause" | "play"
         | "playing" | "progress" | "ratechange" | "seeked" | "seeking" | "stalled" | "suspend"