MichaelJones
MichaelJones

Reputation: 1406

Is it possible to drag & drop between custom VS Code tree views?

The 1.66 (March 2022) release introduces a TreeDragAndDropController API which allows for handling drag & drop events for custom tree views.

However in the docs for the DataTransfer object is says:

Drag and drop controllers that implement {@link TreeDragAndDropController.handleDrag handleDrag} can add additional mime types to the data transfer. These additional mime types will only be included in the handleDrop when the the drag was initiated from an element in the same drag and drop controller.

Does this mean that you cannot drag & drop between custom tree views as they would typically have a custom drag & drop controller per view? Or that you're meant to re-use a drag & drop controller between tree views in order to enable dragging & dropping between views?

I have tried various combinations and been unsuccessful in getting a full drag & drop between two tree views. I do see an error in the console on drop in some situations but that is about it.

Upvotes: 1

Views: 1045

Answers (1)

Andy
Andy

Reputation: 41

It took me a while to figure out how to get drag & drop to work between two different treeviews. For me, the problem was a combination of:

  • Misunderstanding the purpose / usage of dragMimeTypes.
  • Misunderstanding the purpose / usage of treeDataTransfer.set().
  • Using an incorrect naming convention for mime types.

This is probably best described by way of example. Let's assume we're only going to drag from TreeView_A and we'll only drop onto TreeView_B.

For TreeView_A

  • dropMimeTypes can be an empty array as we're not expecting to receive any drops.
  • We don't really need a handleDrop() method, again we're not expecting to receive any drops.
  • dragMimeTypes needs to include the mime type of the treeview that we're going to drop onto (i.e. TreeView_B). A word of warning here, this MUST be in the format application/vnd.code.tree.<treeidlowercase>. So, for this example it would read something like this:
dragMimeTypes = ['application/vnd.code.tree.treeView_b'];
  • handleDrag() method needs to set using a mime type of the target treeview (Treeview_B), (remember lowercase!)
    public async handleDrag(source: TreeItem[], treeDataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<void> {
        treeDataTransfer.set('application/vnd.code.tree.treeView_b', new vscode.DataTransferItem(source));
    }

The lowercase requirement seems more like a suggestion if you read the comments in the underlying code... but no from my experience it seems more like a requirement. Had me stumped for ages!

For TreeView_B

  • dragMimeTypes can be an empty array as we won't be dragging anything from here.
  • similarly, we don't really need a handleDrag() method.
  • dropMimeTypes needs to include the mime type of the treeview that we're going to drop onto (i.e. this treeview, TreeView_B)
dropMimeTypes = ['application/vnd.code.tree.treeView_b'];
  • the handleDrop() method needs to get the correct mime type (you guessed it, Treeview_B in lowercase). In this method, I just log to console.
    public async handleDrop(target: TreeItem | undefined, sources: vscode.DataTransfer): Promise<void> {
        const transferItemAppContent = sources.get('application/vnd.code.tree.treeView_b');
        if (transferItemAppContent) {
            console.log(JSON.stringify(transferItemAppContent));
            return;
        }
    }

I'm still not sure that I've 100% understood how this is supposed to be implemented, but I can tell you that the above method works. Hope it helps.

Upvotes: 3

Related Questions