workbench.ts 58.6 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/workbench';
9

10
import { localize } from 'vs/nls';
11
import { TPromise } from 'vs/base/common/winjs.base';
B
Benjamin Pasero 已提交
12
import { IDisposable, dispose, toDisposable, Disposable } from 'vs/base/common/lifecycle';
M
Matt Bierner 已提交
13
import { Event, Emitter } from 'vs/base/common/event';
14
import * as DOM from 'vs/base/browser/dom';
B
Benjamin Pasero 已提交
15
import { Builder, $ } from 'vs/base/browser/builder';
B
Benjamin Pasero 已提交
16
import { RunOnceScheduler } from 'vs/base/common/async';
17
import * as browser from 'vs/base/browser/browser';
J
Johannes Rieken 已提交
18
import * as perf from 'vs/base/common/performance';
19
import * as errors from 'vs/base/common/errors';
20
import { BackupFileService } from 'vs/workbench/services/backup/node/backupFileService';
21
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
22
import { Registry } from 'vs/platform/registry/common/platform';
B
Benjamin Pasero 已提交
23
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
B
Benjamin Pasero 已提交
24
import { IResourceInput } from 'vs/platform/editor/common/editor';
J
Johannes Rieken 已提交
25
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
B
Benjamin Pasero 已提交
26
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, TextCompareEditorVisibleContext, TEXT_DIFF_EDITOR_ID, EditorsVisibleContext, InEditorZenModeContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, IUntitledResourceInput, IResourceDiffInput, SplitEditorsVertically } from 'vs/workbench/common/editor';
27
import { HistoryService } from 'vs/workbench/services/history/electron-browser/history';
J
Johannes Rieken 已提交
28 29 30 31
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { StatusbarPart } from 'vs/workbench/browser/parts/statusbar/statusbarPart';
B
Benjamin Pasero 已提交
32
import { TitlebarPart } from 'vs/workbench/browser/parts/titlebar/titlebarPart';
33
import { MenubarPart } from 'vs/workbench/browser/parts/menubar/menubarPart';
B
Benjamin Pasero 已提交
34
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
B
Benjamin Pasero 已提交
35
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
36
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
J
Johannes Rieken 已提交
37 38
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
C
Christof Marti 已提交
39 40
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput';
J
Johannes Rieken 已提交
41
import { getServices } from 'vs/platform/instantiation/common/extensions';
42
import { Position, Parts, IPartService, ILayoutOptions, IDimension } from 'vs/workbench/services/part/common/partService';
43
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
44 45 46 47
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
48
import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService';
49 50
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
J
Johannes Rieken 已提交
51 52
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
53
import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
B
Benjamin Pasero 已提交
54
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
I
isidor 已提交
55
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
B
Benjamin Pasero 已提交
56
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
P
Pine Wu 已提交
57
import { ViewletService } from 'vs/workbench/services/viewlet/browser/viewletService';
58
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
J
Johannes Rieken 已提交
59 60
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
61
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService';
J
Johannes Rieken 已提交
62
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
B
Benjamin Pasero 已提交
63
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
J
Johannes Rieken 已提交
64
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
65 66
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
J
Johannes Rieken 已提交
67 68 69 70 71
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { TextFileService } from 'vs/workbench/services/textfile/electron-browser/textFileService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
J
Joao Moreno 已提交
72 73
import { ISCMService } from 'vs/workbench/services/scm/common/scm';
import { SCMService } from 'vs/workbench/services/scm/common/scmService';
74 75
import { IProgressService2 } from 'vs/platform/progress/common/progress';
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
76
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
77
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
78
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
79
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
80
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
B
Benjamin Pasero 已提交
81
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath } from 'vs/platform/windows/common/windows';
J
Johannes Rieken 已提交
82
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
83
import { IMenuService, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
84
import { MenuService } from 'vs/workbench/services/actions/common/menuService';
J
Johannes Rieken 已提交
85 86
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
87
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
88
import { OpenRecentAction, ToggleDevToolsAction, ReloadWindowAction, ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions';
89
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
B
Benjamin Pasero 已提交
90 91
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService';
92
import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService';
J
Johannes Rieken 已提交
93
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
I
isidor 已提交
94
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
B
Benjamin Pasero 已提交
95
import URI from 'vs/base/common/uri';
J
Joao Moreno 已提交
96
import { IListService, ListService } from 'vs/platform/list/browser/listService';
J
Joao Moreno 已提交
97
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
98
import { IViewsService } from 'vs/workbench/common/views';
B
Benjamin Pasero 已提交
99
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
100 101
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
102 103
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
104
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
105
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
106
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
J
Joao Moreno 已提交
107 108
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
S
Sandeep Somavarapu 已提交
109 110
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
B
Benjamin Pasero 已提交
111 112 113
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
J
Joao Moreno 已提交
114
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler';
E
Erich Gamma 已提交
115 116

interface WorkbenchParams {
117
	configuration: IWindowConfiguration;
118
	serviceCollection: ServiceCollection;
E
Erich Gamma 已提交
119 120
}

I
isidor 已提交
121 122
interface IZenModeSettings {
	fullScreen: boolean;
123
	centerLayout: boolean;
I
isidor 已提交
124
	hideTabs: boolean;
125
	hideActivityBar: boolean;
I
isidor 已提交
126
	hideStatusBar: boolean;
I
isidor 已提交
127
	restore: boolean;
I
isidor 已提交
128 129
}

130 131 132
export interface IWorkbenchStartedInfo {
	customKeybindingsCount: number;
	pinnedViewlets: string[];
133
	restoredViewlet: string;
B
Benjamin Pasero 已提交
134
	restoredEditorsCount: number;
135 136
}

137 138
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';

B
Benjamin Pasero 已提交
139 140
const fontAliasingValues: FontAliasingOption[] = ['antialiased', 'none', 'auto'];

141 142
const Identifiers = {
	WORKBENCH_CONTAINER: 'workbench.main.container',
B
Benjamin Pasero 已提交
143
	TITLEBAR_PART: 'workbench.parts.titlebar',
144 145 146 147
	ACTIVITYBAR_PART: 'workbench.parts.activitybar',
	SIDEBAR_PART: 'workbench.parts.sidebar',
	PANEL_PART: 'workbench.parts.panel',
	EDITOR_PART: 'workbench.parts.editor',
148 149
	STATUSBAR_PART: 'workbench.parts.statusbar',
	MENUBAR_PART: 'workbench.parts.menubar'
150 151
};

J
Joao Moreno 已提交
152 153 154 155 156 157 158 159
function getWorkbenchStateString(state: WorkbenchState): string {
	switch (state) {
		case WorkbenchState.EMPTY: return 'empty';
		case WorkbenchState.FOLDER: return 'folder';
		case WorkbenchState.WORKSPACE: return 'workspace';
	}
}

B
Benjamin Pasero 已提交
160 161 162 163 164 165 166 167 168 169
interface IZenMode {
	active: boolean;
	transitionedToFullScreen: boolean;
	transitionedToCenteredEditorLayout: boolean;
	transitionDisposeables: IDisposable[];
	wasSideBarVisible: boolean;
	wasPanelVisible: boolean;
}

export class Workbench extends Disposable implements IPartService {
E
Erich Gamma 已提交
170

171
	private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
172
	private static readonly menubarVisibilityConfigurationKey = 'window.menuBarVisibility';
173 174 175
	private static readonly sidebarRestoreStorageKey = 'workbench.sidebar.restore';
	private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
	private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
176
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
177
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
178
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
179 180 181 182 183
	private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
	private static readonly statusbarVisibleConfigurationKey = 'workbench.statusBar.visible';
	private static readonly activityBarVisibleConfigurationKey = 'workbench.activityBar.visible';
	private static readonly closeWhenEmptyConfigurationKey = 'window.closeWhenEmpty';
	private static readonly fontAliasingConfigurationKey = 'workbench.fontAliasing';
184

B
Benjamin Pasero 已提交
185
	_serviceBrand: any;
186

E
Erich Gamma 已提交
187 188 189 190 191 192
	private workbenchParams: WorkbenchParams;
	private workbenchContainer: Builder;
	private workbench: Builder;
	private workbenchStarted: boolean;
	private workbenchCreated: boolean;
	private workbenchShutdown: boolean;
B
Benjamin Pasero 已提交
193 194 195

	private editorService: EditorService;
	private editorGroupService: IEditorGroupsService;
P
Pine Wu 已提交
196
	private viewletService: IViewletService;
197
	private contextKeyService: IContextKeyService;
198
	private keybindingService: IKeybindingService;
199
	private backupFileService: IBackupFileService;
200
	private fileService: IFileService;
B
Benjamin Pasero 已提交
201 202 203 204
	private quickInput: QuickInputService;

	private workbenchLayout: WorkbenchLayout;

B
Benjamin Pasero 已提交
205
	private titlebarPart: TitlebarPart;
206
	private menubarPart: MenubarPart;
E
Erich Gamma 已提交
207 208
	private activitybarPart: ActivitybarPart;
	private sidebarPart: SidebarPart;
I
isidor 已提交
209
	private panelPart: PanelPart;
E
Erich Gamma 已提交
210 211 212
	private editorPart: EditorPart;
	private statusbarPart: StatusbarPart;
	private quickOpen: QuickOpenController;
213
	private notificationsCenter: NotificationsCenter;
214
	private notificationsToasts: NotificationsToasts;
B
Benjamin Pasero 已提交
215

E
Erich Gamma 已提交
216
	private sideBarHidden: boolean;
217
	private statusBarHidden: boolean;
S
Sanders Lauture 已提交
218
	private activityBarHidden: boolean;
E
Erich Gamma 已提交
219
	private sideBarPosition: Position;
I
isidor 已提交
220
	private panelPosition: Position;
I
isidor 已提交
221
	private panelHidden: boolean;
222
	private menubarHidden: boolean;
B
Benjamin Pasero 已提交
223 224 225 226 227
	private zenMode: IZenMode;
	private centeredEditorLayoutActive: boolean;
	private fontAliasing: FontAliasingOption;
	private hasInitialFilesToOpen: boolean;

I
isidor 已提交
228
	private inZenMode: IContextKey<boolean>;
229
	private sideBarVisibleContext: IContextKey<boolean>;
B
Benjamin Pasero 已提交
230 231

	private closeEmptyWindowScheduler: RunOnceScheduler = new RunOnceScheduler(() => this.onAllEditorsClosed(), 50);
E
Erich Gamma 已提交
232

233
	constructor(
B
Benjamin Pasero 已提交
234 235
		private parent: HTMLElement,
		private container: HTMLElement,
J
Joao Moreno 已提交
236
		private configuration: IWindowConfiguration,
237
		serviceCollection: ServiceCollection,
238
		private lifecycleService: LifecycleService,
J
Joao Moreno 已提交
239
		private mainProcessClient: IPCClient,
240
		@IInstantiationService private instantiationService: IInstantiationService,
241
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
242
		@IStorageService private storageService: IStorageService,
243
		@IConfigurationService private configurationService: WorkspaceService,
I
isidor 已提交
244
		@IEnvironmentService private environmentService: IEnvironmentService,
245 246
		@IWindowService private windowService: IWindowService,
		@INotificationService private notificationService: NotificationService
247
	) {
B
Benjamin Pasero 已提交
248
		super();
E
Erich Gamma 已提交
249

B
Benjamin Pasero 已提交
250
		this.workbenchParams = { configuration, serviceCollection };
E
Erich Gamma 已提交
251

B
Benjamin Pasero 已提交
252
		this.hasInitialFilesToOpen =
B
Benjamin Pasero 已提交
253 254 255
			(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
			(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
			(configuration.filesToDiff && configuration.filesToDiff.length > 0);
256 257
	}

B
Benjamin Pasero 已提交
258
	startup(): TPromise<IWorkbenchStartedInfo> {
259
		this.workbenchStarted = true;
E
Erich Gamma 已提交
260

B
Benjamin Pasero 已提交
261
		// Create Workbench Container
262
		this.createWorkbench();
E
Erich Gamma 已提交
263

264 265
		// Install some global actions
		this.createGlobalActions();
E
Erich Gamma 已提交
266

267 268
		// Services
		this.initServices();
269

B
Benjamin Pasero 已提交
270 271
		// Context Keys
		this.handleContextKeys();
E
Erich Gamma 已提交
272

273 274
		// Register Listeners
		this.registerListeners();
E
Erich Gamma 已提交
275

276 277
		// Settings
		this.initSettings();
E
Erich Gamma 已提交
278

279 280
		// Create Workbench and Parts
		this.renderWorkbench();
281

282 283
		// Workbench Layout
		this.createWorkbenchLayout();
B
polish  
Benjamin Pasero 已提交
284

J
Joao Moreno 已提交
285 286
		// Driver
		if (this.environmentService.driverHandle) {
B
Benjamin Pasero 已提交
287
			registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService).then(disposable => this._register(disposable));
J
Joao Moreno 已提交
288 289
		}

290
		// Restore Parts
B
Benjamin Pasero 已提交
291 292
		return this.restoreParts();
	}
293

B
Benjamin Pasero 已提交
294 295 296 297 298 299
	private createWorkbench(): void {
		this.workbenchContainer = $('.monaco-workbench-container');
		this.workbench = $().div({
			'class': `monaco-workbench ${isWindows ? 'windows' : isLinux ? 'linux' : 'mac'}`,
			id: Identifiers.WORKBENCH_CONTAINER
		}).appendTo(this.workbenchContainer);
300
	}
E
Erich Gamma 已提交
301

302
	private createGlobalActions(): void {
B
Benjamin Pasero 已提交
303
		const isDeveloping = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
304

B
Benjamin Pasero 已提交
305
		// Actions registered here to adjust for developing vs built workbench
B
Benjamin Pasero 已提交
306 307 308 309 310
		const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
		registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyCode.KEY_R } : void 0), 'Reload Window');
		registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I } } : void 0), 'Developer: Toggle Developer Tools', localize('developer', "Developer"));
		registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: isDeveloping ? null : KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', localize('file', "File"));
		registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Reload Window Without Extensions');
