From e13179239ecea7422c25e158af858a02f87d5fb4 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 14 Jun 2016 07:18:23 +0200 Subject: [PATCH] allow DND to tabs (from explorer or desktop) --- .../browser/parts/editor/tabsTitleControl.ts | 64 +++++++++++++++++-- src/vs/workbench/electron-browser/window.ts | 10 +-- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index f8793e48ea6..b5dcd93e654 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -12,10 +12,12 @@ import {IAction} from 'vs/base/common/actions'; import {prepareActions} from 'vs/workbench/browser/actionBarRegistry'; import arrays = require('vs/base/common/arrays'); import errors = require('vs/base/common/errors'); +import URI from 'vs/base/common/uri'; import DOM = require('vs/base/browser/dom'); import {isMacintosh} from 'vs/base/common/platform'; import {Builder, $} from 'vs/base/browser/builder'; import {MIME_BINARY} from 'vs/base/common/mime'; +import {Position} from 'vs/platform/editor/common/editor'; import {IEditorGroup, IEditorIdentifier, asFileEditorInput, EditorOptions} from 'vs/workbench/common/editor'; import {ToolBar} from 'vs/base/browser/ui/toolbar/toolbar'; import {StandardKeyboardEvent} from 'vs/base/browser/keyboardEvent'; @@ -122,12 +124,14 @@ export class TabsTitleControl extends TitleControl { if (target instanceof HTMLElement && target.className.indexOf('tabs-container') === 0) { const group = this.context; if (group) { + const targetPosition = this.stacks.positionOfGroup(group); + const targetIndex = group.count; + + // Local DND if (TabsTitleControl.draggedEditor) { e.preventDefault(); const sourcePosition = this.stacks.positionOfGroup(TabsTitleControl.draggedEditor.group); - const targetPosition = this.stacks.positionOfGroup(group); - const targetIndex = group.count; // Move editor to target position and index if (this.isMoveOperation(e, TabsTitleControl.draggedEditor.group, group)) { @@ -139,6 +143,11 @@ export class TabsTitleControl extends TitleControl { this.editorService.openEditor(TabsTitleControl.draggedEditor.editor, EditorOptions.create({ pinned: true, index: targetIndex }), targetPosition).done(null, errors.onUnexpectedError); } } + + // External DND + else { + this.handleExternalDrop(e, targetPosition, targetIndex); + } } } })); @@ -451,12 +460,14 @@ export class TabsTitleControl extends TitleControl { // Drop this.tabDisposeables.push(DOM.addDisposableListener(tab, DOM.EventType.DROP, (e: DragEvent) => { + const targetPosition = this.stacks.positionOfGroup(group); + const targetIndex = group.indexOf(editor); + + // Local DND if (TabsTitleControl.draggedEditor) { e.preventDefault(); const sourcePosition = this.stacks.positionOfGroup(TabsTitleControl.draggedEditor.group); - const targetPosition = this.stacks.positionOfGroup(group); - const targetIndex = group.indexOf(editor); // Move editor to target position and index if (this.isMoveOperation(e, TabsTitleControl.draggedEditor.group, group)) { @@ -468,9 +479,54 @@ export class TabsTitleControl extends TitleControl { this.editorService.openEditor(TabsTitleControl.draggedEditor.editor, EditorOptions.create({ pinned: true, index: targetIndex }), targetPosition).done(null, errors.onUnexpectedError); } } + + // External DND + else { + this.handleExternalDrop(e, targetPosition, targetIndex); + } })); } + private handleExternalDrop(e: DragEvent, targetPosition: Position, targetIndex: number): void { + let resources: URI[] = []; + + if (e.dataTransfer.types.length > 0) { + + // Check for in-app DND + const rawData = e.dataTransfer.getData(e.dataTransfer.types[0]); + if (rawData) { + const resource = URI.parse(rawData); + if (resource.scheme === 'file' || resource.scheme === 'untitled') { + resources.push(resource); + } + } + + // Check for external app DND + else if (e.dataTransfer && e.dataTransfer.files) { + let thepaths: string[] = []; + for (let i = 0; i < e.dataTransfer.files.length; i++) { + if (e.dataTransfer.files[i] && (e.dataTransfer.files[i]).path) { + thepaths.push(e.dataTransfer.files[i].path); + } + } + + resources = thepaths.map(p => URI.file(p)); + } + } + + // Open resources if found + if (resources.length) { + e.preventDefault(); + + this.editorService.openEditors(resources.map(resource => { + return { + input: { resource, options: { pinned: true, index: targetIndex } }, + position: targetPosition + }; + })).done(() => this.editorGroupService.focusGroup(targetPosition), errors.onUnexpectedError); + } + } + private isMoveOperation(e: DragEvent, source: IEditorGroup, target: IEditorGroup) { const isCopy = (e.ctrlKey && !isMacintosh) || (e.altKey && isMacintosh); diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 0fb36219f3d..0323281bd9a 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -65,7 +65,7 @@ export class ElectronWindow { }); } - // Prevent a dropped file from opening as nw application + // Prevent a dropped file from opening as application window.document.body.addEventListener('dragover', (e: DragEvent) => { e.preventDefault(); }); @@ -82,8 +82,8 @@ export class ElectronWindow { if (e.dataTransfer && e.dataTransfer.files) { let thepaths: string[] = []; for (let i = 0; i < e.dataTransfer.files.length; i++) { - if (e.dataTransfer.files[i] && (e.dataTransfer.files[i]).path) { - thepaths.push((e.dataTransfer.files[i]).path); + if (e.dataTransfer.files[i] && e.dataTransfer.files[i].path) { + thepaths.push(e.dataTransfer.files[i].path); } } @@ -95,8 +95,8 @@ export class ElectronWindow { } // Otherwise check for special webkit transfer - if (!pathsOpened && e.dataTransfer && (e).dataTransfer.items) { - let items: { getAsString: (clb: (str: string) => void) => void; }[] = (e).dataTransfer.items; + if (!pathsOpened && e.dataTransfer && e.dataTransfer.items) { + let items = e.dataTransfer.items; if (items.length && typeof items[0].getAsString === 'function') { items[0].getAsString((str) => { try { -- GitLab