dioxus_web/events/
drag.rs

1use crate::{WebDataTransfer, WebFileData, WebFileEngine};
2
3use super::{Synthetic, WebEventExt};
4use dioxus_html::{
5    geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint},
6    input_data::{decode_mouse_button_set, MouseButton},
7    FileData, HasDataTransferData, HasDragData, HasFileData, HasMouseData,
8    InteractionElementOffset, InteractionLocation, Modifiers, ModifiersInteraction,
9    PointerInteraction,
10};
11use web_sys::{DragEvent, FileReader};
12
13impl InteractionLocation for Synthetic<DragEvent> {
14    fn client_coordinates(&self) -> ClientPoint {
15        ClientPoint::new(self.event.client_x().into(), self.event.client_y().into())
16    }
17
18    fn page_coordinates(&self) -> PagePoint {
19        PagePoint::new(self.event.page_x().into(), self.event.page_y().into())
20    }
21
22    fn screen_coordinates(&self) -> ScreenPoint {
23        ScreenPoint::new(self.event.screen_x().into(), self.event.screen_y().into())
24    }
25}
26
27impl InteractionElementOffset for Synthetic<DragEvent> {
28    fn element_coordinates(&self) -> ElementPoint {
29        ElementPoint::new(self.event.offset_x().into(), self.event.offset_y().into())
30    }
31}
32
33impl ModifiersInteraction for Synthetic<DragEvent> {
34    fn modifiers(&self) -> Modifiers {
35        let mut modifiers = Modifiers::empty();
36
37        if self.event.alt_key() {
38            modifiers.insert(Modifiers::ALT);
39        }
40        if self.event.ctrl_key() {
41            modifiers.insert(Modifiers::CONTROL);
42        }
43        if self.event.meta_key() {
44            modifiers.insert(Modifiers::META);
45        }
46        if self.event.shift_key() {
47            modifiers.insert(Modifiers::SHIFT);
48        }
49
50        modifiers
51    }
52}
53
54impl PointerInteraction for Synthetic<DragEvent> {
55    fn held_buttons(&self) -> dioxus_html::input_data::MouseButtonSet {
56        decode_mouse_button_set(self.event.buttons())
57    }
58
59    fn trigger_button(&self) -> Option<MouseButton> {
60        Some(MouseButton::from_web_code(self.event.button()))
61    }
62}
63
64impl HasMouseData for Synthetic<DragEvent> {
65    fn as_any(&self) -> &dyn std::any::Any {
66        &self.event
67    }
68}
69
70impl HasDragData for Synthetic<DragEvent> {
71    fn as_any(&self) -> &dyn std::any::Any {
72        &self.event
73    }
74}
75
76impl HasDataTransferData for Synthetic<DragEvent> {
77    fn data_transfer(&self) -> dioxus_html::DataTransfer {
78        use wasm_bindgen::JsCast;
79
80        if let Some(target) = self.event.dyn_ref::<web_sys::DragEvent>() {
81            if let Some(data) = target.data_transfer() {
82                let web_data_transfer = WebDataTransfer::new(data);
83                return dioxus_html::DataTransfer::new(web_data_transfer);
84            }
85        }
86
87        // Return an empty DataTransfer if we couldn't get one from the event
88        let web_data_transfer = WebDataTransfer::new(web_sys::DataTransfer::new().unwrap());
89        dioxus_html::DataTransfer::new(web_data_transfer)
90    }
91}
92
93impl HasFileData for Synthetic<DragEvent> {
94    fn files(&self) -> Vec<FileData> {
95        use wasm_bindgen::JsCast;
96
97        if let Some(target) = self.event.dyn_ref::<web_sys::DragEvent>() {
98            if let Some(data_transfer) = target.data_transfer() {
99                if let Some(file_list) = data_transfer.files() {
100                    return WebFileEngine::new(file_list).to_files();
101                } else {
102                    let items = data_transfer.items();
103                    let mut files = vec![];
104                    for i in 0..items.length() {
105                        if let Some(item) = items.get(i) {
106                            if item.kind() == "file" {
107                                if let Ok(Some(file)) = item.get_as_file() {
108                                    let web_data =
109                                        WebFileData::new(file, FileReader::new().unwrap());
110                                    files.push(FileData::new(web_data));
111                                }
112                            }
113                        }
114                    }
115                    return files;
116                }
117            }
118        } else {
119            tracing::warn!("DragEvent target was not a DragEvent");
120        }
121
122        vec![]
123    }
124}
125
126impl WebEventExt for dioxus_html::DragData {
127    type WebEvent = web_sys::DragEvent;
128
129    #[inline(always)]
130    fn try_as_web_event(&self) -> Option<web_sys::DragEvent> {
131        self.downcast::<DragEvent>().cloned()
132    }
133}