瀏覽代碼

Implement idiomatic accessors for WheelData

Reinis Mazeiks 3 年之前
父節點
當前提交
d7e4fcda80
共有 5 個文件被更改,包括 165 次插入11 次删除
  1. 0 0
      examples/event_mouse.rs
  2. 39 0
      examples/event_wheel.rs
  3. 55 1
      packages/html/src/events.rs
  4. 61 0
      packages/html/src/geometry.rs
  5. 10 10
      packages/tui/src/hooks.rs

+ 0 - 0
examples/mouse_event.rs → examples/event_mouse.rs


+ 39 - 0
examples/event_wheel.rs

@@ -0,0 +1,39 @@
+use dioxus::prelude::*;
+use dioxus_core::UiEvent;
+use dioxus_html::on::WheelData;
+
+fn main() {
+    dioxus::desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+    let delta = use_state(&cx, || "".to_string());
+
+    let container_style = r#"
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+    "#;
+    let rect_style = r#"
+        background: deepskyblue;
+        height: 50vh;
+        width: 50vw;
+    "#;
+
+    let handle_event = move |event: UiEvent<WheelData>| {
+        let wheel_data = event.data;
+        delta.set(format!("{:?}", wheel_data.delta()));
+    };
+
+    cx.render(rsx! (
+        div {
+            style: "{container_style}",
+            "Scroll mouse wheel over rectangle:",
+            div {
+                style: "{rect_style}",
+                onwheel: handle_event,
+            }
+            div {"Delta: {delta}"},
+        }
+    ))
+}

+ 55 - 1
packages/html/src/events.rs

@@ -5,10 +5,14 @@ use dioxus_core::*;
 pub mod on {
     //! Input events and associated data
 
-    use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
+    use crate::geometry::{
+        ClientPoint, Coordinates, ElementPoint, LinesVector, PagePoint, PagesVector, PixelsVector,
+        ScreenPoint, WheelDelta,
+    };
     use crate::input_data::{
         decode_mouse_button_set, encode_mouse_button_set, MouseButton, MouseButtonSet,
     };
+    use euclid::UnknownUnit;
     use keyboard_types::Modifiers;
     use std::collections::HashMap;
 
@@ -740,12 +744,62 @@ pub mod on {
     #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     #[derive(Debug, Clone)]
     pub struct WheelData {
+        #[deprecated(since = "0.3.0", note = "use delta() instead")]
         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,
     }
 
+    impl WheelData {
+        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,
+            }
+        }
+
+        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,
+            }
+        }
+
+        #[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),
+            }
+        }
+    }
+
     pub type MediaEvent = UiEvent<MediaData>;
     #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     #[derive(Debug, Clone)]

+ 61 - 0
packages/html/src/geometry.rs

@@ -25,6 +25,67 @@ pub struct PageSpace;
 /// A point in PageSpace
 pub type PagePoint = Point2D<f64, PageSpace>;
 
+/// A pixel unit: one unit corresponds to 1 pixel
+pub struct Pixels;
+/// A vector expressed in Pixels
+pub type PixelsVector = Vector3D<f64, Pixels>;
+
+/// A unit in terms of Lines
+///
+/// One unit is relative to the size of one line
+pub struct Lines;
+/// A vector expressed in Lines
+pub type LinesVector = Vector3D<f64, Lines>;
+
+/// A unit in terms of Screens:
+///
+/// One unit is relative to the size of a page
+pub struct Pages;
+/// A vector expressed in Pages
+pub type PagesVector = Vector3D<f64, Pages>;
+
+/// A vector representing the amount the mouse wheel was moved
+///
+/// This may be expressed in Pixels, Lines or Pages
+#[derive(Copy, Clone, Debug)]
+pub enum WheelDelta {
+    /// Movement in Pixels
+    Pixels(PixelsVector),
+    /// Movement in Lines
+    Lines(LinesVector),
+    /// Movement in Pages
+    Pages(PagesVector),
+}
+
+impl WheelDelta {
+    /// Convenience function for constructing a WheelDelta with pixel units
+    pub fn pixels(x: f64, y: f64, z: f64) -> Self {
+        WheelDelta::Pixels(PixelsVector::new(x, y, z))
+    }
+
+    /// Convenience function for constructing a WheelDelta with line units
+    pub fn lines(x: f64, y: f64, z: f64) -> Self {
+        WheelDelta::Lines(LinesVector::new(x, y, z))
+    }
+
+    /// Convenience function for constructing a WheelDelta with page units
+    pub fn pages(x: f64, y: f64, z: f64) -> Self {
+        WheelDelta::Pages(PagesVector::new(x, y, z))
+    }
+
+    pub fn is_zero(&self) -> bool {
+        self.strip_units() == Vector3D::new(0., 0., 0.)
+    }
+
+    pub fn strip_units(&self) -> Vector3D<f64, UnknownUnit> {
+        match self {
+            WheelDelta::Pixels(v) => v.cast_unit(),
+            WheelDelta::Lines(v) => v.cast_unit(),
+            WheelDelta::Pages(v) => v.cast_unit(),
+        }
+    }
+}
+
 /// Coordinates of a point in the app's interface
 pub struct Coordinates {
     screen: ScreenPoint,

+ 10 - 10
packages/tui/src/hooks.rs

@@ -5,7 +5,9 @@ use dioxus_core::*;
 use fxhash::{FxHashMap, FxHashSet};
 
 use dioxus_html::geometry::euclid::{Point2D, Rect, Size2D};
-use dioxus_html::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
+use dioxus_html::geometry::{
+    ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint, WheelDelta,
+};
 use dioxus_html::input_data::keyboard_types::Modifiers;
 use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons;
 use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet};
@@ -248,7 +250,10 @@ impl InnerInputState {
             // a mouse button is released if a button was down and is now not down
             let was_released = !(previous_buttons - mouse_data.held_buttons()).is_empty();
 
-            let wheel_delta = self.wheel.as_ref().map_or(0.0, |w| w.delta_y);
+            let was_scrolled = self
+                .wheel
+                .as_ref()
+                .map_or(false, |data| !data.delta().is_zero());
             let wheel_data = &self.wheel;
 
             {
@@ -412,7 +417,7 @@ impl InnerInputState {
             {
                 // wheel
                 if let Some(w) = wheel_data {
-                    if wheel_delta != 0.0 {
+                    if was_scrolled {
                         let mut will_bubble = FxHashSet::default();
                         for node in dom.get_listening_sorted("wheel") {
                             let node_layout =
@@ -638,13 +643,8 @@ fn get_event(evt: TermEvent) -> Option<(&'static str, EventData)> {
             };
 
             let get_wheel_data = |up| {
-                // from https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
-                EventData::Wheel(WheelData {
-                    delta_mode: 0x01,
-                    delta_x: 0.0,
-                    delta_y: if up { -1.0 } else { 1.0 },
-                    delta_z: 0.0,
-                })
+                let y = if up { -1.0 } else { 1.0 };
+                EventData::Wheel(WheelData::new(WheelDelta::lines(0., y, 0.)))
             };
 
             match m.kind {