提交 e6c6e4f0 编写于 作者: B Benjamin Pasero

dropping multiple folders: open workspace

上级 0c59c951
...@@ -155,7 +155,7 @@ class NewWorkspaceAction extends BaseWorkspacesAction { ...@@ -155,7 +155,7 @@ class NewWorkspaceAction extends BaseWorkspacesAction {
} }
private createWorkspace(folders: URI[]): TPromise<void> { private createWorkspace(folders: URI[]): TPromise<void> {
const workspaceFolders = distinct(folders.map(folder => folder.toString(true /* encoding */))); const workspaceFolders = distinct(folders.map(folder => folder.toString(true /* skip encoding to preserve drive letters readable */)));
return this.windowService.createAndOpenWorkspace(workspaceFolders); return this.windowService.createAndOpenWorkspace(workspaceFolders);
} }
......
...@@ -39,6 +39,7 @@ import { Themable, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_T ...@@ -39,6 +39,7 @@ import { Themable, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_T
import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { IMessageService } from 'vs/platform/message/common/message'; import { IMessageService } from 'vs/platform/message/common/message';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
export enum Rochade { export enum Rochade {
NONE, NONE,
...@@ -152,7 +153,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro ...@@ -152,7 +153,8 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
@IWindowsService private windowsService: IWindowsService, @IWindowsService private windowsService: IWindowsService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IFileService private fileService: IFileService, @IFileService private fileService: IFileService,
@IMessageService private messageService: IMessageService @IMessageService private messageService: IMessageService,
@IWorkspacesService private workspacesService: IWorkspacesService
) { ) {
super(themeService); super(themeService);
...@@ -1118,7 +1120,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro ...@@ -1118,7 +1120,7 @@ export class EditorGroupsControl extends Themable implements IEditorGroupsContro
else { else {
const droppedResources = extractResources(e).filter(r => r.resource.scheme === 'file' || r.resource.scheme === 'untitled'); const droppedResources = extractResources(e).filter(r => r.resource.scheme === 'file' || r.resource.scheme === 'untitled');
if (droppedResources.length) { if (droppedResources.length) {
handleWorkspaceExternalDrop(droppedResources, $this.fileService, $this.messageService, $this.windowsService, $this.windowService).then(handled => { handleWorkspaceExternalDrop(droppedResources, $this.fileService, $this.messageService, $this.windowsService, $this.windowService, $this.workspacesService).then(handled => {
if (handled) { if (handled) {
return; return;
} }
......
...@@ -43,6 +43,7 @@ import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } ...@@ -43,6 +43,7 @@ import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector }
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { activeContrastBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
interface IEditorInputLabel { interface IEditorInputLabel {
name: string; name: string;
...@@ -74,7 +75,8 @@ export class TabsTitleControl extends TitleControl { ...@@ -74,7 +75,8 @@ export class TabsTitleControl extends TitleControl {
@IWindowService private windowService: IWindowService, @IWindowService private windowService: IWindowService,
@IWindowsService private windowsService: IWindowsService, @IWindowsService private windowsService: IWindowsService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IFileService private fileService: IFileService @IFileService private fileService: IFileService,
@IWorkspacesService private workspacesService: IWorkspacesService
) { ) {
super(contextMenuService, instantiationService, editorService, editorGroupService, contextKeyService, keybindingService, telemetryService, messageService, menuService, quickOpenService, themeService); super(contextMenuService, instantiationService, editorService, editorGroupService, contextKeyService, keybindingService, telemetryService, messageService, menuService, quickOpenService, themeService);
...@@ -691,7 +693,7 @@ export class TabsTitleControl extends TitleControl { ...@@ -691,7 +693,7 @@ export class TabsTitleControl extends TitleControl {
if (droppedResources.length) { if (droppedResources.length) {
DOM.EventHelper.stop(e, true); DOM.EventHelper.stop(e, true);
handleWorkspaceExternalDrop(droppedResources, this.fileService, this.messageService, this.windowsService, this.windowService).then(handled => { handleWorkspaceExternalDrop(droppedResources, this.fileService, this.messageService, this.windowsService, this.windowService, this.workspacesService).then(handled => {
if (handled) { if (handled) {
return; return;
} }
......
...@@ -40,10 +40,11 @@ import { ResourceContextKey } from 'vs/workbench/common/resources'; ...@@ -40,10 +40,11 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Themable } from 'vs/workbench/common/theme'; import { Themable } from 'vs/workbench/common/theme';
import { IDraggedResource } from 'vs/base/browser/dnd'; import { IDraggedResource } from 'vs/base/browser/dnd';
import { WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces'; import { WORKSPACE_EXTENSION, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { extname } from 'vs/base/common/paths'; import { extname } from 'vs/base/common/paths';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows'; import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import URI from 'vs/base/common/uri';
export interface IToolbarActions { export interface IToolbarActions {
primary: IAction[]; primary: IAction[];
...@@ -492,7 +493,8 @@ export function handleWorkspaceExternalDrop( ...@@ -492,7 +493,8 @@ export function handleWorkspaceExternalDrop(
fileService: IFileService, fileService: IFileService,
messageService: IMessageService, messageService: IMessageService,
windowsService: IWindowsService, windowsService: IWindowsService,
windowService: IWindowService windowService: IWindowService,
workspacesService: IWorkspacesService
): TPromise<boolean /* handled */> { ): TPromise<boolean /* handled */> {
// Return early if there are no external resources // Return early if there are no external resources
...@@ -501,40 +503,54 @@ export function handleWorkspaceExternalDrop( ...@@ -501,40 +503,54 @@ export function handleWorkspaceExternalDrop(
return TPromise.as(false); return TPromise.as(false);
} }
const externalWorkspaceResources: { workspaces: URI[], folders: URI[] } = {
workspaces: [],
folders: []
};
return TPromise.join(externalResources.map(resource => { return TPromise.join(externalResources.map(resource => {
// Check for Workspace // Check for Workspace
if (extname(resource.fsPath) === `.${WORKSPACE_EXTENSION}`) { if (extname(resource.fsPath) === `.${WORKSPACE_EXTENSION}`) {
return TPromise.as(true); // Workspace externalWorkspaceResources.workspaces.push(resource);
return void 0;
} }
// Check for Folder // Check for Folder
return fileService.resolveFile(resource).then(stat => stat.isDirectory, error => false); return fileService.resolveFile(resource).then(stat => {
})).then(res => { if (stat.isDirectory) {
externalWorkspaceResources.folders.push(stat.resource);
}
}, error => void 0);
})).then(_ => {
const { workspaces, folders } = externalWorkspaceResources;
// Return early if no external resource is a folder or workspace // Return early if no external resource is a folder or workspace
const openAsWorkspace = res.some(res => !!res); if (workspaces.length === 0 && folders.length === 0) {
if (!openAsWorkspace) { return false;
return false; // not handled as workspace
} }
// Pass focus to window // Pass focus to window
windowService.focusWindow(); windowService.focusWindow();
// Ask the user when opening a potential large number of folders let workspacesToOpen: TPromise<string[]>;
let doOpen = true;
if (externalResources.length > 20) { // Open in separate windows if we drop workspaces or just one folder
doOpen = messageService.confirm({ if (workspaces.length > 0 || folders.length === 1) {
message: nls.localize('confirmOpen', "Are you sure you want to open {0} workspaces?", externalResources.length), workspacesToOpen = TPromise.as([...workspaces, ...folders].map(resources => resources.fsPath));
primaryButton: nls.localize({ key: 'confirmOpenButton', comment: ['&& denotes a mnemonic'] }, "&&Open"),
type: 'question'
});
} }
if (doOpen) { // Multiple folders: Create new workspace with folders and open
windowsService.openWindow(externalResources.map(r => r.fsPath), { forceReuseWindow: true }); else if (folders.length > 1) {
workspacesToOpen = workspacesService.createWorkspace([...folders].map(folder => folder.toString(true /* skip encoding to preserve drive letters readable */))).then(workspace => [workspace.configPath]);
} }
// Open
workspacesToOpen.then(workspaces => {
windowsService.openWindow(workspaces, { forceReuseWindow: true });
});
return true; return true;
}); });
} }
\ No newline at end of file
...@@ -895,7 +895,7 @@ export class FileDragAndDrop implements IDragAndDrop { ...@@ -895,7 +895,7 @@ export class FileDragAndDrop implements IDragAndDrop {
const currentRoots = this.contextService.getWorkspace().roots; const currentRoots = this.contextService.getWorkspace().roots;
const newRoots = [...currentRoots, ...folders]; const newRoots = [...currentRoots, ...folders];
return this.windowService.createAndOpenWorkspace(distinct(newRoots.map(root => root.toString(true /* encoding */)))); return this.windowService.createAndOpenWorkspace(distinct(newRoots.map(root => root.toString(true /* skip encoding to preserve drive letters readable */))));
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册