Skip to content

Commit

Permalink
Enable file dnd in tree views
Browse files Browse the repository at this point in the history
Part of #32592
  • Loading branch information
alexr00 committed Nov 17, 2021
1 parent da099cc commit 6191365
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/vs/workbench/api/browser/mainThreadTreeViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTreeViews);
}

async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, dragAndDropMimeTypes: string[] }): Promise<void> {
async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, dragAndDropMimeTypes: string[] | undefined }): Promise<void> {
this.logService.trace('MainThreadTreeViews#$registerTreeViewDataProvider', treeViewId, options);

this.extensionService.whenInstalledExtensionsRegistered().then(() => {
const dataProvider = new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService);
this._dataProviders.set(treeViewId, dataProvider);
const dndController = (options.dragAndDropMimeTypes.length > 0)
const dndController = options.dragAndDropMimeTypes
? new TreeViewDragAndDropController(treeViewId, options.dragAndDropMimeTypes, this._proxy) : undefined;
const viewer = this.getTreeView(treeViewId);
if (viewer) {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
}

export interface MainThreadTreeViewsShape extends IDisposable {
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, dragAndDropMimeTypes: string[] }): Promise<void>;
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, dragAndDropMimeTypes: string[] | undefined}): Promise<void>;
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem; }): Promise<void>;
$reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise<void>;
$setMessage(treeViewId: string, message: string): void;
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostTreeViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
if (!options || !options.treeDataProvider) {
throw new Error('Options with treeDataProvider is mandatory');
}
const dragAndDropMimeTypes = (options.dragAndDropController === undefined) ? [] : options.dragAndDropController.supportedMimeTypes;
const dragAndDropMimeTypes = options.dragAndDropController?.supportedMimeTypes;
const registerPromise = this._proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany, dragAndDropMimeTypes });
const treeView = this.createExtHostTreeView(viewId, options, extension);
return {
Expand Down
31 changes: 28 additions & 3 deletions src/vs/workbench/browser/parts/views/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
import { Command } from 'vs/editor/common/modes';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { CodeDataTransfers, fillEditorsDragData } from 'vs/workbench/browser/dnd';
import { Schemas } from 'vs/base/common/network';

export class TreeViewPane extends ViewPane {

Expand Down Expand Up @@ -1224,7 +1226,8 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
private readonly treeMimeType: string;
constructor(
private readonly treeId: string,
@ILabelService private readonly labelService: ILabelService) {
@ILabelService private readonly labelService: ILabelService,
@IInstantiationService private readonly instantiationService: IInstantiationService) {
this.treeMimeType = `tree/${treeId.toLowerCase()}`;
}

Expand All @@ -1233,21 +1236,43 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
this.dndController = controller;
}

private addResourceInfoToTransfer(originalEvent: DragEvent, resources: URI[]) {
if (resources.length && originalEvent.dataTransfer) {
// Apply some datatransfer types to allow for dragging the element outside of the application
this.instantiationService.invokeFunction(accessor => fillEditorsDragData(accessor, resources, originalEvent));

// The only custom data transfer we set from the explorer is a file transfer
// to be able to DND between multiple code file explorers across windows
const fileResources = resources.filter(s => s.scheme === Schemas.file).map(r => r.fsPath);
if (fileResources.length) {
originalEvent.dataTransfer.setData(CodeDataTransfers.FILES, JSON.stringify(fileResources));
}
}
}

onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void {
if (originalEvent.dataTransfer) {
const treeItemsData = (data as ElementsDragAndDropData<ITreeItem, ITreeItem[]>).getData();
const resources: URI[] = [];
const sourceInfo: TreeDragSourceInfo = {
id: this.treeId,
itemHandles: treeItemsData.map(item => item.handle)
itemHandles: []
};
treeItemsData.forEach(item => {
sourceInfo.itemHandles.push(item.handle);
if (item.resourceUri) {
resources.push(URI.revive(item.resourceUri));
}
});
this.addResourceInfoToTransfer(originalEvent, resources);
originalEvent.dataTransfer.setData(this.treeMimeType,
JSON.stringify(sourceInfo));
}
}

onDragOver(data: IDragAndDropData, targetElement: ITreeItem, targetIndex: number, originalEvent: DragEvent): boolean | ITreeDragOverReaction {
const dndController = this.dndController;
if (!dndController || !originalEvent.dataTransfer) {
if (!dndController || !originalEvent.dataTransfer || (dndController.supportedMimeTypes.length === 0)) {
return false;
}
const dragContainersSupportedType = originalEvent.dataTransfer.types.some((value, index) => {
Expand Down
2 changes: 1 addition & 1 deletion src/vscode-dts/vscode.proposed.treeViewDragAndDrop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ declare module 'vscode' {
*
* @param source The source items for the drag and drop operation.
*/
onWillDrop(source: T[]): Thenable<TreeDataTransfer>;
onWillDrop?(source: T[]): Thenable<TreeDataTransfer>;

/**
* Called when a drag and drop action results in a drop on the tree that this `DragAndDropController` belongs too.
Expand Down

0 comments on commit 6191365

Please sign in to comment.