Skip to main content

dioxus_html/events/
drag.rs

1use crate::input_data::{MouseButton, MouseButtonSet};
2use crate::*;
3use crate::{
4    data_transfer::DataTransfer,
5    geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint},
6};
7use std::option::Option;
8
9use dioxus_core::Event;
10use keyboard_types::Modifiers;
11
12use crate::HasMouseData;
13
14pub type DragEvent = Event<DragData>;
15
16/// The DragEvent interface is a DOM event that represents a drag and drop interaction. The user initiates a drag by
17/// placing a pointer device (such as a mouse) on the touch surface and then dragging the pointer to a new location
18/// (such as another DOM element). Applications are free to interpret a drag and drop interaction in an
19/// application-specific way.
20pub struct DragData {
21    inner: Box<dyn HasDragData>,
22}
23
24impl<E: HasDragData + 'static> From<E> for DragData {
25    fn from(e: E) -> Self {
26        Self { inner: Box::new(e) }
27    }
28}
29
30impl std::fmt::Debug for DragData {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        f.debug_struct("DragData")
33            .field("coordinates", &self.coordinates())
34            .field("modifiers", &self.modifiers())
35            .field("held_buttons", &self.held_buttons())
36            .field("trigger_button", &self.trigger_button())
37            .finish()
38    }
39}
40
41impl PartialEq for DragData {
42    fn eq(&self, other: &Self) -> bool {
43        self.coordinates() == other.coordinates()
44            && self.modifiers() == other.modifiers()
45            && self.held_buttons() == other.held_buttons()
46            && self.trigger_button() == other.trigger_button()
47    }
48}
49
50impl DragData {
51    /// Create a new DragData
52    pub fn new(inner: impl HasDragData + 'static) -> Self {
53        Self {
54            inner: Box::new(inner),
55        }
56    }
57
58    /// The DataTransfer object is used to hold the data that is being dragged during a drag and drop operation.
59    pub fn data_transfer(&self) -> DataTransfer {
60        self.inner.data_transfer()
61    }
62
63    /// Downcast this event data to a specific type
64    #[inline(always)]
65    pub fn downcast<T: 'static>(&self) -> Option<&T> {
66        HasDragData::as_any(&*self.inner).downcast_ref::<T>()
67    }
68}
69
70impl crate::HasFileData for DragData {
71    fn files(&self) -> Vec<FileData> {
72        self.inner.files()
73    }
74}
75
76impl InteractionLocation for DragData {
77    fn client_coordinates(&self) -> ClientPoint {
78        self.inner.client_coordinates()
79    }
80
81    fn page_coordinates(&self) -> PagePoint {
82        self.inner.page_coordinates()
83    }
84
85    fn screen_coordinates(&self) -> ScreenPoint {
86        self.inner.screen_coordinates()
87    }
88}
89
90impl InteractionElementOffset for DragData {
91    fn element_coordinates(&self) -> ElementPoint {
92        self.inner.element_coordinates()
93    }
94
95    fn coordinates(&self) -> Coordinates {
96        self.inner.coordinates()
97    }
98}
99
100impl ModifiersInteraction for DragData {
101    fn modifiers(&self) -> Modifiers {
102        self.inner.modifiers()
103    }
104}
105
106impl PointerInteraction for DragData {
107    fn held_buttons(&self) -> MouseButtonSet {
108        self.inner.held_buttons()
109    }
110
111    // 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
112    fn trigger_button(&self) -> Option<MouseButton> {
113        self.inner.trigger_button()
114    }
115}
116
117#[cfg(feature = "serialize")]
118pub use ser::*;
119
120#[cfg(feature = "serialize")]
121mod ser {
122    use super::*;
123
124    /// A serialized version of DragData
125    #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
126    pub struct SerializedDragData {
127        pub mouse: crate::point_interaction::SerializedPointInteraction,
128
129        pub data_transfer: crate::data_transfer::SerializedDataTransfer,
130    }
131
132    impl SerializedDragData {
133        fn new(drag: &DragData) -> Self {
134            Self {
135                mouse: crate::point_interaction::SerializedPointInteraction::from(drag),
136                data_transfer: crate::data_transfer::SerializedDataTransfer::from(drag),
137            }
138        }
139    }
140
141    impl HasDataTransferData for SerializedDragData {
142        fn data_transfer(&self) -> crate::data_transfer::DataTransfer {
143            crate::data_transfer::DataTransfer::new(self.data_transfer.clone())
144        }
145    }
146
147    impl HasDragData for SerializedDragData {
148        fn as_any(&self) -> &dyn std::any::Any {
149            self
150        }
151    }
152
153    impl crate::file_data::HasFileData for SerializedDragData {
154        fn files(&self) -> Vec<FileData> {
155            self.data_transfer().files()
156        }
157    }
158
159    impl HasMouseData for SerializedDragData {
160        fn as_any(&self) -> &dyn std::any::Any {
161            self
162        }
163    }
164
165    impl InteractionLocation for SerializedDragData {
166        fn client_coordinates(&self) -> ClientPoint {
167            self.mouse.client_coordinates()
168        }
169
170        fn page_coordinates(&self) -> PagePoint {
171            self.mouse.page_coordinates()
172        }
173
174        fn screen_coordinates(&self) -> ScreenPoint {
175            self.mouse.screen_coordinates()
176        }
177    }
178
179    impl InteractionElementOffset for SerializedDragData {
180        fn element_coordinates(&self) -> ElementPoint {
181            self.mouse.element_coordinates()
182        }
183
184        fn coordinates(&self) -> Coordinates {
185            self.mouse.coordinates()
186        }
187    }
188
189    impl ModifiersInteraction for SerializedDragData {
190        fn modifiers(&self) -> Modifiers {
191            self.mouse.modifiers()
192        }
193    }
194
195    impl PointerInteraction for SerializedDragData {
196        fn held_buttons(&self) -> MouseButtonSet {
197            self.mouse.held_buttons()
198        }
199
200        fn trigger_button(&self) -> Option<MouseButton> {
201            self.mouse.trigger_button()
202        }
203    }
204
205    impl serde::Serialize for DragData {
206        fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
207            SerializedDragData::new(self).serialize(serializer)
208        }
209    }
210
211    impl<'de> serde::Deserialize<'de> for DragData {
212        fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
213            let data = SerializedDragData::deserialize(deserializer)?;
214            Ok(Self {
215                inner: Box::new(data),
216            })
217        }
218    }
219}
220
221/// A trait for any object that has the data for a drag event
222pub trait HasDragData: HasMouseData + crate::HasFileData + crate::HasDataTransferData {
223    /// return self as Any
224    fn as_any(&self) -> &dyn std::any::Any;
225}