311

312
		// Actions for macOS native tabs management (only when enabled)
313
		const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
314
		if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) {
B
Benjamin Pasero 已提交
315 316 317 318 319
			registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousWindowTab, ShowPreviousWindowTab.ID, ShowPreviousWindowTab.LABEL), 'Show Previous Window Tab');
			registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextWindowTab, ShowNextWindowTab.ID, ShowNextWindowTab.LABEL), 'Show Next Window Tab');
			registry.registerWorkbenchAction(new SyncActionDescriptor(MoveWindowTabToNewWindow, MoveWindowTabToNewWindow.ID, MoveWindowTabToNewWindow.LABEL), 'Move Window Tab to New Window');
			registry.registerWorkbenchAction(new SyncActionDescriptor(MergeAllWindowTabs, MergeAllWindowTabs.ID, MergeAllWindowTabs.LABEL), 'Merge All Windows');
			registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWindowTabsBar, ToggleWindowTabsBar.ID, ToggleWindowTabsBar.LABEL), 'Toggle Window Tabs Bar');
320
		}
321 322
	}

E
Erich Gamma 已提交
323
	private initServices(): void {
B
Benjamin Pasero 已提交
324
		const { serviceCollection } = this.workbenchParams;
325

E
Erich Gamma 已提交
326
		// Services we contribute
327
		serviceCollection.set(IPartService, this);
E
Erich Gamma 已提交
328

329 330 331
		// Clipboard
		serviceCollection.set(IClipboardService, new ClipboardService());

332 333
		// Status bar
		this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
B
Benjamin Pasero 已提交
334
		this._register(toDisposable(() => this.statusbarPart.shutdown()));
335 336
		serviceCollection.set(IStatusbarService, this.statusbarPart);

337 338 339
		// Progress 2
		serviceCollection.set(IProgressService2, new SyncDescriptor(ProgressService2));

340
		// Keybindings
A
Alex Dima 已提交
341
		this.contextKeyService = this.instantiationService.createInstance(ContextKeyService);
342
		serviceCollection.set(IContextKeyService, this.contextKeyService);
343

B
Benjamin Pasero 已提交
344
		this.keybindingService = this.instantiationService.createInstance(WorkbenchKeybindingService, window);
345
		serviceCollection.set(IKeybindingService, this.keybindingService);
A
Alex Dima 已提交
346

347 348 349
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

350
		// Context Menu
351
		serviceCollection.set(IContextMenuService, new SyncDescriptor(ContextMenuService));
352

353 354
		// Menus/Actions
		serviceCollection.set(IMenuService, new SyncDescriptor(MenuService));
355

P
Pine Wu 已提交
356
		// Sidebar part
357
		this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
B
Benjamin Pasero 已提交
358
		this._register(toDisposable(() => this.sidebarPart.shutdown()));
P
Pine Wu 已提交
359 360 361 362

		// Viewlet service
		this.viewletService = this.instantiationService.createInstance(ViewletService, this.sidebarPart);
		serviceCollection.set(IViewletService, this.viewletService);
E
Erich Gamma 已提交
363

I
isidor 已提交
364
		// Panel service (panel part)
365
		this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
B
Benjamin Pasero 已提交
366
		this._register(toDisposable(() => this.panelPart.shutdown()));
367
		serviceCollection.set(IPanelService, this.panelPart);
I
isidor 已提交
368

S
Sandeep Somavarapu 已提交
369
		// Custom views service
B
Benjamin Pasero 已提交
370
		const customViewsService = this.instantiationService.createInstance(ViewsService);
371
		serviceCollection.set(IViewsService, customViewsService);
S
Sandeep Somavarapu 已提交
372

E
Erich Gamma 已提交
373
		// Activity service (activitybar part)
374
		this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
B
Benjamin Pasero 已提交
375
		this._register(toDisposable(() => this.activitybarPart.shutdown()));
I
isidor 已提交
376 377
		const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
		serviceCollection.set(IActivityService, activityService);
E
Erich Gamma 已提交
378

379 380 381
		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
S
#47154  
Sandeep Somavarapu 已提交
382
		this.configurationService.acquireFileService(this.fileService);
E
Erich Gamma 已提交
383

B
Benjamin Pasero 已提交
384 385 386 387 388 389 390 391
		// Editor and Group services
		const restorePreviousEditorState = !this.hasInitialFilesToOpen;
		this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
		this._register(toDisposable(() => this.editorPart.shutdown()));
		this.editorGroupService = this.editorPart;
		serviceCollection.set(IEditorGroupsService, this.editorPart);
		this.editorService = this.instantiationService.createInstance(EditorService);
		serviceCollection.set(IEditorService, this.editorService);
E
Erich Gamma 已提交
392

393 394
		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
B
Benjamin Pasero 已提交
395
		this._register(toDisposable(() => this.titlebarPart.shutdown()));
396 397
		serviceCollection.set(ITitleService, this.titlebarPart);

398
		// History
399
		serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService));
