Few questions about DragAndDropContainer

here’s what I currently got in the component that inherits from DragAndDropContainer (latest juce develop):

void mouseDown(const Mouse& mouse) override
{
	if (isDragAndDropActive())
		return;
	const auto file = saveWav();
	if (!file.existsAsFile())
		return;
	const bool canMoveFiles = true;
	files.clear();
	files.add(file.getFullPathName());
	performExternalDragDropOfFiles
	(
		files,
		canMoveFiles,
		this,
		[]() {}
	);
	const Var sourceDescription(420);
	Point imageOffsetFromMouse(0, 0);
	startDragging(sourceDescription, this, scaledImage, true, &imageOffsetFromMouse, &mouse.source);
}

the idea was like this:
if we’re not currently dragging already and saving the (single) wav file was successful, we let the drag n drop thing pass it to some other place. and that works! yay

but sometimes when I close the application the leak detector is triggered in some StringArray and it looks like there are still a few (2,3,4 etc) elements in it. I added those conditionals in the beginning of the method trying to fight this bug, because I thought if I make sure there is no new drag before the last file was fully created and managed it might not mess with that StringArray (files) but that doesn’t work. So now I’d like to know what I’m missing here, what should be done instead to make this work.


Now here’s my 2nd problem. It’s less important tbh so if you have limited time pls only think about the first one: But for some reason whenever I start a new drag the dragImage does not follow the cursor but it quickly moves to the center of the component that inherits from DragAndDropContainer while dissolving into transparency. I have no idea how to troubleshoot this because DragAndDropContainer has no setters for the position of the dragImage. I expected it to just follow the mouse cursor. What do I have to do to make it work? It happens both with juce::Image and juce::ScaledImage

I think it’s probably incorrect to call performExternalDragDropOfFiles and startDragging inside the same mouse callback. Depending on the desired effect, maybe you could try overriding shouldDropFilesWhenDraggedExternally, and removing the call to performExternalDragDropOfFiles from your mouseDown.

this seems to have solved both issues at once. thx

actually i found another problem. now i can’t drag the wav file to another component within my plugin anymore. i guess that has something to do with the method specifically saying “externally” but there is no method for internal drops either, so it’s a little confusing. what do i need to change to make it also work for components internally that ask for wav files? here’s what i currently got:

void mouseDown(const Mouse& mouse) override
{
	const Var sourceDescription(420);
	Point imageOffsetFromMouse(0, 0);
	startDragging(sourceDescription, this, scaledImage, true, &imageOffsetFromMouse, &mouse.source);
}

bool shouldDropFilesWhenDraggedExternally(const DnDSrc&,
	StringArray& files, bool& canMoveFiles) override
{
	const auto file = saveWav();
	if (!file.existsAsFile())
		return false;
	files.clearQuick();
	files.add(file.getFullPathName());
	canMoveFiles = false;
	return true;
}

(this might actually be a JUCE bug, because the tooltip in startDragging() says that the bool allowDraggingToOtherJuceWindows is meant to enable that behaviour. but it did work when i still used performExternalDragDropOfFiles(), so the solution must be in the JUCE code somewhere already)

i would like to give this thread a little bump. hope it’s ok. before i made the proposed changes it was possible to drag n drop from the juce component to a different internal component that accepts dropping wav files. but since we solved the issues i initially had it only lets me drag n drop outside of the plugin. and that’s definitely the main thing I wanted to have, but it would be cool if both works so I wanna ask what would have to be changed for that. the docs aren’t clear about that imo

There’s effectively a couple of different ‘kinds’ of drag-and-drop that you need to consider: ‘internal’ DnD, where you’re dragging between JUCE components and JUCE is keeping track of the dragged item; and ‘external’ or ‘native’ DnD, where JUCE asks the OS to take over and handle the drag. For internal DnD, JUCE will display a drag image that normally matches the dragged component, and for external DnD, the OS will generally display a thumbnail icon corresponding to the dragged filetype. External DnD is required to drag to any other process, or non-JUCE windows in the same process.

I believe that shouldDropFilesWhenDraggedExternally will switch the DnD mechanism from internal to external when the mouse cursor leaves the JUCE window. My guess is that you’re not handling internal drags currently - make sure you’re implementing DragAndDropTarget and FileDragAndDropTarget on components that need to accept internal and external drags.

Alternatively, you could switch back to using performExternalDragDropOfFiles only, to immediately start an external DnD, although I expect this approach will disable the JUCE drag image.

1 Like

yeah, letting the other component inherit from DragAndDropTarget and implementing some of its virtual functions solved the problem fully for me. that was the missing piece of the puzzle. this thread is solved! thx