diff --git a/imgui/src/drag_drop.rs b/imgui/src/drag_drop.rs index 2ffbe4b..d896fec 100644 --- a/imgui/src/drag_drop.rs +++ b/imgui/src/drag_drop.rs @@ -52,6 +52,9 @@ pub struct DragDropSource<'a> { } impl<'a> DragDropSource<'a> { + /// Creates a new [DragDropSource] with no flags and the `Condition::Always` with the given name. + /// ImGui refers to this `name` field as a `type`, but really it's just an identifier to match up + /// Source/Target for DragDrop. pub fn new(name: &'a ImStr) -> Self { Self { name, @@ -62,6 +65,24 @@ impl<'a> DragDropSource<'a> { } } + /// Creates a new [DragDropSource] with no flags and the `Condition::Always` with the given name. + /// ImGui refers to this `name` field as a `type`, but really it's just an identifier to match up + /// Source/Target for DragDrop. + /// + /// This payload will be passed to ImGui, which will provide it to + /// a target when it runs [accept_drag_drop_payload](DragDropTarget::accept_drag_drop_payload). + /// + /// ## Safety + /// This function is not inherently unsafe, and won't panic itself, but using it opts you into + /// managing the lifetime yourself. When you dereference the pointer given in [accept_drag_drop_payload](DragDropTarget::accept_drag_drop_payload), + /// you can easily create memory safety problems. + pub unsafe fn payload(name: &'a ImStr, payload: *const T) -> Self { + let mut output = Self::new(name); + output.payload = payload as *const ffi::c_void; + output.size = std::mem::size_of::(); + output + } + /// Sets the flags on the [DragDropSource]. Only the flags `SOURCE_NO_PREVIEW_TOOLTIP`, /// `SOURCE_NO_DISABLE_HOVER`, `SOURCE_NO_HOLD_TO_OPEN_OTHERS`, `SOURCE_ALLOW_NULL_ID`, /// `SOURCE_EXTERN`, `SOURCE_AUTO_EXPIRE_PAYLOAD` make semantic sense, but any other flags will @@ -77,19 +98,6 @@ impl<'a> DragDropSource<'a> { self } - /// Sets a payload. This payload will be passed to ImGui, which will provide it to - /// a target when it runs [accept_drag_drop_payload](DragDropTarget::accept_drag_drop_payload). - /// - /// ## Safety - /// This function is not inherently unsafe, and won't panic itself, but using it opts you into - /// managing the lifetime yourself. When you dereference the pointer given in [accept_drag_drop_payload](DragDropTarget::accept_drag_drop_payload), - /// you can easily create memory safety problems. - pub unsafe fn payload(mut self, payload: *const T) -> Self { - self.payload = payload as *const ffi::c_void; - self.size = std::mem::size_of::(); - self - } - /// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() pub fn begin<'ui>(self, _ui: &'ui Ui) -> Option> { let should_begin = unsafe { sys::igBeginDragDropSource(self.flags.bits() as i32) }; @@ -133,13 +141,20 @@ pub struct DragDropPayload { /// Data which is copied and owned by ImGui. If you have accepted the payload, you can /// take ownership of the data; otherwise, view it immutably. Interacting with `data` is /// very unsafe. + /// @fixme: this doesn't make a ton of sense. pub data: *const ffi::c_void, /// Set when [`accept_drag_drop_payload`](Self::accept_drag_drop_payload) was called /// and mouse has been hovering the target item (nb: handle overlapping drag targets). - /// @fixme: literally what does this mean + /// @fixme: literally what does this mean -- I believe this is false on the first + /// frame when source hovers over target and then is subsequently true? but I'm not sure + /// when this matters. If DragDropFlags::ACCEPT_NO_PREVIEW is set, it doesn't make a difference + /// to this flag. pub preview: bool, /// Set when AcceptDragDropPayload() was called and mouse button is released over the target item. + /// If this is set to false, then you set DragDropFlags::ACCEPT_BEFORE_DELIVERY and shouldn't + /// mess with `data` + /// @fixme: obviously this isn't an impressive implementation of ffi data mutability. pub delivery: bool, } @@ -158,6 +173,7 @@ impl<'ui> DragDropTarget<'ui> { /// Accepts, popping the drag_drop payload, if it exists. If `DragDropFlags::ACCEPT_BEFORE_DELIVERY` is /// set, this function will return `Some` even if the type is wrong as long as there is a payload to accept. + /// How do we possibly handle communicating that this data is somewhat immutable? pub fn accept_drag_drop_payload(&self, name: &ImStr, flags: DragDropFlags) -> Option { unsafe { let inner = sys::igAcceptDragDropPayload(name.as_ptr(), flags.bits() as i32); @@ -166,6 +182,9 @@ impl<'ui> DragDropTarget<'ui> { } else { let inner = *inner; + // @fixme: there are actually other fields on `inner` which I have shorn -- they're + // considered internal to imgui (such as id of who sent this), so i've left it for + // now this way. Some(DragDropPayload { data: inner.Data, preview: inner.Preview,