400

B
Benjamin Pasero 已提交
401 402 403
		// Menubar
		this.menubarPart = this.instantiationService.createInstance(MenubarPart, Identifiers.MENUBAR_PART);

404
		// Backup File Service
405
		this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.workbenchParams.configuration.backupPath);
406
		serviceCollection.set(IBackupFileService, this.backupFileService);
407

408
		// Text File Service
409
		serviceCollection.set(ITextFileService, new SyncDescriptor(TextFileService));
410

411
		// File Decorations
J
Johannes Rieken 已提交
412
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));
413

J
Joao Moreno 已提交
414
		// SCM Service
415
		serviceCollection.set(ISCMService, new SyncDescriptor(SCMService));
416

J
Joao Moreno 已提交
417
		// Inactive extension URL handler
J
Joao Moreno 已提交
418
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));
J
Joao Moreno 已提交
419

B
Benjamin Pasero 已提交
420
		// Text Model Resolver Service
421
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));
B
Benjamin Pasero 已提交
422

423 424 425 426
		// JSON Editing
		const jsonEditingService = this.instantiationService.createInstance(JSONEditingService);
		serviceCollection.set(IJSONEditingService, jsonEditingService);

427 428 429
		// Workspace Editing
		serviceCollection.set(IWorkspaceEditingService, new SyncDescriptor(WorkspaceEditingService));

430 431 432
		// Keybinding Editing
		serviceCollection.set(IKeybindingEditingService, this.instantiationService.createInstance(KeybindingsEditingService));

433
		// Configuration Resolver
B
Benjamin Pasero 已提交
434
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, process.env));
435

E
Erich Gamma 已提交
436
		// Quick open service (quick open controller)
437
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
B
Benjamin Pasero 已提交
438
		this._register(toDisposable(() => this.quickOpen.shutdown()));
439
		serviceCollection.set(IQuickOpenService, this.quickOpen);
E
Erich Gamma 已提交
440

C
Christof Marti 已提交
441 442
		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
B
Benjamin Pasero 已提交
443
		this._register(toDisposable(() => this.quickInput.shutdown()));
C
Christof Marti 已提交
444 445
		serviceCollection.set(IQuickInputService, this.quickInput);

S
Sandeep Somavarapu 已提交
446 447 448
		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

B
polish  
Benjamin Pasero 已提交
449
		// Contributed services
B
Benjamin Pasero 已提交
450
		const contributedServices = getServices();
E
Erich Gamma 已提交
451
		for (let contributedService of contributedServices) {
452
			serviceCollection.set(contributedService.id, contributedService.descriptor);
E
Erich Gamma 已提交
453 454 455
		}

		// Set the some services to registries that have been created eagerly
456
		Registry.as<IActionBarRegistry>(ActionBarExtensions.Actionbar).setInstantiationService(this.instantiationService);
457
		Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(this.instantiationService, this.lifecycleService);
458
		Registry.as<IEditorInputFactoryRegistry>(EditorExtensions.EditorInputFactories).setInstantiationService(this.instantiationService);
459

460
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
461

S
#47154  
Sandeep Somavarapu 已提交
462
		this.configurationService.acquireInstantiationService(this.getInstantiationService());
E
Erich Gamma 已提交
463 464
	}

B
Benjamin Pasero 已提交
465
	//#region event handling
E
Erich Gamma 已提交
466

B
Benjamin Pasero 已提交
467
	private registerListeners(): void {
E
Erich Gamma 已提交
468

B
Benjamin Pasero 已提交
469 470
		// Listen to visible editor changes
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
I
isidor 已提交
471

B
Benjamin Pasero 已提交
472 473 474 475 476 477
		// Listen to editor closing (if we run with --wait)
		const filesToWait = this.workbenchParams.configuration.filesToWait;
		if (filesToWait) {
			const resourcesToWaitFor = filesToWait.paths.map(p => URI.file(p.filePath));
			const waitMarkerFile = URI.file(filesToWait.waitMarkerFilePath);
			const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
B
Benjamin Pasero 已提交
478

B
Benjamin Pasero 已提交
479 480
			this._register(listenerDispose);
		}
I
isidor 已提交
481

B
Benjamin Pasero 已提交
482 483
		// Configuration changes
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
S
Sanders Lauture 已提交
484

B
Benjamin Pasero 已提交
485 486 487
		// Fullscreen changes
		this._register(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
	}
I
isidor 已提交
488

B
Benjamin Pasero 已提交
489 490 491 492
	private onFullscreenChanged(): void {
		if (!this.isCreated) {
			return; // we need to be ready
		}
493

B
Benjamin Pasero 已提交
494 495 496 497 498 499 500 501 502 503
		// Apply as CSS class
		const isFullscreen = browser.isFullscreen();
		if (isFullscreen) {
			this.workbench.addClass('fullscreen');
		} else {
			this.workbench.removeClass('fullscreen');
			if (this.zenMode.transitionedToFullScreen && this.zenMode.active) {
				this.toggleZenMode();
			}
		}
S
SrTobi 已提交
504

505 506
		this.menubarPart.updateStyles();

B
Benjamin Pasero 已提交
507 508 509 510 511 512
		// Changing fullscreen state of the window has an impact on custom title bar visibility, so we need to update
		const hasCustomTitle = this.getCustomTitleBarStyle() === 'custom';
		if (hasCustomTitle) {
			this._onTitleBarVisibilityChange.fire();
			this.layout(); // handle title bar when fullscreen changes
		}
E
Erich Gamma 已提交
513 514
	}

B
Benjamin Pasero 已提交
515
	private onEditorClosed(listenerDispose: IDisposable, resourcesToWaitFor: URI[], waitMarkerFile: URI): void {
E
Erich Gamma 已提交
516

B
Benjamin Pasero 已提交
517 518 519 520 521 522 523
		// In wait mode, listen to changes to the editors and wait until the files
		// are closed that the user wants to wait for. When this happens we delete
		// the wait marker file to signal to the outside that editing is done.
		if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
			listenerDispose.dispose();
			this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError);
		}
