提交 5f1e86ea 编写于 作者: M Martin Aeschlimann

add FileDialogService

上级 9ba00291
......@@ -10,6 +10,8 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { URI } from 'vs/base/common/uri';
import { basename } from 'vs/base/common/paths';
import { localize } from 'vs/nls';
import { FileFilter } from 'vs/platform/windows/common/windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export interface IConfirmation {
title?: string;
......@@ -39,6 +41,74 @@ export interface IConfirmationResult {
checkboxChecked?: boolean;
}
export interface IPickAndOpenOptions {
forceNewWindow?: boolean;
defaultUri?: URI;
telemetryExtraData?: ITelemetryData;
}
export interface ISaveDialogOptions {
/**
* A human-readable string for the dialog title
*/
title?: string;
/**
* The resource the dialog shows when opened.
*/
defaultUri?: URI;
/**
* A set of file filters that are used by the dialog. Each entry is a human readable label,
* like "TypeScript", and an array of extensions.
*/
filters?: FileFilter[];
/**
* A human-readable string for the ok button
*/
buttonLabel?: string;
}
export interface IOpenDialogOptions {
/**
* A human-readable string for the dialog title
*/
title?: string;
/**
* The resource the dialog shows when opened.
*/
defaultUri?: URI;
/**
* A human-readable string for the open button.
*/
openLabel?: string;
/**
* Allow to select files, defaults to `true`.
*/
canSelectFiles?: boolean;
/**
* Allow to select folders, defaults to `false`.
*/
canSelectFolders?: boolean;
/**
* Allow to select many files or folders.
*/
canSelectMany?: boolean;
/**
* A set of file filters that are used by the dialog. Each entry is a human readable label,
* like "TypeScript", and an array of extensions.
*/
filters?: FileFilter[];
}
export const IDialogService = createDecorator<IDialogService>('dialogService');
export interface IDialogOptions {
......@@ -71,6 +141,66 @@ export interface IDialogService {
show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): TPromise<number>;
}
export const IFileDialogService = createDecorator<IFileDialogService>('fileDialogService');
/**
* A service to bring up file dialogs.
*/
export interface IFileDialogService {
_serviceBrand: any;
/**
* The default path for a new file based on previously used files.
* @param schemeFilter The scheme of the file path.
*/
defaultFilePath(schemeFilter: string): URI;
/**
* The default path for a new folder based on previously used folders.
* @param schemeFilter The scheme of the folder path.
*/
defaultFolderPath(schemeFilter: string): URI;
/**
* The default path for a new workspace based on previously used workspaces.
* @param schemeFilter The scheme of the workspace path.
*/
defaultWorkspacePath(schemeFilter: string): URI;
/**
* Shows a file-folder selection dialog and opens the selected entry.
*/
pickFileFolderAndOpen(options: IPickAndOpenOptions): TPromise<any>;
/**
* Shows a file selection dialog and opens the selected entry.
*/
pickFileAndOpen(options: IPickAndOpenOptions): TPromise<any>;
/**
* Shows a folder selection dialog and opens the selected entry.
*/
pickFolderAndOpen(options: IPickAndOpenOptions): TPromise<any>;
/**
* Shows a workspace selection dialog and opens the selected entry.
*/
pickWorkspaceAndOpen(options: IPickAndOpenOptions): TPromise<any>;
/**
* Shows a save file dialog and returns the chosen file URI.
*/
showSaveDialog(options: ISaveDialogOptions): TPromise<URI>;
/**
* Shows a open file dialog and returns the chosen file URI.
*/
showOpenDialog(options: IOpenDialogOptions): TPromise<URI[] | undefined>;
}
const MAX_CONFIRM_FILES = 10;
export function getConfirmMessage(start: string, resourcesToConfirm: URI[]): string {
const message = [start];
......
......@@ -10,7 +10,6 @@ import { isMacintosh, isLinux, isWindows } from 'vs/base/common/platform';
export const InputFocusedContextKey = 'inputFocus';
export const InputFocusedContext = new RawContextKey<boolean>(InputFocusedContextKey, false);
export const FileDialogContext = new RawContextKey<string>('fileDialog', 'local');
export const IsMacContext = new RawContextKey<boolean>('isMac', isMacintosh);
export const IsLinuxContext = new RawContextKey<boolean>('isLinux', isLinux);
export const IsWindowsContext = new RawContextKey<boolean>('isWindows', isWindows);
......@@ -13,14 +13,13 @@ import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { WORKSPACE_FILTER, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID, defaultWorkspacePath, defaultFilePath, defaultFolderPath } from 'vs/workbench/browser/actions/workspaceCommands';
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
export class OpenFileAction extends Action {
......@@ -30,16 +29,13 @@ export class OpenFileAction extends Action {
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@IHistoryService private historyService: IHistoryService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
@IFileDialogService private dialogService: IFileDialogService
) {
super(id, label);
}
run(event?: any, data?: ITelemetryData): TPromise<any> {
const defaultPathURI = defaultFilePath(this.contextService, this.historyService, Schemas.file);
return this.windowService.pickFileAndOpen({ telemetryExtraData: data, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
return this.dialogService.pickFileAndOpen({ forceNewWindow: false, telemetryExtraData: data });
}
}
......@@ -51,16 +47,13 @@ export class OpenFolderAction extends Action {
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@IHistoryService private historyService: IHistoryService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
@IFileDialogService private dialogService: IFileDialogService
) {
super(id, label);
}
run(event?: any, data?: ITelemetryData): TPromise<any> {
const defaultPathURI = defaultFolderPath(this.contextService, this.historyService, Schemas.file);
return this.windowService.pickFolderAndOpen({ telemetryExtraData: data, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
return this.dialogService.pickFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data });
}
}
......@@ -72,16 +65,13 @@ export class OpenFileFolderAction extends Action {
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@IHistoryService private historyService: IHistoryService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
@IFileDialogService private dialogService: IFileDialogService
) {
super(id, label);
}
run(event?: any, data?: ITelemetryData): TPromise<any> {
const defaultPathURI = defaultFilePath(this.contextService, this.historyService, Schemas.file);
return this.windowService.pickFileFolderAndOpen({ telemetryExtraData: data, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
return this.dialogService.pickFileFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data });
}
}
......@@ -144,18 +134,18 @@ export class SaveWorkspaceAsAction extends Action {
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@IHistoryService private historyService: IHistoryService
@IFileDialogService private dialogService: IFileDialogService
) {
super(id, label);
}
run(): TPromise<any> {
return this.getNewWorkspaceConfigPath().then(configPath => {
if (configPath) {
return this.getNewWorkspaceConfigPath().then(configPathUri => {
if (configPathUri) {
const configPath = configPathUri.fsPath;
switch (this.contextService.getWorkbenchState()) {
case WorkbenchState.EMPTY:
case WorkbenchState.FOLDER:
......@@ -171,13 +161,12 @@ export class SaveWorkspaceAsAction extends Action {
});
}
private getNewWorkspaceConfigPath(): TPromise<string> {
const defaultPathURI = defaultWorkspacePath(this.contextService, this.historyService, this.environmentService, Schemas.file);
return this.windowService.showSaveDialog({
private getNewWorkspaceConfigPath(): TPromise<URI> {
return this.dialogService.showSaveDialog({
buttonLabel: mnemonicButtonLabel(nls.localize({ key: 'save', comment: ['&& denotes a mnemonic'] }, "&&Save")),
title: nls.localize('saveWorkspace', "Save Workspace"),
filters: WORKSPACE_FILTER,
defaultPath: defaultPathURI && defaultPathURI.fsPath
defaultUri: this.dialogService.defaultWorkspacePath(Schemas.file)
});
}
}
......@@ -190,17 +179,13 @@ export class OpenWorkspaceAction extends Action {
constructor(
id: string,
label: string,
@IWindowService private windowService: IWindowService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IHistoryService private historyService: IHistoryService,
@IEnvironmentService private environmentService: IEnvironmentService
@IFileDialogService private dialogService: IFileDialogService
) {
super(id, label);
}
run(event?: any, data?: ITelemetryData): TPromise<any> {
const defaultPathURI = defaultWorkspacePath(this.contextService, this.historyService, this.environmentService, Schemas.file);
return this.windowService.pickWorkspaceAndOpen({ telemetryExtraData: data, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
return this.dialogService.pickWorkspaceAndOpen({ telemetryExtraData: data });
}
}
......
......@@ -5,142 +5,54 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import * as nls from 'vs/nls';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { URI } from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { CancellationToken } from 'vs/base/common/cancellation';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { FileKind, isParent } from 'vs/platform/files/common/files';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { FileKind } from 'vs/platform/files/common/files';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { isLinux } from 'vs/base/common/platform';
import { ILabelService } from 'vs/platform/label/common/label';
import { IQuickInputService, IPickOptions, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { getIconClasses } from 'vs/workbench/browser/labels';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { Schemas } from 'vs/base/common/network';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
export const ADD_ROOT_FOLDER_COMMAND_ID = 'addRootFolder';
export const ADD_ROOT_FOLDER_LABEL = nls.localize('addFolderToWorkspace', "Add Folder to Workspace...");
export const PICK_WORKSPACE_FOLDER_COMMAND_ID = '_workbench.pickWorkspaceFolder';
function pickFolders(buttonLabel: string, title: string, windowService: IWindowService, contextService: IWorkspaceContextService, historyService: IHistoryService): TPromise<string[]> {
const defaultPathURI = defaultFolderPath(contextService, historyService, Schemas.file);
return windowService.showOpenDialog({
buttonLabel,
title,
properties: ['multiSelections', 'openDirectory', 'createDirectory'],
defaultPath: defaultPathURI && defaultPathURI.fsPath
});
}
export function defaultFolderPath(contextService: IWorkspaceContextService, historyService: IHistoryService, schemeFilter: string): URI {
let candidate: URI;
// Check for last active file root first...
candidate = historyService.getLastActiveWorkspaceRoot(schemeFilter);
// ...then for last active file
if (!candidate) {
candidate = historyService.getLastActiveFile(schemeFilter);
}
return candidate ? resources.dirname(candidate) : void 0;
}
function services(accessor: ServicesAccessor): { windowService: IWindowService, historyService: IHistoryService, contextService: IWorkspaceContextService, environmentService: IEnvironmentService } {
return {
windowService: accessor.get(IWindowService),
historyService: accessor.get(IHistoryService),
contextService: accessor.get(IWorkspaceContextService),
environmentService: accessor.get(IEnvironmentService)
};
}
export function defaultFilePath(contextService: IWorkspaceContextService, historyService: IHistoryService, schemeFilter: string): URI {
let candidate: URI;
// Check for last active file first...
candidate = historyService.getLastActiveFile(schemeFilter);
// ...then for last active file root
if (!candidate) {
candidate = historyService.getLastActiveWorkspaceRoot(schemeFilter);
}
return candidate ? resources.dirname(candidate) : void 0;
}
export function defaultWorkspacePath(contextService: IWorkspaceContextService, historyService: IHistoryService, environmentService: IEnvironmentService, schemeFilter: string): URI {
// Check for current workspace config file first...
if (schemeFilter === Schemas.file && contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && !isUntitledWorkspace(contextService.getWorkspace().configuration.fsPath, environmentService)) {
return resources.dirname(contextService.getWorkspace().configuration);
}
// ...then fallback to default folder path
return defaultFolderPath(contextService, historyService, schemeFilter);
}
function isUntitledWorkspace(path: string, environmentService: IEnvironmentService): boolean {
return isParent(path, environmentService.workspacesHome, !isLinux /* ignore case */);
}
// Command registration
CommandsRegistry.registerCommand({
id: 'workbench.action.files.openFileFolderInNewWindow',
handler: (accessor: ServicesAccessor) => {
const { windowService, historyService, contextService } = services(accessor);
const defaultPathURI = defaultFilePath(contextService, historyService, Schemas.file);
windowService.pickFileFolderAndOpen({ forceNewWindow: true, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
}
handler: (accessor: ServicesAccessor) => accessor.get(IFileDialogService).pickFileFolderAndOpen({ forceNewWindow: true })
});
CommandsRegistry.registerCommand({
id: '_files.pickFolderAndOpen',
handler: (accessor: ServicesAccessor, forceNewWindow: boolean) => {
const { windowService, historyService, contextService } = services(accessor);
const defaultPathURI = defaultFolderPath(contextService, historyService, Schemas.file);
windowService.pickFolderAndOpen({ forceNewWindow, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
}
handler: (accessor: ServicesAccessor, forceNewWindow: boolean) => accessor.get(IFileDialogService).pickFolderAndOpen({ forceNewWindow })
});
CommandsRegistry.registerCommand({
id: 'workbench.action.files.openFolderInNewWindow',
handler: (accessor: ServicesAccessor) => {
const { windowService, historyService, contextService } = services(accessor);
const defaultPathURI = defaultFolderPath(contextService, historyService, Schemas.file);
windowService.pickFolderAndOpen({ forceNewWindow: true, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
}
handler: (accessor: ServicesAccessor) => accessor.get(IFileDialogService).pickFolderAndOpen({ forceNewWindow: true })
});
CommandsRegistry.registerCommand({
id: 'workbench.action.files.openFileInNewWindow',
handler: (accessor: ServicesAccessor) => {
const { windowService, historyService, contextService } = services(accessor);
const defaultPathURI = defaultFilePath(contextService, historyService, Schemas.file);
windowService.pickFileAndOpen({ forceNewWindow: true, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
}
handler: (accessor: ServicesAccessor) => accessor.get(IFileDialogService).pickFileAndOpen({ forceNewWindow: true })
});
CommandsRegistry.registerCommand({
id: 'workbench.action.openWorkspaceInNewWindow',
handler: (accessor: ServicesAccessor) => {
const { windowService, historyService, contextService, environmentService } = services(accessor);
const defaultPathURI = defaultWorkspacePath(contextService, historyService, environmentService, Schemas.file);
windowService.pickWorkspaceAndOpen({ forceNewWindow: true, dialogOptions: { defaultPath: defaultPathURI && defaultPathURI.fsPath } });
}
handler: (accessor: ServicesAccessor) => accessor.get(IFileDialogService).pickWorkspaceAndOpen({ forceNewWindow: true })
});
CommandsRegistry.registerCommand({
......@@ -148,17 +60,23 @@ CommandsRegistry.registerCommand({
handler: (accessor) => {
const viewletService = accessor.get(IViewletService);
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
return pickFolders(mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")), nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace"),
accessor.get(IWindowService), accessor.get(IWorkspaceContextService), accessor.get(IHistoryService)).then(folders => {
if (!folders || !folders.length) {
return null;
}
// Add and show Files Explorer viewlet
return workspaceEditingService.addFolders(folders.map(folder => ({ uri: URI.file(folder) })))
.then(() => viewletService.openViewlet(viewletService.getDefaultViewletId(), true))
.then(() => void 0);
});
const dialogsService = accessor.get(IFileDialogService);
return dialogsService.showOpenDialog({
openLabel: mnemonicButtonLabel(nls.localize({ key: 'add', comment: ['&& denotes a mnemonic'] }, "&&Add")),
title: nls.localize('addFolderToWorkspaceTitle', "Add Folder to Workspace"),
canSelectFolders: true,
canSelectMany: true,
defaultUri: dialogsService.defaultFolderPath(Schemas.file)
}).then(folders => {
if (!folders || !folders.length) {
return null;
}
// Add and show Files Explorer viewlet
return workspaceEditingService.addFolders(folders.map(folder => ({ uri: folder })))
.then(() => viewletService.openViewlet(viewletService.getDefaultViewletId(), true))
.then(() => void 0);
});
}
});
......
......@@ -23,7 +23,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ADD_ROOT_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { FileDialogContext, IsMacContext } from 'vs/platform/workbench/common/contextkeys';
import { IsMacContext } from 'vs/platform/workbench/common/contextkeys';
// Contribute Commands
registerCommands();
......@@ -39,12 +39,11 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Switch
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(QuickSwitchWindow, QuickSwitchWindow.ID, QuickSwitchWindow.LABEL), 'Quick Switch Window...');
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
const isLocal = FileDialogContext.isEqualTo('local');
if (isMacintosh) {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileFolderAction, OpenFileFolderAction.ID, OpenFileFolderAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, isLocal), 'File: Open...', fileCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileFolderAction, OpenFileFolderAction.ID, OpenFileFolderAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }), 'File: Open...', fileCategory);
} else {
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileAction, OpenFileAction.ID, OpenFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, isLocal), 'File: Open File...', fileCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }, isLocal), 'File: Open Folder...', fileCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileAction, OpenFileAction.ID, OpenFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }), 'File: Open File...', fileCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }), 'File: Open Folder...', fileCategory);
}
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
......@@ -108,10 +107,10 @@ workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(Increa
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(DecreaseViewSizeAction, DecreaseViewSizeAction.ID, DecreaseViewSizeAction.LABEL, null), 'View: Decrease Current View Size', viewCategory);
const workspacesCategory = nls.localize('workspaces', "Workspaces");
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory, isLocal);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
CommandsRegistry.registerCommand(OpenWorkspaceConfigFileAction.ID, serviceAccessor => {
......@@ -171,7 +170,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
title: nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")
},
order: 1,
when: ContextKeyExpr.and(IsMacContext.toNegated(), isLocal)
when: IsMacContext.toNegated()
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......@@ -181,7 +180,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
title: nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")
},
order: 2,
when: ContextKeyExpr.and(IsMacContext.toNegated(), isLocal)
when: IsMacContext.toNegated()
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......@@ -191,7 +190,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
title: nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")
},
order: 1,
when: ContextKeyExpr.and(IsMacContext, isLocal)
when: IsMacContext
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......@@ -200,8 +199,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: OpenWorkspaceAction.ID,
title: nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "Open Wor&&kspace...")
},
order: 3,
when: isLocal
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......@@ -228,8 +226,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: nls.localize({ key: 'miAddFolderToWorkspace', comment: ['&& denotes a mnemonic'] }, "A&&dd Folder to Workspace...")
},
order: 1,
when: isLocal
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......@@ -238,8 +235,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: SaveWorkspaceAsAction.ID,
title: nls.localize('miSaveWorkspaceAs', "Save Workspace As...")
},
order: 2,
when: isLocal
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......
......@@ -93,7 +93,7 @@ import { IDecorationsService } from 'vs/workbench/services/decorations/browser/d
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
import { URI } from 'vs/base/common/uri';
import { IListService, ListService } from 'vs/platform/list/browser/listService';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, FileDialogContext } from 'vs/platform/workbench/common/contextkeys';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext } from 'vs/platform/workbench/common/contextkeys';
import { IViewsService } from 'vs/workbench/common/views';
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
import { INotificationService } from 'vs/platform/notification/common/notification';
......@@ -115,6 +115,8 @@ import { ContextViewService } from 'vs/platform/contextview/browser/contextViewS
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { LabelService, ILabelService } from 'vs/platform/label/common/label';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
interface WorkbenchParams {
configuration: IWindowConfiguration;
......@@ -415,6 +417,9 @@ export class Workbench extends Disposable implements IPartService {
// History
serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService));
// File Dialogs
serviceCollection.set(IFileDialogService, new SyncDescriptor(FileDialogService));
// Backup File Service
if (this.workbenchParams.configuration.backupPath) {
this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.workbenchParams.configuration.backupPath);
......@@ -613,7 +618,6 @@ export class Workbench extends Disposable implements IPartService {
IsMacContext.bindTo(this.contextKeyService);
IsLinuxContext.bindTo(this.contextKeyService);
IsWindowsContext.bindTo(this.contextKeyService);
FileDialogContext.bindTo(this.contextKeyService);
const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);
......
......@@ -25,7 +25,6 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { FileDialogContext } from 'vs/platform/workbench/common/contextkeys';
// Contribute Global Actions
const category = nls.localize('filesCategory', "File");
......@@ -184,7 +183,7 @@ appendToCommandPalette(SAVE_FILES_COMMAND_ID, { value: nls.localize('saveFiles',
appendToCommandPalette(REVERT_FILE_COMMAND_ID, { value: nls.localize('revert', "Revert File"), original: 'File: Revert File' }, category);
appendToCommandPalette(COMPARE_WITH_SAVED_COMMAND_ID, { value: nls.localize('compareActiveWithSaved', "Compare Active File with Saved"), original: 'File: Compare Active File with Saved' }, category);
appendToCommandPalette(REVEAL_IN_OS_COMMAND_ID, { value: REVEAL_IN_OS_LABEL, original: isWindows ? 'File: Reveal in Explorer' : isMacintosh ? 'File: Reveal in Finder' : 'File: Open Containing Folder' }, category);
appendToCommandPalette(SAVE_FILE_AS_COMMAND_ID, { value: SAVE_FILE_AS_LABEL, original: 'File: Save As...' }, category, FileDialogContext.isEqualTo('local'));
appendToCommandPalette(SAVE_FILE_AS_COMMAND_ID, { value: SAVE_FILE_AS_LABEL, original: 'File: Save As...' }, category);
appendToCommandPalette(CLOSE_EDITOR_COMMAND_ID, { value: nls.localize('closeEditor', "Close Editor"), original: 'View: Close Editor' }, nls.localize('view', "View"));
appendToCommandPalette(NEW_FILE_COMMAND_ID, { value: NEW_FILE_LABEL, original: 'File: New File' }, category);
appendToCommandPalette(NEW_FOLDER_COMMAND_ID, { value: NEW_FOLDER_LABEL, original: 'File: New Folder' }, category);
......@@ -450,7 +449,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: ADD_ROOT_FOLDER_LABEL
},
when: ContextKeyExpr.and(ExplorerRootContext, FileDialogContext.isEqualTo('local'))
when: ContextKeyExpr.and(ExplorerRootContext)
});
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
......@@ -541,8 +540,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: SAVE_FILE_AS_COMMAND_ID,
title: nls.localize({ key: 'miSaveAs', comment: ['&& denotes a mnemonic'] }, "Save &&As...")
},
order: 2,
when: FileDialogContext.isEqualTo('local')
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......
......@@ -10,10 +10,17 @@ import product from 'vs/platform/node/product';
import { TPromise } from 'vs/base/common/winjs.base';
import Severity from 'vs/base/common/severity';
import { isLinux, isWindows } from 'vs/base/common/platform';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IWindowService, INativeOpenDialogOptions } from 'vs/platform/windows/common/windows';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions, IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import * as resources from 'vs/base/common/resources';
import { isParent } from 'vs/platform/files/common/files';
interface IMassagedMessageBoxOptions {
......@@ -146,4 +153,147 @@ export class DialogService implements IDialogService {
return { options, buttonIndexMap };
}
}
export class FileDialogService implements IFileDialogService {
_serviceBrand: any;
constructor(
@IWindowService private windowService: IWindowService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IHistoryService private historyService: IHistoryService,
@IEnvironmentService private environmentService: IEnvironmentService
) { }
public defaultFilePath(schemeFilter: string): URI {
let candidate: URI;
// Check for last active file first...
candidate = this.historyService.getLastActiveFile(schemeFilter);
// ...then for last active file root
if (!candidate) {
candidate = this.historyService.getLastActiveWorkspaceRoot(schemeFilter);
}
return candidate ? resources.dirname(candidate) : void 0;
}
public defaultFolderPath(schemeFilter: string): URI {
let candidate: URI;
// Check for last active file root first...
candidate = this.historyService.getLastActiveWorkspaceRoot(schemeFilter);
// ...then for last active file
if (!candidate) {
candidate = this.historyService.getLastActiveFile(schemeFilter);
}
return candidate ? resources.dirname(candidate) : void 0;
}
public defaultWorkspacePath(schemeFilter: string): URI {
// Check for current workspace config file first...
if (schemeFilter === Schemas.file && this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && !isUntitledWorkspace(this.contextService.getWorkspace().configuration.fsPath, this.environmentService)) {
return resources.dirname(this.contextService.getWorkspace().configuration);
}
// ...then fallback to default folder path
return this.defaultFolderPath(schemeFilter);
}
private toNativeOpenDialogOptions(options: IPickAndOpenOptions): INativeOpenDialogOptions {
return {
forceNewWindow: options.forceNewWindow,
telemetryExtraData: options.telemetryExtraData,
dialogOptions: {
defaultPath: options.defaultUri && options.defaultUri.fsPath
}
};
}
public pickFileFolderAndOpen(options: IPickAndOpenOptions): TPromise<any> {
let defaultUri = options.defaultUri;
if (!defaultUri) {
options.defaultUri = this.defaultFilePath(Schemas.file);
}
return this.windowService.pickFileFolderAndOpen(this.toNativeOpenDialogOptions(options));
}
public pickFileAndOpen(options: IPickAndOpenOptions): TPromise<any> {
let defaultUri = options.defaultUri;
if (!defaultUri) {
options.defaultUri = this.defaultFilePath(Schemas.file);
}
return this.windowService.pickFileAndOpen(this.toNativeOpenDialogOptions(options));
}
public pickFolderAndOpen(options: IPickAndOpenOptions): TPromise<any> {
let defaultUri = options.defaultUri;
if (!defaultUri) {
options.defaultUri = this.defaultFolderPath(Schemas.file);
}
return this.windowService.pickFolderAndOpen(this.toNativeOpenDialogOptions(options));
}
public pickWorkspaceAndOpen(options: IPickAndOpenOptions): TPromise<void> {
let defaultUri = options.defaultUri;
if (!defaultUri) {
options.defaultUri = this.defaultWorkspacePath(Schemas.file);
}
return this.windowService.pickWorkspaceAndOpen(this.toNativeOpenDialogOptions(options));
}
private toNativeSaveDialogOptions(options: ISaveDialogOptions): Electron.SaveDialogOptions {
return {
defaultPath: options.defaultUri && options.defaultUri.fsPath,
buttonLabel: options.buttonLabel,
filters: options.filters,
title: options.title
};
}
public showSaveDialog(options: ISaveDialogOptions): TPromise<URI> {
return this.windowService.showSaveDialog(this.toNativeSaveDialogOptions(options)).then(result => {
if (result) {
return URI.file(result);
}
return void 0;
});
}
public showOpenDialog(options: IOpenDialogOptions): TPromise<URI[] | undefined> {
const defaultUri = options.defaultUri;
const filters = [];
if (options.filters) {
for (let name in options.filters) {
filters.push({ name, extensions: options.filters[name] });
}
}
const properties = [];
if (options.canSelectFiles) {
properties.push('openFile');
}
if (options.canSelectFolders) {
properties.push('openDirectory');
}
if (options.canSelectMany) {
properties.push('multiSelections');
}
return this.windowService.showOpenDialog({
title: options.title,
defaultPath: defaultUri && defaultUri.fsPath,
buttonLabel: options.openLabel,
filters,
properties
}).then(result => result ? result.map(URI.file) : void 0);
}
}
function isUntitledWorkspace(path: string, environmentService: IEnvironmentService): boolean {
return isParent(path, environmentService.workspacesHome, !isLinux /* ignore case */);
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ import * as errors from 'vs/base/common/errors';
import * as objects from 'vs/base/common/objects';
import { Event, Emitter } from 'vs/base/common/event';
import * as platform from 'vs/base/common/platform';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions, AutoSaveContext, IWillMoveEvent } from 'vs/workbench/services/textfile/common/textfiles';
import { ConfirmResult, IRevertOptions } from 'vs/workbench/common/editor';
......@@ -33,7 +33,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
import { IModelService } from 'vs/editor/common/services/modelService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { isEqualOrParent, isEqual } from 'vs/base/common/resources';
import { isEqualOrParent, isEqual, joinPath } from 'vs/base/common/resources';
export interface IBackupResult {
didBackup: boolean;
......@@ -76,6 +76,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
protected environmentService: IEnvironmentService,
private backupFileService: IBackupFileService,
private windowsService: IWindowsService,
protected windowService: IWindowService,
private historyService: IHistoryService,
contextKeyService: IContextKeyService,
private modelService: IModelService
......@@ -99,7 +100,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
abstract resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise<IRawTextContent>;
abstract promptForPath(resource: URI, defaultPath: string): TPromise<string>;
abstract promptForPath(resource: URI, defaultPath: URI): TPromise<URI>;
abstract confirmSave(resources?: URI[]): TPromise<ConfirmResult>;
......@@ -451,7 +452,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
});
}
targetUri = URI.file(targetPath);
targetUri = targetPath;
}
targetsForUntitled.push(targetUri);
......@@ -536,18 +537,12 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
if (target) {
targetPromise = TPromise.wrap(target);
} else {
let dialogPath = resource.fsPath;
let dialogPath = resource;
if (resource.scheme === Schemas.untitled) {
dialogPath = this.suggestFileName(resource);
}
targetPromise = this.promptForPath(resource, dialogPath).then(pathRaw => {
if (pathRaw) {
return URI.file(pathRaw);
}
return void 0;
});
targetPromise = this.promptForPath(resource, dialogPath);
}
return targetPromise.then(target => {
......@@ -630,20 +625,22 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
});
}
private suggestFileName(untitledResource: URI): string {
private suggestFileName(untitledResource: URI): URI {
const untitledFileName = this.untitledEditorService.suggestFileName(untitledResource);
const lastActiveFile = this.historyService.getLastActiveFile(Schemas.file);
const schemeFilter = Schemas.file;
const lastActiveFile = this.historyService.getLastActiveFile(schemeFilter);
if (lastActiveFile) {
return URI.file(paths.join(paths.dirname(lastActiveFile.fsPath), untitledFileName)).fsPath;
return joinPath(lastActiveFile, untitledFileName);
}
const lastActiveFolder = this.historyService.getLastActiveWorkspaceRoot(Schemas.file);
const lastActiveFolder = this.historyService.getLastActiveWorkspaceRoot(schemeFilter);
if (lastActiveFolder) {
return URI.file(paths.join(lastActiveFolder.fsPath, untitledFileName)).fsPath;
return joinPath(lastActiveFolder, untitledFileName);
}
return untitledFileName;
return URI.file(untitledFileName);
}
revert(resource: URI, options?: IRevertOptions): TPromise<boolean> {
......
......@@ -29,7 +29,7 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IModelService } from 'vs/editor/common/services/modelService';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { getConfirmMessage, IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { getConfirmMessage, IDialogService, ISaveDialogOptions, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
export class TextFileService extends AbstractTextFileService {
......@@ -43,7 +43,7 @@ export class TextFileService extends AbstractTextFileService {
@IConfigurationService configurationService: IConfigurationService,
@IModeService private modeService: IModeService,
@IModelService modelService: IModelService,
@IWindowService private windowService: IWindowService,
@IWindowService windowService: IWindowService,
@IEnvironmentService environmentService: IEnvironmentService,
@INotificationService notificationService: INotificationService,
@IBackupFileService backupFileService: IBackupFileService,
......@@ -51,9 +51,10 @@ export class TextFileService extends AbstractTextFileService {
@IHistoryService historyService: IHistoryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IDialogService private dialogService: IDialogService,
@IFileDialogService private fileDialogService: IFileDialogService,
@IEditorService private editorService: IEditorService
) {
super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, notificationService, environmentService, backupFileService, windowsService, historyService, contextKeyService, modelService);
super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, notificationService, environmentService, backupFileService, windowsService, windowService, historyService, contextKeyService, modelService);
}
resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise<IRawTextContent> {
......@@ -104,16 +105,19 @@ export class TextFileService extends AbstractTextFileService {
});
}
promptForPath(resource: URI, defaultPath: string): TPromise<string> {
promptForPath(resource: URI, defaultUri: URI): TPromise<URI> {
// Help user to find a name for the file by opening it first
return this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true, } }).then(() => {
return this.windowService.showSaveDialog(this.getSaveDialogOptions(defaultPath));
return this.fileDialogService.showSaveDialog(this.getSaveDialogOptions(defaultUri));
});
}
private getSaveDialogOptions(defaultPath: string): Electron.SaveDialogOptions {
const options: Electron.SaveDialogOptions = { defaultPath };
private getSaveDialogOptions(defaultUri: URI): ISaveDialogOptions {
const options: ISaveDialogOptions = {
defaultUri,
title: nls.localize('saveAsTitle', "Save As")
};
// Filters are only enabled on Windows where they work properly
if (!isWindows) {
......@@ -123,7 +127,7 @@ export class TextFileService extends AbstractTextFileService {
interface IFilter { name: string; extensions: string[]; }
// Build the file filter by using our known languages
const ext: string = defaultPath ? paths.extname(defaultPath) : void 0;
const ext: string = defaultUri ? paths.extname(defaultUri.path) : void 0;
let matchingFilter: IFilter;
const filters: IFilter[] = this.modeService.getRegisteredLanguageNames().map(languageName => {
const extensions = this.modeService.getExtensions(languageName);
......
......@@ -254,7 +254,7 @@ suite('Files - TextFileService', () => {
(<TextFileEditorModelManager>accessor.textFileService.models).add(model.getResource(), model);
const service = accessor.textFileService;
service.setPromptPath(model.getResource().fsPath);
service.setPromptPath(model.getResource());
return model.load().then(() => {
model.textEditorModel.setValue('foo');
......@@ -273,7 +273,7 @@ suite('Files - TextFileService', () => {
(<TextFileEditorModelManager>accessor.textFileService.models).add(model.getResource(), model);
const service = accessor.textFileService;
service.setPromptPath(model.getResource().fsPath);
service.setPromptPath(model.getResource());
return model.load().then(() => {
model.textEditorModel.setValue('foo');
......
......@@ -59,7 +59,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService, MockKeybindingService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { ITextBufferFactory, DefaultEndOfLine, EndOfLinePreference, IModelDecorationOptions, ITextModel } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions, IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { IExtensionService, ProfileSession, IExtensionsStatus, ExtensionPointContribution, IExtensionDescription } from '../services/extensions/common/extensions';
......@@ -173,7 +173,7 @@ export class TestContextService implements IWorkspaceContextService {
export class TestTextFileService extends TextFileService {
public cleanupBackupsBeforeShutdownCalled: boolean;
private promptPath: string;
private promptPath: URI;
private confirmResult: ConfirmResult;
private resolveTextContentError: FileOperationError;
......@@ -187,14 +187,15 @@ export class TestTextFileService extends TextFileService {
@INotificationService notificationService: INotificationService,
@IBackupFileService backupFileService: IBackupFileService,
@IWindowsService windowsService: IWindowsService,
@IWindowService windowService: IWindowService,
@IHistoryService historyService: IHistoryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IModelService modelService: IModelService
) {
super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, notificationService, TestEnvironmentService, backupFileService, windowsService, historyService, contextKeyService, modelService);
super(lifecycleService, contextService, configurationService, fileService, untitledEditorService, instantiationService, notificationService, TestEnvironmentService, backupFileService, windowsService, windowService, historyService, contextKeyService, modelService);
}
public setPromptPath(path: string): void {
public setPromptPath(path: URI): void {
this.promptPath = path;
}
......@@ -226,7 +227,7 @@ export class TestTextFileService extends TextFileService {
});
}
public promptForPath(resource: URI, defaultPath: string): TPromise<string> {
public promptForPath(resource: URI, defaultPath: URI): TPromise<URI> {
return TPromise.wrap(this.promptPath);
}
......@@ -276,7 +277,7 @@ export function workbenchInstantiationService(): IInstantiationService {
instantiationService.stub(IHashService, new TestHashService());
instantiationService.stub(ILogService, new TestLogService());
instantiationService.stub(IEditorGroupsService, new TestEditorGroupsService([new TestEditorGroup(0)]));
instantiationService.stub(ILabelService, new LabelService(TestEnvironmentService, workspaceContextService));
instantiationService.stub(ILabelService, <ILabelService>instantiationService.createInstance(LabelService));
const editorService = new TestEditorService();
instantiationService.stub(IEditorService, editorService);
instantiationService.stub(ICodeEditorService, new TestCodeEditorService());
......@@ -392,6 +393,39 @@ export class TestDialogService implements IDialogService {
}
}
export class TestFileDialogService implements IFileDialogService {
public _serviceBrand: any;
public defaultFilePath(schemeFilter: string): URI {
return void 0;
}
public defaultFolderPath(schemeFilter: string): URI {
return void 0;
}
public defaultWorkspacePath(schemeFilter: string): URI {
return void 0;
}
public pickFileFolderAndOpen(options: IPickAndOpenOptions): TPromise<any> {
return TPromise.as(0);
}
public pickFileAndOpen(options: IPickAndOpenOptions): TPromise<any> {
return TPromise.as(0);
}
public pickFolderAndOpen(options: IPickAndOpenOptions): TPromise<any> {
return TPromise.as(0);
}
public pickWorkspaceAndOpen(options: IPickAndOpenOptions): TPromise<any> {
return TPromise.as(0);
}
public showSaveDialog(options: ISaveDialogOptions): TPromise<URI> {
return TPromise.as(void 0);
}
public showOpenDialog(options: IOpenDialogOptions): TPromise<URI[]> {
return TPromise.as(void 0);
}
}
export class TestPartService implements IPartService {
public _serviceBrand: any;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册