"MultiDragAndDropContainer"?


#1

Hi Jules,

I’m currently writing some code to replace DragAndDropContainer because I need to move several components in one drag operation for each of them.
I’m just starting, but I realize I’m duplicating a lot of code from the original DragAndDropContainer, except everytime, I repeat the operations for every component in my selection.

Therefore, I was wondering if there would be a chance to have another startDragging method in DragAndDropContainer which would take a container of Component* and do what startDragging does (mouse tracking and calling DragAndDropTarget methods) for every component in the container ?

Am I dreaming ?


#2

I’m totally confused. There’s nothing that can’t be done with the current implementation of drag and drop now, with the exception of changing the image during the drag.

Why do you have to duplicate any code from DragAndDropContainer? Are you deriving your content Component from DragAndDropContainer? Or are you making each control a subclass of DragAndDropContainer?


#3

Hi Vinn ! Thanks for your reply.

I think we both agree that you have only one sourceComponent here :

void DragAndDropContainer::startDragging (const var & sourceDescription, Component * sourceComponent, const Image & dragImage = Image::null, bool allowDraggingToOtherJuceWindows = false, const Point< int > * imageOffsetFromMouse = nullptr )

What I’m trying to do is to have multiple source components, and multiple dragAndDropTargets.
Just imagine that in a sequencer, you’re dragging several clips on several tracks for example.

I don’t see how this can be done using only juce drag and drop implementation. Maybe you do ?

Don’t want to bother you with the details but for one clip, what I do is that I call startDragging, and I update my model in the DragAndDropTarget methods, which in turn updates the views. This is working perfectly. On the other hand, if I have several clips, this approach doesn’t work. Unless it’s safe to call startDragging for each component (clip) in sequence ? I’m not sure it works …

There’s always the workaround of not using a drag image and displaying whatever you want in the DragAndDropTarget (itemDragEnter/itemDragMove/itemDragExit) .

Nope I’m deriving my content component from a custom MultiDragAndDropContainer.

Code like : (from DragAndDropContainer)

[code]MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource (0);

    if (draggingSource == nullptr || ! draggingSource->isDragging())
    {
        jassertfalse;   // You must call startDragging() from within a mouseDown or mouseDrag callback!
        return;
    }

    const Point<int> lastMouseDown (Desktop::getLastMouseDownPosition());
    Point<int> imageOffset;[/code]

Is independant of how many components you want to drag at once. Sometimes -well most of the time- I’m not cloning the code but trying to understand it and doing the same thing a bit differently but the global algorithm stays the same.

Do you mean DragAndDropTarget ? In this case, yes.


#4

Sounds like a bad idea to me. I’ve often used the current implementation for dragging multiple objects, e.g. in the treeview class.

The drag source description is a var, so you can attach any kind of data you need, e.g. a list of all the things that you’re dragging, or even a DynamicObject containing any c++ object at all. But I’d have thought that in 99% of cases you’ll be dragging “all the currently selected items”, so you can just make your target look at your list of selected items - that’s what I do in the introjucer.


#5

Hi Jules,

Agreed : for this particular problem, you’ve got plenty of workarounds.

In “simple cases”, this works perfectly. The problem with this approach is, that the target needs to go through the list of selected items, and then, to it’s own list of children, and check the components intersections . All of this is not that simple, and already done in DragAndDropContainer anyway, to generate the dragEnter, dragMove and dragExit callbacks …


#6

TBH it sounds like you probably shouldn’t use the normal drag-and-drop mechanism… I certainly wouldn’t use it for dragging clips in a sequencer, because in that case you’d want to continuously move the components themselves rather than just dropping a representation of them onto a target, right?


#7

Not sure I see what you mean. You can always trigger the model update in mouse itemDragMove, can’t you ?
Or did you mean that itemDragMove isn’t “continuous” because it’s called every x milliseconds ?

Or are you talking about the difference between the representation of a clip and the actual clip in the model ?


#8

The drag-and-drop classes are for picking something up, and dropping it onto a target, assuming that nothing of interest is going to happen in-between. I’d say that if you need to do anything even slightly complicated inside your itemDragMove, then you should probably do it some other way. If you’re picking up some clips so that you can drag-and-drop them onto some separate window or target, then ok, use it. But if you’re sliding them around, then don’t use this, just move them directly.


#9

Interesting, is there a specific reason for not doing complicated stuff in dragMove ?
I’ll take that into account, thanks


#10

Could these two classes help you?

componentBroadcast

componentNotifyParent


#11

Also this one:

DragAndDropData

Here’s what I’m thinking. When the drag starts, you create a DragAndDropData object. Then you broadcast a call to your content component and its children (recursively) using componentBroadcast() with the DragAndDropData as a parameter. Each component which wants to participate adds itself to some list embedded in the DragAndDropData. When the component adds itself to the list it can also register a functor that will be called when the drag completes.

Would this help?


#12

I’ve always been impressed by VFLib. Never considered using it because it’s GPLd but I think you changed that to MIT now, haven’t you ? Your solution looks really good indeed


#13

Thanks. Yes, the develop and release branches hold update sources that are MIT licensed. The docs have already been published and I will release VFLib 1.1 (MIT Licensed) this week.