E
Erich Gamma 已提交
524 525
	}

B
Benjamin Pasero 已提交
526 527
	private onDidVisibleEditorsChange(): void {
		const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
528

B
Benjamin Pasero 已提交
529 530 531 532 533 534 535 536
		// Close when empty: check if we should close the window based on the setting
		// Overruled by: window has a workspace opened or this window is for extension development
		// or setting is disabled. Also enabled when running with --wait from the command line.
		if (visibleEditors.length === 0 && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && !this.environmentService.isExtensionDevelopment) {
			const closeWhenEmpty = this.configurationService.getValue<boolean>(Workbench.closeWhenEmptyConfigurationKey);
			if (closeWhenEmpty || this.environmentService.args.wait) {
				this.closeEmptyWindowScheduler.schedule();
			}
E
Erich Gamma 已提交
537
		}
538 539
	}

B
Benjamin Pasero 已提交
540 541 542 543
	private onAllEditorsClosed(): void {
		const visibleEditors = this.editorService.visibleControls.length;
		if (visibleEditors === 0) {
			this.windowService.closeWindow();
E
Erich Gamma 已提交
544 545 546
		}
	}

B
Benjamin Pasero 已提交
547 548 549 550 551
	private onDidUpdateConfiguration(skipLayout?: boolean): void {
		const newSidebarPositionValue = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
		const newSidebarPosition = (newSidebarPositionValue === 'right') ? Position.RIGHT : Position.LEFT;
		if (newSidebarPosition !== this.getSideBarPosition()) {
			this.setSideBarPosition(newSidebarPosition);
552
		}
E
Erich Gamma 已提交
553

B
Benjamin Pasero 已提交
554
		this.setPanelPositionFromStorageOrConfig();
E
Erich Gamma 已提交
555

B
Benjamin Pasero 已提交
556 557 558
		const fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
		if (fontAliasing !== this.fontAliasing) {
			this.setFontAliasing(fontAliasing);
559 560
		}

B
Benjamin Pasero 已提交
561 562 563 564 565 566 567 568 569 570 571
		if (!this.zenMode.active) {
			const newStatusbarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.statusbarVisibleConfigurationKey);
			if (newStatusbarHiddenValue !== this.statusBarHidden) {
				this.setStatusBarHidden(newStatusbarHiddenValue, skipLayout);
			}

			const newActivityBarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.activityBarVisibleConfigurationKey);
			if (newActivityBarHiddenValue !== this.activityBarHidden) {
				this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout);
			}
		}
572 573 574

		const newMenubarVisibility = this.configurationService.getValue<string>(Workbench.menubarVisibilityConfigurationKey);
		this.setMenubarHidden(newMenubarVisibility, skipLayout);
575 576
	}

B
Benjamin Pasero 已提交
577
	//#endregion
B
Benjamin Pasero 已提交
578

B
Benjamin Pasero 已提交
579 580
	private handleContextKeys(): void {
		this.inZenMode = InEditorZenModeContext.bindTo(this.contextKeyService);
B
Benjamin Pasero 已提交
581

B
Benjamin Pasero 已提交
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
		const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
		this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);

		const editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
		const textCompareEditorVisible = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
		const activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
		const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);

		const updateEditorContextKeys = () => {
			const visibleEditors = this.editorService.visibleControls;

			textCompareEditorVisible.set(visibleEditors.some(control => control.getId() === TEXT_DIFF_EDITOR_ID));

			if (visibleEditors.length > 0) {
				editorsVisibleContext.set(true);
			} else {
				editorsVisibleContext.reset();
599
			}
B
Benjamin Pasero 已提交
600

B
Benjamin Pasero 已提交
601 602 603 604
			if (!this.editorService.activeEditor) {
				activeEditorGroupEmpty.set(true);
			} else {
				activeEditorGroupEmpty.reset();
R
Ryan Adolf 已提交
605
			}
606

B
Benjamin Pasero 已提交
607 608 609 610 611 612
			if (this.editorGroupService.count > 1) {
				multipleEditorGroups.set(true);
			} else {
				multipleEditorGroups.reset();
			}
		};
B
Benjamin Pasero 已提交
613

B
Benjamin Pasero 已提交
614 615 616 617 618
		this.editorPart.whenRestored.then(() => updateEditorContextKeys());
		this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
		this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
		this._register(this.editorGroupService.onDidAddGroup(() => updateEditorContextKeys()));
		this._register(this.editorGroupService.onDidRemoveGroup(() => updateEditorContextKeys()));
619

B
Benjamin Pasero 已提交
620 621 622 623 624 625 626 627 628 629
		const inputFocused = InputFocusedContext.bindTo(this.contextKeyService);
		this._register(DOM.addDisposableListener(window, 'focusin', () => {
			inputFocused.set(document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA'));
		}, true));

		const workbenchStateRawContext = new RawContextKey<string>('workbenchState', getWorkbenchStateString(this.configurationService.getWorkbenchState()));
		const workbenchStateContext = workbenchStateRawContext.bindTo(this.contextKeyService);
		this._register(this.configurationService.onDidChangeWorkbenchState(() => {
			workbenchStateContext.set(getWorkbenchStateString(this.configurationService.getWorkbenchState()));
		}));
I
isidor 已提交
630

B
Benjamin Pasero 已提交
631 632 633 634 635
		const workspaceFolderCountRawContext = new RawContextKey<number>('workspaceFolderCount', this.configurationService.getWorkspace().folders.length);
		const workspaceFolderCountContext = workspaceFolderCountRawContext.bindTo(this.contextKeyService);
		this._register(this.configurationService.onDidChangeWorkspaceFolders(() => {
			workspaceFolderCountContext.set(this.configurationService.getWorkspace().folders.length);
		}));
636

B
Benjamin Pasero 已提交
637
		const splitEditorsVerticallyContext = SplitEditorsVertically.bindTo(this.contextKeyService);
S
Sanders Lauture 已提交
638

B
Benjamin Pasero 已提交
639 640 641 642
		const updateSplitEditorsVerticallyContext = () => {
			const direction = preferredSideBySideGroupDirection(this.configurationService);
			splitEditorsVerticallyContext.set(direction === GroupDirection.DOWN);
		};
S
Sanders Lauture 已提交
643

B
Benjamin Pasero 已提交
644 645 646 647 648
		this._register(this.configurationService.onDidChangeConfiguration(e => {
			if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) {
				updateSplitEditorsVerticallyContext();
			}
		}));
E
Erich Gamma 已提交
649

B
Benjamin Pasero 已提交
650 651
		updateSplitEditorsVerticallyContext();
	}
E
Erich Gamma 已提交
652

