1use std::{any::Any, sync::Arc};
2
3use crate::{Context, CursorIcon, Id};
4
5#[doc(alias = "drag and drop")]
18#[derive(Clone, Default)]
19pub struct DragAndDrop {
20 payload: Option<Arc<dyn Any + Send + Sync>>,
22}
23
24impl DragAndDrop {
25 pub(crate) fn register(ctx: &Context) {
26 ctx.on_end_frame("debug_text", std::sync::Arc::new(Self::end_frame));
27 }
28
29 fn end_frame(ctx: &Context) {
30 let abort_dnd =
31 ctx.input(|i| i.pointer.any_released() || i.key_pressed(crate::Key::Escape));
32
33 let mut is_dragging = false;
34
35 ctx.data_mut(|data| {
36 let state = data.get_temp_mut_or_default::<Self>(Id::NULL);
37
38 if abort_dnd {
39 state.payload = None;
40 }
41
42 is_dragging = state.payload.is_some();
43 });
44
45 if is_dragging {
46 ctx.set_cursor_icon(CursorIcon::Grabbing);
47 }
48 }
49
50 pub fn set_payload<Payload>(ctx: &Context, payload: Payload)
54 where
55 Payload: Any + Send + Sync,
56 {
57 ctx.data_mut(|data| {
58 let state = data.get_temp_mut_or_default::<Self>(Id::NULL);
59 state.payload = Some(Arc::new(payload));
60 });
61 }
62
63 pub fn clear_payload(ctx: &Context) {
65 ctx.data_mut(|data| {
66 let state = data.get_temp_mut_or_default::<Self>(Id::NULL);
67 state.payload = None;
68 });
69 }
70
71 pub fn payload<Payload>(ctx: &Context) -> Option<Arc<Payload>>
78 where
79 Payload: Any + Send + Sync,
80 {
81 ctx.data(|data| {
82 let state = data.get_temp::<Self>(Id::NULL)?;
83 let payload = state.payload?;
84 payload.downcast().ok()
85 })
86 }
87
88 pub fn take_payload<Payload>(ctx: &Context) -> Option<Arc<Payload>>
95 where
96 Payload: Any + Send + Sync,
97 {
98 ctx.data_mut(|data| {
99 let state = data.get_temp_mut_or_default::<Self>(Id::NULL);
100 let payload = state.payload.take()?;
101 payload.downcast().ok()
102 })
103 }
104
105 pub fn has_payload_of_type<Payload>(ctx: &Context) -> bool
110 where
111 Payload: Any + Send + Sync,
112 {
113 Self::payload::<Payload>(ctx).is_some()
114 }
115
116 pub fn has_any_payload(ctx: &Context) -> bool {
121 ctx.data(|data| {
122 let state = data.get_temp::<Self>(Id::NULL);
123 state.map_or(false, |state| state.payload.is_some())
124 })
125 }
126}