dear_imgui_rs/drag_drop/target.rs
1use super::flags::{DragDropTargetFlags, validate_drag_drop_target_flags};
2use super::payload::{
3 DragDropPayload, DragDropPayloadEmpty, DragDropPayloadPod, PayloadIsWrongType,
4 decode_typed_payload,
5};
6use super::validation::validate_payload_type_name;
7use crate::{Ui, sys};
8
9/// Drag drop target for accepting payloads
10///
11/// This struct is created by [`Ui::drag_drop_target`] and provides
12/// methods for accepting different types of payloads.
13#[derive(Debug)]
14pub struct DragDropTarget<'ui>(pub(super) &'ui Ui);
15
16impl<'ui> DragDropTarget<'ui> {
17 /// Accept an empty payload
18 ///
19 /// This is the safest option for drag and drop operations.
20 /// Use this when you only need to know that a drop occurred,
21 /// not transfer actual data.
22 ///
23 /// # Arguments
24 /// * `name` - Payload type name (must match source name)
25 /// * `flags` - Accept flags
26 ///
27 /// Returns payload info if accepted, `None` otherwise.
28 pub fn accept_payload_empty(
29 &self,
30 name: impl AsRef<str>,
31 flags: DragDropTargetFlags,
32 ) -> Option<DragDropPayloadEmpty> {
33 self.accept_payload(name, flags)?
34 .ok()
35 .map(|payload_pod: DragDropPayloadPod<()>| DragDropPayloadEmpty {
36 preview: payload_pod.preview,
37 delivery: payload_pod.delivery,
38 })
39 }
40
41 /// Accept a typed payload
42 ///
43 /// Attempts to accept a payload with the specified type.
44 /// Returns `Ok(payload)` if the type matches, `Err(PayloadIsWrongType)` if not.
45 ///
46 /// # Arguments
47 /// * `name` - Payload type name (must match source name)
48 /// * `flags` - Accept flags
49 ///
50 /// Returns `Some(Result<payload, error>)` if payload exists, `None` otherwise.
51 pub fn accept_payload<T: 'static + Copy, Name: AsRef<str>>(
52 &self,
53 name: Name,
54 flags: DragDropTargetFlags,
55 ) -> Option<Result<DragDropPayloadPod<T>, PayloadIsWrongType>> {
56 let output = unsafe { self.accept_payload_unchecked(name, flags) };
57
58 output.map(decode_typed_payload)
59 }
60
61 /// Accept raw payload data (unsafe)
62 ///
63 /// # Safety
64 /// The returned pointer and size are managed by ImGui and may become
65 /// invalid at any time. The caller must not access the data after
66 /// the drag operation completes.
67 ///
68 /// # Arguments
69 /// * `name` - Payload type name
70 /// * `flags` - Accept flags
71 pub unsafe fn accept_payload_unchecked(
72 &self,
73 name: impl AsRef<str>,
74 flags: DragDropTargetFlags,
75 ) -> Option<DragDropPayload> {
76 validate_payload_type_name(name.as_ref(), "DragDropTarget::accept_payload_unchecked()");
77 validate_drag_drop_target_flags("DragDropTarget::accept_payload_unchecked()", flags);
78 let name = self.0.scratch_txt(name);
79 let inner = self.0.run_with_bound_context(|| unsafe {
80 sys::igAcceptDragDropPayload(name, flags.bits() as i32)
81 });
82
83 if inner.is_null() {
84 None
85 } else {
86 Some(DragDropPayload::from_raw(unsafe { *inner }))
87 }
88 }
89
90 /// End the drag drop target
91 ///
92 /// This is called automatically when the token is dropped.
93 pub fn pop(self) {
94 // Drop will handle cleanup
95 }
96}
97
98impl Drop for DragDropTarget<'_> {
99 fn drop(&mut self) {
100 self.0.run_with_bound_context(|| unsafe {
101 sys::igEndDragDropTarget();
102 });
103 }
104}