B
Benjamin Pasero 已提交
653 654
	private restoreParts(): TPromise<IWorkbenchStartedInfo> {
		const restorePromises: Thenable<any>[] = [];
B
Benjamin Pasero 已提交
655

B
Benjamin Pasero 已提交
656 657 658 659 660 661
		// Restore Editorpart
		perf.mark('willRestoreEditors');
		restorePromises.push(this.editorPart.whenRestored.then(() => {
			return this.resolveEditorsToOpen().then(inputs => {
				if (inputs.length) {
					return this.editorService.openEditors(inputs);
662
				}
E
Erich Gamma 已提交
663

B
Benjamin Pasero 已提交
664 665 666 667 668
				return TPromise.as(void 0);
			});
		}).then(() => {
			perf.mark('didRestoreEditors');
		}));
E
Erich Gamma 已提交
669

B
Benjamin Pasero 已提交
670 671 672 673
		// Restore Sidebar
		let viewletIdToRestore: string;
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);
674

B
Benjamin Pasero 已提交
675 676
			if (this.shouldRestoreLastOpenedViewlet()) {
				viewletIdToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE);
677
			}
678

B
Benjamin Pasero 已提交
679 680
			if (!viewletIdToRestore) {
				viewletIdToRestore = this.viewletService.getDefaultViewletId();
681
			}
E
Erich Gamma 已提交
682

B
Benjamin Pasero 已提交
683 684 685 686 687 688
			perf.mark('willRestoreViewlet');
			restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore)
				.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId()))
				.then(() => {
					perf.mark('didRestoreViewlet');
				}));
689 690
		}

B
Benjamin Pasero 已提交
691 692 693 694 695
		// Restore Panel
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
		const panelId = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
		if (!this.panelHidden && !!panelId) {
			restorePromises.push(this.panelPart.openPanel(panelId, false));
I
isidor 已提交
696 697
		}

B
Benjamin Pasero 已提交
698 699 700
		// Restore Zen Mode if active
		if (this.storageService.getBoolean(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE, false)) {
			this.toggleZenMode(true);
I
isidor 已提交
701 702
		}

B
Benjamin Pasero 已提交
703 704 705 706
		// Restore Forced Editor Center Mode
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
			this.centeredEditorLayoutActive = true;
		}
707

B
Benjamin Pasero 已提交
708 709
		const onRestored = (error?: Error): IWorkbenchStartedInfo => {
			this.workbenchCreated = true;
710

B
Benjamin Pasero 已提交
711 712
			if (error) {
				errors.onUnexpectedError(error);
713
			}
I
isidor 已提交
714

B
Benjamin Pasero 已提交
715 716 717 718 719 720 721
			return {
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
				pinnedViewlets: this.activitybarPart.getPinned(),
				restoredViewlet: viewletIdToRestore,
				restoredEditorsCount: this.editorService.visibleEditors.length
			};
		};
I
isidor 已提交
722

B
Benjamin Pasero 已提交
723
		return TPromise.join(restorePromises).then(() => onRestored(), error => onRestored(error));
E
Erich Gamma 已提交
724 725
	}

B
Benjamin Pasero 已提交
726 727 728
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
E
Erich Gamma 已提交
729 730
		}

B
Benjamin Pasero 已提交
731 732 733 734
		const restore = this.storageService.getBoolean(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE);
		if (restore) {
			this.storageService.remove(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE); // only support once
		}
735

B
Benjamin Pasero 已提交
736
		return restore;
E
Erich Gamma 已提交
737 738
	}

B
Benjamin Pasero 已提交
739 740
	private resolveEditorsToOpen(): TPromise<IResourceEditor[]> {
		const config = this.workbenchParams.configuration;
I
isidor 已提交
741

B
Benjamin Pasero 已提交
742 743
		// Files to open, diff or create
		if (this.hasInitialFilesToOpen) {
I
isidor 已提交
744

B
Benjamin Pasero 已提交
745 746 747 748 749 750 751 752 753
			// Files to diff is exclusive
			const filesToDiff = this.toInputs(config.filesToDiff, false);
			if (filesToDiff && filesToDiff.length === 2) {
				return TPromise.as([<IResourceDiffInput>{
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
					options: { pinned: true }
				}]);
			}
I
isidor 已提交
754

B
Benjamin Pasero 已提交
755 756
			const filesToCreate = this.toInputs(config.filesToCreate, true);
			const filesToOpen = this.toInputs(config.filesToOpen, false);
I
isidor 已提交
757

B
Benjamin Pasero 已提交
758 759 760
			// Otherwise: Open/Create files
			return TPromise.as([...filesToOpen, ...filesToCreate]);
		}
I
isidor 已提交
761

B
Benjamin Pasero 已提交
762 763 764 765 766 767
		// Empty workbench
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
			const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
			if (!isEmpty) {
				return TPromise.as([]); // do not open any empty untitled file if we restored editors from previous session
			}
B
Benjamin Pasero 已提交
768

B
Benjamin Pasero 已提交
769 770 771 772
			return this.backupFileService.hasBackups().then(hasBackups => {
				if (hasBackups) {
					return TPromise.as([]); // do not open any empty untitled file if we have backups to restore
				}
B
Benjamin Pasero 已提交
773

B
Benjamin Pasero 已提交
774 775
				return TPromise.as([<IUntitledResourceInput>{}]);
			});
776
		}
777

B
Benjamin Pasero 已提交
778 779
		return TPromise.as([]);
	}
780

B
Benjamin Pasero 已提交
781 782 783
	private toInputs(paths: IPath[], isNew: boolean): (IResourceInput | IUntitledResourceInput)[] {
		if (!paths || !paths.length) {
			return [];
784
		}
I
isidor 已提交
785

B
Benjamin Pasero 已提交
786 787 788 789 790 791 792
		return paths.map(p => {
			const resource = URI.file(p.filePath);
			let input: IResourceInput | IUntitledResourceInput;
			if (isNew) {
				input = { filePath: resource.fsPath, options: { pinned: true } } as IUntitledResourceInput;
			} else {
				input = { resource, options: { pinned: true } } as IResourceInput;
793
			}
E
Erich Gamma 已提交
794

B
Benjamin Pasero 已提交
795 796 797 798 799 800
			if (!isNew && p.lineNumber) {
				input.options.selection = {
					startLineNumber: p.lineNumber,
					startColumn: p.columnNumber
				};
			}
801

B
Benjamin Pasero 已提交
802 803
			return input;
		});
804 805
	}

B
Benjamin Pasero 已提交
806 807 808 809 810 811 812 813 814
	private openUntitledFile() {
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');

		// Fallback to previous workbench.welcome.enabled setting in case startupEditor is not defined
		if (!startupEditor.user && !startupEditor.workspace) {
			const welcomeEnabledValue = this.configurationService.getValue('workbench.welcome.enabled');
			if (typeof welcomeEnabledValue === 'boolean') {
				return !welcomeEnabledValue;
			}
815
		}
E
Erich Gamma 已提交
816

B
Benjamin Pasero 已提交
817 818
		return startupEditor.value === 'newUntitledFile';
	}
E
Erich Gamma 已提交
819

B
Benjamin Pasero 已提交
820
	private initSettings(): void {
821

B
Benjamin Pasero 已提交
822 823
		// Sidebar visibility
		this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenStorageKey, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY);
824

B
Benjamin Pasero 已提交
825 826 827 828 829
		// Panel part visibility
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
830 831
		}

B
Benjamin Pasero 已提交
832 833 834
		// Sidebar position
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
835

B
Benjamin Pasero 已提交
836 837
		// Panel position
		this.setPanelPositionFromStorageOrConfig();
838

839 840 841 842
		// Menubar visibility
		const menuBarVisibility = this.configurationService.getValue<string>(Workbench.menubarVisibilityConfigurationKey);
		this.setMenubarHidden(menuBarVisibility, true);

B
Benjamin Pasero 已提交
843 844 845
		// Statusbar visibility
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
		this.statusBarHidden = !statusBarVisible;
846

B
Benjamin Pasero 已提交
847 848 849
		// Activity bar visibility
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
		this.activityBarHidden = !activityBarVisible;
850

B
Benjamin Pasero 已提交
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
		// Font aliasing
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);

		// Zen mode
		this.zenMode = {
			active: false,
			transitionedToFullScreen: false,
			transitionedToCenteredEditorLayout: false,
			wasSideBarVisible: false,
			wasPanelVisible: false,
			transitionDisposeables: []
		};

		// Centered Editor Layout
		this.centeredEditorLayoutActive = false;
