Skip to main content

dioxus_gestures/state/gestures/
drag.rs

1use std::{cell::RefCell, rc::Rc};
2use dioxus::html::point_interaction::InteractionLocation;
3use dioxus::{html::PointerData};
4
5use crate::state::gestures::pointer::{IncrementalOffsetPointer, InitialPointer, OffsetPointer};
6
7/// ```rust
8/// use dioxus::{
9///     html::geometry::{euclid::Point2D, ClientSpace},
10///     prelude::*,
11/// };
12/// use dioxus_gestures::{
13///     state::gestures::drag::Drag,
14///     use_gestures::{use_gestures, Gestures},
15/// };
16///
17/// const UNDRAGGED_TEXT: &str = "Drag me!";
18/// const DRAGGED_TEXT: &str = "Dragging ...";
19///
20/// #[component]
21/// pub fn DragExample() -> Element {
22///     let mut position = use_signal(|| Point2D::<_, ClientSpace>::new(0.0, 0.0));
23///     let mut text = use_signal(|| UNDRAGGED_TEXT);
24///
25///     let gestures = use_gestures(
26///         Gestures::default()
27///             .drag(
28///                 Drag::default()
29///                     .on_start(move |_| text.set(DRAGGED_TEXT))
30///                     .on_update(move |data| {
31///                         let movement = data.pointer.delta_movement();
32///                         position.set(position() + movement);
33///                     })
34///                     .on_end(move |_| text.set(UNDRAGGED_TEXT))
35///                     .on_cancel(move |_| text.set(UNDRAGGED_TEXT)),
36///             )
37///     );
38///
39///     rsx! {
40///         div {
41///         class: "target drag",
42///         style: format!("
43///             user-select: none;
44///             touch-action: none;
45///             position: relative;
46///             left: {}px;
47///             top: {}px;
48///         ", position().x, position().y),
49///         ..gestures.event_handlers(),
50///             "{text}"
51///         }
52///     }
53/// }
54/// ```
55#[derive(Clone)]
56pub struct Drag {
57    pub on_start: Option<Rc<RefCell<dyn FnMut(DragStartData)>>>,
58    pub on_update: Option<Rc<RefCell<dyn FnMut(DragUpdateData)>>>,
59    pub on_end: Option<Rc<RefCell<dyn FnMut(DragEndData)>>>,
60    pub on_cancel: Option<Rc<RefCell<dyn FnMut(DragCancelData)>>>,
61    pub has_started: Rc<dyn Fn([&PointerData; 2]) -> bool>,
62}
63
64impl Drag {
65    pub fn on_start(mut self, handler: impl FnMut(DragStartData) + 'static) -> Self {
66        self.on_start = Some(Rc::new(RefCell::new(handler)));
67        self
68    }
69
70    pub fn on_update(mut self, handler: impl FnMut(DragUpdateData) + 'static) -> Self {
71        self.on_update = Some(Rc::new(RefCell::new(handler)));
72        self
73    }
74
75    pub fn on_end(mut self, handler: impl FnMut(DragEndData) + 'static) -> Self {
76        self.on_end = Some(Rc::new(RefCell::new(handler)));
77        self
78    }
79
80    pub fn on_cancel(mut self, handler: impl FnMut(DragCancelData) + 'static) -> Self {
81        self.on_cancel = Some(Rc::new(RefCell::new(handler)));
82        self
83    }
84
85    pub fn has_started(mut self, predicate: impl Fn([&PointerData; 2]) -> bool + 'static) -> Self {
86        self.has_started = Rc::new(predicate);
87        self
88    }
89}
90
91pub struct DragStartData {
92    pub pointer: InitialPointer,
93}
94pub struct DragUpdateData {
95    pub pointer: IncrementalOffsetPointer,
96}
97pub struct DragEndData {
98    pub pointer: OffsetPointer,
99}
100pub struct DragCancelData {
101    pub pointer: OffsetPointer,
102}
103
104impl Default for Drag {
105    fn default() -> Self {
106        Self {
107            on_start: Default::default(),
108            on_update: Default::default(),
109            on_end: Default::default(),
110            on_cancel: Default::default(),
111            has_started: Rc::new(|[initial, current]| {
112                (current.client_coordinates() - initial.client_coordinates()).length() >= 5.0
113            }),
114        }
115    }
116}