Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag'n Drop: How to tell in the DragDropSource, if payload has been delivered? #8225

Open
Bizzarrus opened this issue Dec 12, 2024 · 2 comments
Labels
drag drop drag and drop

Comments

@Bizzarrus
Copy link

Version/Branch of Dear ImGui:

Version 1.91.5, Branch: docking

Back-ends:

custom

Compiler, OS:

Windows 11 / MSVC 2022

Full config/build information:

No response

Details:

My Question:

During a BeginDragDropSource/EndDragDropSource, how can I tell, if the payload has been delivered? This is, an AcceptDragDropPayload has successfully returned in a different place?

The use case for this would be, if a drag'n'drop is intended to move some data from one storage to another. Let's say, for example, I have two separate and independent lists of items, and I want to be able to move items from one to the other through drag and drop. Ideally, it would be the responsibility of the DragDropSource to remove the item from the previous storage, while the DragDropTarget is adding it to the new storage - but, obviously, the DragDropSource should only remove the item from the storage, if it actually has actually been delivered to another storage, and not when the drag'n'drop has been canceled.

I know that, as a work around, the DragDropTarget can do both the remove and the add operation. However, if there are multiple possible DragDropSources and DragDropTargets (which might be implemented in different classes/using a different internal data structure) for the same type of data, this can quickly become quite messy. So I'm looking for a cleaner and more general solution to this.

Thank you in advance :)

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

static std::vector<int> data = { 0, 1, 2 };

ImGui::Button("Test");
if(!data.empty() && ImGui::BeginDragDropSource())
{
    int value = data.back();
    ImGui::SetDragDropPayload("MY_ITEM", &value, sizeof(value));
    
    //if(ImGui::WasDragDropDelivered())  // <-- Something like this ???
    //    data.pop_back();

    ImGui::EndDragDropSource();
}

@GamingMinds-DanielC
Copy link
Contributor

Drag&drop can get very complex, the operations you may want to perform can depend on the type of drag source, the type of drop target or a combination of both. Therefore how to best handle drag&drop very much depends on the application.

Handling it at the target is usually the best way. If you split removal at the source and insertion at the target, you might end up with an invalid state (element inserted at the target but not yet removed at the source) between frames. Probably not a problem with integers, but with more complex objects it might be.

If I understand you correctly, you have different source containers and potentially different types of source containers. If it is just different containers of the same type, you could set a pointer to the vector as the payload and handle removal at the drop target. With different types of containers, you could specify an interface class, derive several classes that handle container type specific retrieval and removal of data from containers and set a pointer to a persistent interface as a payload. At the target you can then just call a virtual method and don't have to worry about the source container type.

@ocornut ocornut added the drag drop drag and drop label Dec 12, 2024
@ocornut ocornut changed the title [Drag'n'Drop] How to tell in the DragDropSource, if payload has been delivered? Drag'n Drop: How to tell in the DragDropSource, if payload has been delivered? Dec 12, 2024
@ocornut
Copy link
Owner

ocornut commented Dec 12, 2024

Consider that the source item is not guaranteed to exist or visible while the payload is dropped (because e.g. you might may changing a visible tab while dragging the payload), so it would be dangerous to rely on both side performing their actions.

I agree that the best solution may be to include all the required data inside your payload. And then every drop target can execute a same function to process that payload and perform the move.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
drag drop drag and drop
Projects
None yet
Development

No branches or pull requests

3 participants