E
Erich Gamma 已提交
866 867
	}

B
Benjamin Pasero 已提交
868 869 870 871 872
	private setPanelPositionFromStorageOrConfig() {
		const defaultPanelPosition = this.configurationService.getValue<string>(Workbench.defaultPanelPositionStorageKey);
		const panelPosition = this.storageService.get(Workbench.panelPositionStorageKey, StorageScope.WORKSPACE, defaultPanelPosition);
		this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
	}
873

B
Benjamin Pasero 已提交
874 875 876 877
	private getCustomTitleBarStyle(): 'custom' {
		const isDev = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
		if (isMacintosh && isDev) {
			return null; // not enabled when developing due to https://github.com/electron/electron/issues/3647
878 879
		}

B
Benjamin Pasero 已提交
880 881 882 883 884 885
		const windowConfig = this.configurationService.getValue<IWindowSettings>();
		if (windowConfig && windowConfig.window) {
			const useNativeTabs = windowConfig.window.nativeTabs;
			if (useNativeTabs) {
				return null; // native tabs on sierra do not work with custom title style
			}
E
Erich Gamma 已提交
886

B
Benjamin Pasero 已提交
887 888 889
			const style = windowConfig.window.titleBarStyle;
			if (style === 'custom') {
				return style;
890 891 892
			}
		}

B
Benjamin Pasero 已提交
893
		return null;
B
Benjamin Pasero 已提交
894 895
	}

B
Benjamin Pasero 已提交
896 897
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
898

B
Benjamin Pasero 已提交
899 900 901
		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nostatusbar');
E
Erich Gamma 已提交
902
		} else {
B
Benjamin Pasero 已提交
903
			this.workbench.removeClass('nostatusbar');
E
Erich Gamma 已提交
904 905
		}

B
Benjamin Pasero 已提交
906 907 908
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
909 910 911
		}
	}

B
Benjamin Pasero 已提交
912 913
	private setFontAliasing(aliasing: FontAliasingOption) {
		this.fontAliasing = aliasing;
914

B
Benjamin Pasero 已提交
915 916
		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));
S
Sanders Lauture 已提交
917

B
Benjamin Pasero 已提交
918 919 920
		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
921
		}
922 923
	}

E
Erich Gamma 已提交
924
	private createWorkbenchLayout(): void {
925 926
		this.workbenchLayout = this.instantiationService.createInstance(
			WorkbenchLayout,
B
Benjamin Pasero 已提交
927 928
			this.container,
			this.workbench.getHTMLElement(),
I
isidor 已提交
929
			{
B
Benjamin Pasero 已提交
930 931 932 933 934 935 936
				titlebar: this.titlebarPart,
				menubar: this.menubarPart,
				activitybar: this.activitybarPart,
				editor: this.editorPart,
				sidebar: this.sidebarPart,
				panel: this.panelPart,
				statusbar: this.statusbarPart,
I
isidor 已提交
937
			},
B
Benjamin Pasero 已提交
938 939 940 941
			this.quickOpen,
			this.quickInput,
			this.notificationsCenter,
			this.notificationsToasts
E
Erich Gamma 已提交
942 943
		);

944 945 946 947 948
		if (!isMacintosh && this.getCustomTitleBarStyle()) {
			this.windowService.isMaximized().then((max) => {
				this.workbenchLayout.onMaximizeChange(max);
				this.workbenchLayout.layout();
			});
B
Benjamin Pasero 已提交
949

950 951
			this.windowService.onDidChangeMaximize(this.workbenchLayout.onMaximizeChange, this.workbenchLayout);
		}
E
Erich Gamma 已提交
952 953 954 955 956 957 958 959
	}

	private renderWorkbench(): void {

		// Apply sidebar state as CSS class
		if (this.sideBarHidden) {
			this.workbench.addClass('nosidebar');
		}
960 961 962
		if (this.panelHidden) {
			this.workbench.addClass('nopanel');
		}
963 964 965
		if (this.statusBarHidden) {
			this.workbench.addClass('nostatusbar');
		}
E
Erich Gamma 已提交
966

B
Benjamin Pasero 已提交
967
		// Apply font aliasing
968 969
		this.setFontAliasing(this.fontAliasing);

B
Benjamin Pasero 已提交
970
		// Apply title style if shown
971 972 973 974 975 976 977 978
		const titleStyle = this.getCustomTitleBarStyle();
		if (titleStyle) {
			DOM.addClass(this.parent, `titlebar-style-${titleStyle}`);
		}

		// Apply fullscreen state
		if (browser.isFullscreen()) {
			this.workbench.addClass('fullscreen');
B
Benjamin Pasero 已提交
979 980
		}

E
Erich Gamma 已提交
981
		// Create Parts
B
Benjamin Pasero 已提交
982
		this.createTitlebarPart();
983
		this.createMenubarPart();
E
Erich Gamma 已提交
984 985 986
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
987
		this.createPanelPart();
E
Erich Gamma 已提交
988 989
		this.createStatusbarPart();

990 991
		// Notification Handlers
		this.createNotificationsHandlers();
992

E
Erich Gamma 已提交
993 994 995 996
		// Add Workbench to DOM
		this.workbenchContainer.build(this.container);
	}

B
Benjamin Pasero 已提交
997 998 999 1000 1001 1002 1003
	private createTitlebarPart(): void {
		const titlebarContainer = $(this.workbench).div({
			'class': ['part', 'titlebar'],
			id: Identifiers.TITLEBAR_PART,
			role: 'contentinfo'
		});

1004
		this.titlebarPart.create(titlebarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
1005 1006
	}

1007
	private createMenubarPart(): void {
1008 1009 1010 1011 1012
		const menubarContainer = $(this.workbench).div({
			'class': ['part', 'menubar'],
			id: Identifiers.MENUBAR_PART,
			role: 'menubar'
		});
B
Benjamin Pasero 已提交
1013

1014 1015 1016
		this.menubarPart.create(menubarContainer.getHTMLElement());
	}

E
Erich Gamma 已提交
1017
	private createActivityBarPart(): void {
B
Benjamin Pasero 已提交
1018
		const activitybarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
1019 1020
			.div({
				'class': ['part', 'activitybar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
1021 1022
				id: Identifiers.ACTIVITYBAR_PART,
				role: 'navigation'
E
Erich Gamma 已提交
1023 1024
			});

1025
		this.activitybarPart.create(activitybarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1026 1027 1028
	}

	private createSidebarPart(): void {
B
Benjamin Pasero 已提交
1029
		const sidebarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
1030 1031
			.div({
				'class': ['part', 'sidebar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
1032 1033
				id: Identifiers.SIDEBAR_PART,
				role: 'complementary'
E
Erich Gamma 已提交
1034 1035
			});

1036
		this.sidebarPart.create(sidebarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1037 1038
	}

I
isidor 已提交
1039
	private createPanelPart(): void {
B
Benjamin Pasero 已提交
1040
		const panelPartContainer = $(this.workbench)
I
isidor 已提交
1041
			.div({
1042
				'class': ['part', 'panel', this.panelPosition === Position.BOTTOM ? 'bottom' : 'right'],
1043 1044
				id: Identifiers.PANEL_PART,
				role: 'complementary'
I
isidor 已提交
1045 1046
			});

1047
		this.panelPart.create(panelPartContainer.getHTMLElement());
I
isidor 已提交
1048 1049
	}

E
Erich Gamma 已提交
1050
	private createEditorPart(): void {
B
Benjamin Pasero 已提交
1051
		const editorContainer = $(this.workbench)
E
Erich Gamma 已提交
1052
			.div({
B
Benjamin Pasero 已提交
1053
				'class': ['part', 'editor'],
1054 1055
				id: Identifiers.EDITOR_PART,
				role: 'main'
E
Erich Gamma 已提交
1056 1057
			});

1058
		this.editorPart.create(editorContainer.getHTMLElement());
E
Erich Gamma 已提交
1059 1060 1061
	}

	private createStatusbarPart(): void {
B
Benjamin Pasero 已提交
1062
		const statusbarContainer = $(this.workbench).div({
E
Erich Gamma 已提交
1063
			'class': ['part', 'statusbar'],
1064 1065
			id: Identifiers.STATUSBAR_PART,
			role: 'contentinfo'
E
Erich Gamma 已提交
1066 1067
		});

1068
		this.statusbarPart.create(statusbarContainer.getHTMLElement());
E
Erich Gamma 已提交
1069 1070
	}

1071 1072
	private createNotificationsHandlers(): void {

1073
		// Notifications Center
B
Benjamin Pasero 已提交
1074
		this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench.getHTMLElement(), this.notificationService.model));
1075

1076
		// Notifications Toasts
B
Benjamin Pasero 已提交
1077
		this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench.getHTMLElement(), this.notificationService.model));
1078

1079
		// Notifications Alerts
B
Benjamin Pasero 已提交
1080
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1081 1082 1083 1084

		// Notifications Status
		const notificationsStatus = this.instantiationService.createInstance(NotificationsStatus, this.notificationService.model);

1085
		// Eventing
B
Benjamin Pasero 已提交
1086
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1087 1088 1089 1090 1091 1092 1093 1094

			// Update status
			notificationsStatus.update(this.notificationsCenter.isVisible);

			// Update toasts
			this.notificationsToasts.update(this.notificationsCenter.isVisible);
		}));

1095
		// Register Commands
1096
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1097 1098
	}

B
Benjamin Pasero 已提交
1099
	getInstantiationService(): IInstantiationService {
E
Erich Gamma 已提交
1100 1101 1102
		return this.instantiationService;
	}

B
Benjamin Pasero 已提交
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
	dispose(reason = ShutdownReason.QUIT): void {
		super.dispose();

		// Restore sidebar if we are being shutdown as a matter of a reload
		if (reason === ShutdownReason.RELOAD) {
			this.storageService.store(Workbench.sidebarRestoreStorageKey, 'true', StorageScope.WORKSPACE);
		}

		// Preserve zen mode only on reload. Real quit gets out of zen mode so novice users do not get stuck in zen mode.
		const zenConfig = this.configurationService.getValue<IZenModeSettings>('zenMode');
		const restoreZenMode = this.zenMode.active && (zenConfig.restore || reason === ShutdownReason.RELOAD);
		if (restoreZenMode) {
			this.storageService.store(Workbench.zenModeActiveStorageKey, true, StorageScope.WORKSPACE);
		} else {
			if (this.zenMode.active) {
				this.toggleZenMode(true);
			}
			this.storageService.remove(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE);
		}

		this.workbenchShutdown = true;
	}

	//#region IPartService

	private _onTitleBarVisibilityChange: Emitter<void> = new Emitter<void>();
	get onTitleBarVisibilityChange(): Event<void> { return this._onTitleBarVisibilityChange.event; }

	get onEditorLayout(): Event<IDimension> { return this.editorPart.onDidLayout; }

	isCreated(): boolean {
		return this.workbenchCreated && this.workbenchStarted;
	}

	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}

		const container = this.getContainer(part);
		return DOM.isAncestor(activeElement, container);
	}

	getContainer(part: Parts): HTMLElement {
		let container: HTMLElement = null;
		switch (part) {
			case Parts.TITLEBAR_PART:
				container = this.titlebarPart.getContainer();
				break;
			case Parts.MENUBAR_PART:
				container = this.menubarPart.getContainer();
				break;
			case Parts.ACTIVITYBAR_PART:
				container = this.activitybarPart.getContainer();
				break;
			case Parts.SIDEBAR_PART:
				container = this.sidebarPart.getContainer();
				break;
			case Parts.PANEL_PART:
				container = this.panelPart.getContainer();
				break;
			case Parts.EDITOR_PART:
				container = this.editorPart.getContainer();
				break;
			case Parts.STATUSBAR_PART:
				container = this.statusbarPart.getContainer();
				break;
		}

		return container;
	}

	isVisible(part: Parts): boolean {
		switch (part) {
			case Parts.TITLEBAR_PART:
				return this.getCustomTitleBarStyle() && !browser.isFullscreen();
			case Parts.MENUBAR_PART:
1181
				return !this.menubarHidden;
B
Benjamin Pasero 已提交
1182 1183 1184 1185 1186 1187 1188 1189
			case Parts.SIDEBAR_PART:
				return !this.sideBarHidden;
			case Parts.PANEL_PART:
				return !this.panelHidden;
			case Parts.STATUSBAR_PART:
				return !this.statusBarHidden;
			case Parts.ACTIVITYBAR_PART:
				return !this.activityBarHidden;
E
Erich Gamma 已提交
1190
		}
B
Benjamin Pasero 已提交
1191 1192

		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1193 1194
	}

B
Benjamin Pasero 已提交
1195 1196 1197 1198
	getTitleBarOffset(): number {
		let offset = 0;
		if (this.isVisible(Parts.TITLEBAR_PART)) {
			offset = 22 / browser.getZoomFactor(); // adjust the position based on title bar size and zoom factor
E
Erich Gamma 已提交
1199
		}
B
Benjamin Pasero 已提交
1200 1201

		return offset;
E
Erich Gamma 已提交
1202
	}
1203

B
Benjamin Pasero 已提交
1204
	getWorkbenchElementId(): string {
1205 1206
		return Identifiers.WORKBENCH_CONTAINER;
	}
1207

B
Benjamin Pasero 已提交
1208
	toggleZenMode(skipLayout?: boolean): void {
I
isidor 已提交
1209
		this.zenMode.active = !this.zenMode.active;
B
Benjamin Pasero 已提交
1210
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1211

B
Benjamin Pasero 已提交
1212 1213
		// Check if zen mode transitioned to full screen and if now we are out of zen mode
		// -> we need to go out of full screen (same goes for the centered editor layout)
1214
		let toggleFullScreen = false;
B
Benjamin Pasero 已提交
1215 1216

		// Zen Mode Active
I
isidor 已提交
1217
		if (this.zenMode.active) {
1218
			const config = this.configurationService.getValue<IZenModeSettings>('zenMode');
B
Benjamin Pasero 已提交
1219

I
isidor 已提交
1220
			toggleFullScreen = !browser.isFullscreen() && config.fullScreen;
I
isidor 已提交
1221
			this.zenMode.transitionedToFullScreen = toggleFullScreen;
1222
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1223 1224
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
B
Benjamin Pasero 已提交
1225

1226 1227
			this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
			this.setSideBarHidden(true, true).done(void 0, errors.onUnexpectedError);
I
isidor 已提交
1228

1229 1230 1231
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1232

I
isidor 已提交
1233
			if (config.hideStatusBar) {
I
isidor 已提交
1234 1235
				this.setStatusBarHidden(true, true);
			}
1236

B
Benjamin Pasero 已提交
1237 1238
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1239
			}
1240 1241 1242 1243

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
B
Benjamin Pasero 已提交
1244 1245 1246 1247
		}

		// Zen Mode Inactive
		else {
1248
			if (this.zenMode.wasPanelVisible) {
1249
				this.setPanelHidden(false, true).done(void 0, errors.onUnexpectedError);
1250
			}
B
Benjamin Pasero 已提交
1251

1252
			if (this.zenMode.wasSideBarVisible) {
1253
				this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError);
1254
			}
B
Benjamin Pasero 已提交
1255

1256 1257 1258
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
1259

1260 1261
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
B
Benjamin Pasero 已提交
1262 1263

			this.editorGroupService.activeGroup.focus();
1264

1265
			toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen();
I
isidor 已提交
1266
		}
1267

1268
		this.inZenMode.set(this.zenMode.active);
I
isidor 已提交
1269

I
isidor 已提交
1270
		if (!skipLayout) {
1271
			this.layout();
I
isidor 已提交
1272
		}
1273

1274
		if (toggleFullScreen) {
1275
			this.windowService.toggleFullScreen().done(void 0, errors.onUnexpectedError);
1276
		}
I
isidor 已提交
1277 1278
	}

B
Benjamin Pasero 已提交
1279 1280 1281 1282 1283 1284 1285
	layout(options?: ILayoutOptions): void {
		if (this.workbenchStarted && !this.workbenchShutdown) {
			this.workbenchLayout.layout(options);
		}
	}

	isEditorLayoutCentered(): boolean {
B
Benjamin Pasero 已提交
1286
		return this.centeredEditorLayoutActive;
S
SrTobi 已提交
1287 1288
	}

B
Benjamin Pasero 已提交
1289 1290 1291 1292 1293 1294
	// TODO@ben support centered editor layout using empty groups or not? functionality missing:
	// - resize sashes left and right in sync
	// - IEditorInput.supportsCenteredEditorLayout() no longer supported
	// - should we just allow to enter layout even if groups > 1? what does it then mean to be
	//   actively in centered editor layout though?
	centerEditorLayout(active: boolean, skipLayout?: boolean): void {
1295
		this.centeredEditorLayoutActive = active;
1296
		this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, this.centeredEditorLayoutActive, StorageScope.WORKSPACE);
B
Benjamin Pasero 已提交
1297

B
Benjamin Pasero 已提交
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
		// Enter Centered Editor Layout
		if (active) {
			if (this.editorGroupService.count === 1) {
				const activeGroup = this.editorGroupService.activeGroup;
				this.editorGroupService.addGroup(activeGroup, GroupDirection.LEFT);
				this.editorGroupService.addGroup(activeGroup, GroupDirection.RIGHT);

				this.editorGroupService.applyLayout({ groups: [{ size: 0.2 }, { size: 0.6 }, { size: 0.2 }], orientation: GroupOrientation.HORIZONTAL });
			}
		}

		// Leave Centered Editor Layout
		else {
			if (this.editorGroupService.count === 3) {
				this.editorGroupService.groups.forEach(group => {
					if (group.count === 0) {
						this.editorGroupService.removeGroup(group);
					}
				});
			}
		}

1320 1321 1322
		if (!skipLayout) {
			this.layout();
		}
S
SrTobi 已提交
1323 1324
	}

B
Benjamin Pasero 已提交
1325
	resizePart(part: Parts, sizeChange: number): void {
1326 1327 1328 1329 1330 1331 1332
		switch (part) {
			case Parts.SIDEBAR_PART:
			case Parts.PANEL_PART:
			case Parts.EDITOR_PART:
				this.workbenchLayout.resizePart(part, sizeChange);
				break;
			default:
B
Benjamin Pasero 已提交
1333
				return; // Cannot resize other parts
1334 1335 1336
		}
	}

B
Benjamin Pasero 已提交
1337 1338
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1339

B
Benjamin Pasero 已提交
1340 1341 1342
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
1343
		}
B
Benjamin Pasero 已提交
1344
	}
1345

B
Benjamin Pasero 已提交
1346 1347 1348 1349 1350 1351 1352 1353 1354
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nosidebar');
		} else {
			this.workbench.removeClass('nosidebar');
1355 1356
		}

B
Benjamin Pasero 已提交
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
		// If sidebar becomes hidden, also hide the current active Viewlet if any
		let promise = TPromise.wrap<any>(null);
		if (hidden && this.sidebarPart.getActiveViewlet()) {
			promise = this.sidebarPart.hideActiveViewlet().then(() => {
				const activePanel = this.panelPart.getActivePanel();

				// Pass Focus to Editor or Panel if Sidebar is now hidden
				if (this.hasFocus(Parts.PANEL_PART) && activePanel) {
					activePanel.focus();
				} else {
					this.editorGroupService.activeGroup.focus();
				}
			});
		}

		// If sidebar becomes visible, show last active Viewlet or default viewlet
		else if (!hidden && !this.sidebarPart.getActiveViewlet()) {
			const viewletToOpen = this.sidebarPart.getLastActiveViewletId();
			if (viewletToOpen) {
				promise = this.viewletService.openViewlet(viewletToOpen, true)
					.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true));
			}
		}

		return promise.then(() => {

			// Remember in settings
			const defaultHidden = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY;
			if (hidden !== defaultHidden) {
				this.storageService.store(Workbench.sidebarHiddenStorageKey, hidden ? 'true' : 'false', StorageScope.WORKSPACE);
			} else {
				this.storageService.remove(Workbench.sidebarHiddenStorageKey, StorageScope.WORKSPACE);
			}

			// Layout
			if (!skipLayout) {
				this.workbenchLayout.layout();
			}
		});
1396
	}
B
Benjamin Pasero 已提交
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474

	setPanelHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.panelHidden = hidden;

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nopanel');
		} else {
			this.workbench.removeClass('nopanel');
		}

		// If panel part becomes hidden, also hide the current active panel if any
		let promise = TPromise.wrap<any>(null);
		if (hidden && this.panelPart.getActivePanel()) {
			promise = this.panelPart.hideActivePanel().then(() => {
				this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
			});
		}

		// If panel part becomes visible, show last active panel or default panel
		else if (!hidden && !this.panelPart.getActivePanel()) {
			const panelToOpen = this.panelPart.getLastActivePanelId();
			if (panelToOpen) {
				promise = this.panelPart.openPanel(panelToOpen, true);
			}
		}

		return promise.then(() => {

			// Remember in settings
			if (!hidden) {
				this.storageService.store(Workbench.panelHiddenStorageKey, 'false', StorageScope.WORKSPACE);
			} else {
				this.storageService.remove(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE);
			}

			// Layout
			if (!skipLayout) {
				this.workbenchLayout.layout();
			}
		});
	}

	toggleMaximizedPanel(): void {
		this.workbenchLayout.layout({ toggleMaximizedPanel: true, source: Parts.PANEL_PART });
	}

	isPanelMaximized(): boolean {
		return this.workbenchLayout.isPanelMaximized();
	}

	getSideBarPosition(): Position {
		return this.sideBarPosition;
	}

	setSideBarPosition(position: Position): void {
		if (this.sideBarHidden) {
			this.setSideBarHidden(false, true /* Skip Layout */).done(void 0, errors.onUnexpectedError);
		}

		const newPositionValue = (position === Position.LEFT) ? 'left' : 'right';
		const oldPositionValue = (this.sideBarPosition === Position.LEFT) ? 'left' : 'right';
		this.sideBarPosition = position;

		// Adjust CSS
		DOM.removeClass(this.activitybarPart.getContainer(), oldPositionValue);
		DOM.removeClass(this.sidebarPart.getContainer(), oldPositionValue);
		DOM.addClass(this.activitybarPart.getContainer(), newPositionValue);
		DOM.addClass(this.sidebarPart.getContainer(), newPositionValue);

		// Update Styles
		this.activitybarPart.updateStyles();
		this.sidebarPart.updateStyles();

		// Layout
		this.workbenchLayout.layout();
	}

1475 1476 1477 1478 1479 1480 1481 1482
	setMenubarHidden(visibility: string, skipLayout: boolean): void {
		this.menubarHidden = !(visibility === 'visible' || (visibility === 'default' && !browser.isFullscreen()));

		if (!skipLayout) {
			this.workbenchLayout.layout();
		}
	}

B
Benjamin Pasero 已提交
1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
	getPanelPosition(): Position {
		return this.panelPosition;
	}

	setPanelPosition(position: Position): TPromise<void> {
		return (this.panelHidden ? this.setPanelHidden(false, true /* Skip Layout */) : TPromise.as(undefined)).then(() => {
			const newPositionValue = (position === Position.BOTTOM) ? 'bottom' : 'right';
			const oldPositionValue = (this.panelPosition === Position.BOTTOM) ? 'bottom' : 'right';
			this.panelPosition = position;
			this.storageService.store(Workbench.panelPositionStorageKey, Position[this.panelPosition].toLowerCase(), StorageScope.WORKSPACE);

			// Adjust CSS
			DOM.removeClass(this.panelPart.getContainer(), oldPositionValue);
			DOM.addClass(this.panelPart.getContainer(), newPositionValue);

			// Update Styles
			this.panelPart.updateStyles();

			// Layout
			this.workbenchLayout.layout();
		});
	}

	//#endregion
}