workbench.ts 59.5 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';
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';
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';
B
Benjamin Pasero 已提交
20
import { BackupFileService, InMemoryBackupFileService } 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';
24
import { IResourceInput } from 'vs/platform/editor/common/editor';
J
Johannes Rieken 已提交
25
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
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';
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
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
S
SteVen Batten 已提交
45 46
import { ContextMenuService as NativeContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
import { ContextMenuService as HTMLContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
J
Johannes Rieken 已提交
47 48
import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
49
import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService';
50 51
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
J
Johannes Rieken 已提交
52
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
53 54
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
55
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
I
isidor 已提交
56
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
B
Benjamin Pasero 已提交
57
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
P
Pine Wu 已提交
58
import { ViewletService } from 'vs/workbench/services/viewlet/browser/viewletService';
59
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
J
Johannes Rieken 已提交
60 61
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
62
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService';
J
Johannes Rieken 已提交
63
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
B
Benjamin Pasero 已提交
64
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
J
Johannes Rieken 已提交
65
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
66 67
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
J
Johannes Rieken 已提交
68 69 70 71 72
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 已提交
73 74
import { ISCMService } from 'vs/workbench/services/scm/common/scm';
import { SCMService } from 'vs/workbench/services/scm/common/scmService';
75
import { IProgressService2 } from 'vs/workbench/services/progress/common/progress';
76
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
77
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
78
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
79
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
80
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
81
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
82
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath, MenuBarVisibility } from 'vs/platform/windows/common/windows';
J
Johannes Rieken 已提交
83
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
84
import { IMenuService, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
85
import { MenuService } from 'vs/workbench/services/actions/common/menuService';
S
SteVen Batten 已提交
86
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
J
Johannes Rieken 已提交
87
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
88
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
89
import { OpenRecentAction, ToggleDevToolsAction, ReloadWindowAction, ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions';
90
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
91
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
B
Benjamin Pasero 已提交
92
import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService';
93
import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService';
J
Johannes Rieken 已提交
94
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
I
isidor 已提交
95
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
B
Benjamin Pasero 已提交
96
import URI from 'vs/base/common/uri';
J
Joao Moreno 已提交
97
import { IListService, ListService } from 'vs/platform/list/browser/listService';
J
Joao Moreno 已提交
98
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
99
import { IViewsService } from 'vs/workbench/common/views';
S
Sandeep Somavarapu 已提交
100
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
101 102
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
103 104
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
105
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
106
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
107
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
J
Joao Moreno 已提交
108 109
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
S
Sandeep Somavarapu 已提交
110 111
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
112
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
I
isidor 已提交
113
import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection } from 'vs/workbench/services/group/common/editorGroupsService';
114
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
J
Joao Moreno 已提交
115
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler';
S
SteVen Batten 已提交
116
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
S
SteVen Batten 已提交
117 118
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
A
Alex Dima 已提交
119 120
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
121
import { IUriDisplayService, UriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
122

E
Erich Gamma 已提交
123
interface WorkbenchParams {
124
	configuration: IWindowConfiguration;
125
	serviceCollection: ServiceCollection;
E
Erich Gamma 已提交
126 127
}

I
isidor 已提交
128 129
interface IZenModeSettings {
	fullScreen: boolean;
130
	centerLayout: boolean;
I
isidor 已提交
131
	hideTabs: boolean;
132
	hideActivityBar: boolean;
I
isidor 已提交
133
	hideStatusBar: boolean;
I
isidor 已提交
134
	restore: boolean;
I
isidor 已提交
135 136
}

137 138 139
export interface IWorkbenchStartedInfo {
	customKeybindingsCount: number;
	pinnedViewlets: string[];
140
	restoredViewlet: string;
141
	restoredEditorsCount: number;
142 143
}

144 145
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';

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

148 149
const Identifiers = {
	WORKBENCH_CONTAINER: 'workbench.main.container',
B
Benjamin Pasero 已提交
150
	TITLEBAR_PART: 'workbench.parts.titlebar',
151 152 153 154
	ACTIVITYBAR_PART: 'workbench.parts.activitybar',
	SIDEBAR_PART: 'workbench.parts.sidebar',
	PANEL_PART: 'workbench.parts.panel',
	EDITOR_PART: 'workbench.parts.editor',
155 156
	STATUSBAR_PART: 'workbench.parts.statusbar',
	MENUBAR_PART: 'workbench.parts.menubar'
157 158
};

J
Joao Moreno 已提交
159 160 161 162 163 164 165 166
function getWorkbenchStateString(state: WorkbenchState): string {
	switch (state) {
		case WorkbenchState.EMPTY: return 'empty';
		case WorkbenchState.FOLDER: return 'folder';
		case WorkbenchState.WORKSPACE: return 'workspace';
	}
}

167 168 169 170 171 172 173 174 175 176
interface IZenMode {
	active: boolean;
	transitionedToFullScreen: boolean;
	transitionedToCenteredEditorLayout: boolean;
	transitionDisposeables: IDisposable[];
	wasSideBarVisible: boolean;
	wasPanelVisible: boolean;
}

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

178
	private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
179
	private static readonly menubarVisibilityConfigurationKey = 'window.menuBarVisibility';
180 181 182
	private static readonly sidebarRestoreStorageKey = 'workbench.sidebar.restore';
	private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
	private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
183
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
184
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
185
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
186 187 188 189 190
	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';
191

192
	_serviceBrand: any;
193

E
Erich Gamma 已提交
194 195 196 197 198
	private workbenchParams: WorkbenchParams;
	private workbench: Builder;
	private workbenchStarted: boolean;
	private workbenchCreated: boolean;
	private workbenchShutdown: boolean;
199

200 201
	private editorService: EditorService;
	private editorGroupService: IEditorGroupsService;
P
Pine Wu 已提交
202
	private viewletService: IViewletService;
J
Joao Moreno 已提交
203
	private contextViewService: ContextViewService;
204
	private contextKeyService: IContextKeyService;
205
	private keybindingService: IKeybindingService;
206
	private backupFileService: IBackupFileService;
207
	private fileService: IFileService;
208 209 210 211
	private quickInput: QuickInputService;

	private workbenchLayout: WorkbenchLayout;

B
Benjamin Pasero 已提交
212
	private titlebarPart: TitlebarPart;
213
	private menubarPart: MenubarPart;
E
Erich Gamma 已提交
214 215
	private activitybarPart: ActivitybarPart;
	private sidebarPart: SidebarPart;
I
isidor 已提交
216
	private panelPart: PanelPart;
E
Erich Gamma 已提交
217 218 219
	private editorPart: EditorPart;
	private statusbarPart: StatusbarPart;
	private quickOpen: QuickOpenController;
220
	private notificationsCenter: NotificationsCenter;
221
	private notificationsToasts: NotificationsToasts;
222

E
Erich Gamma 已提交
223
	private sideBarHidden: boolean;
224
	private statusBarHidden: boolean;
S
Sanders Lauture 已提交
225
	private activityBarHidden: boolean;
E
Erich Gamma 已提交
226
	private sideBarPosition: Position;
I
isidor 已提交
227
	private panelPosition: Position;
I
isidor 已提交
228
	private panelHidden: boolean;
S
SteVen Batten 已提交
229
	private menubarVisibility: MenuBarVisibility;
230 231
	private zenMode: IZenMode;
	private fontAliasing: FontAliasingOption;
232
	private hasInitialFilesToOpen: boolean;
233

I
isidor 已提交
234
	private inZenMode: IContextKey<boolean>;
235
	private sideBarVisibleContext: IContextKey<boolean>;
236

B
Benjamin Pasero 已提交
237
	private closeEmptyWindowScheduler: RunOnceScheduler = this._register(new RunOnceScheduler(() => this.onAllEditorsClosed(), 50));
E
Erich Gamma 已提交
238

239
	constructor(
240
		private container: HTMLElement,
J
Joao Moreno 已提交
241
		private configuration: IWindowConfiguration,
242
		serviceCollection: ServiceCollection,
243
		private lifecycleService: LifecycleService,
J
Joao Moreno 已提交
244
		private mainProcessClient: IPCClient,
245
		@IInstantiationService private instantiationService: IInstantiationService,
246
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
247
		@IStorageService private storageService: IStorageService,
248
		@IConfigurationService private configurationService: WorkspaceService,
A
Alex Dima 已提交
249
		@IWorkbenchThemeService private themeService: WorkbenchThemeService,
I
isidor 已提交
250
		@IEnvironmentService private environmentService: IEnvironmentService,
251
		@IWindowService private windowService: IWindowService,
S
SteVen Batten 已提交
252
		@INotificationService private notificationService: NotificationService,
S
SteVen Batten 已提交
253
		@ITelemetryService private telemetryService: TelemetryService
254
	) {
255
		super();
E
Erich Gamma 已提交
256

257
		this.workbenchParams = { configuration, serviceCollection };
E
Erich Gamma 已提交
258

259
		this.hasInitialFilesToOpen =
B
Benjamin Pasero 已提交
260 261 262
			(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
			(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
			(configuration.filesToDiff && configuration.filesToDiff.length > 0);
263 264
	}

265
	startup(): TPromise<IWorkbenchStartedInfo> {
266
		this.workbenchStarted = true;
E
Erich Gamma 已提交
267

B
Benjamin Pasero 已提交
268
		// Create Workbench Container
269
		this.createWorkbench();
E
Erich Gamma 已提交
270

271 272
		// Install some global actions
		this.createGlobalActions();
273

274 275
		// Services
		this.initServices();
E
Erich Gamma 已提交
276

277 278
		// Context Keys
		this.handleContextKeys();
J
Joao Moreno 已提交
279

280 281
		// Register Listeners
		this.registerListeners();
E
Erich Gamma 已提交
282

283 284
		// Settings
		this.initSettings();
E
Erich Gamma 已提交
285

286 287
		// Create Workbench and Parts
		this.renderWorkbench();
288

289 290
		// Workbench Layout
		this.createWorkbenchLayout();
B
polish  
Benjamin Pasero 已提交
291

J
Joao Moreno 已提交
292 293
		// Driver
		if (this.environmentService.driverHandle) {
294
			registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService).then(disposable => this._register(disposable));
J
Joao Moreno 已提交
295 296
		}

297
		// Restore Parts
B
Benjamin Pasero 已提交
298 299
		return this.restoreParts();
	}
300

B
Benjamin Pasero 已提交
301 302 303 304
	private createWorkbench(): void {
		this.workbench = $().div({
			'class': `monaco-workbench ${isWindows ? 'windows' : isLinux ? 'linux' : 'mac'}`,
			id: Identifiers.WORKBENCH_CONTAINER
J
Joao Moreno 已提交
305
		});
306
	}
E
Erich Gamma 已提交
307

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

B
Benjamin Pasero 已提交
311
		// Actions registered here to adjust for developing vs built workbench
312 313 314 315 316
		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');
317

318
		// Actions for macOS native tabs management (only when enabled)
319
		const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
320
		if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) {
321 322 323 324 325
			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');
326
		}
327 328
	}

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

E
Erich Gamma 已提交
332
		// Services we contribute
333
		serviceCollection.set(IPartService, this);
E
Erich Gamma 已提交
334

335 336 337
		// Clipboard
		serviceCollection.set(IClipboardService, new ClipboardService());

338
		// Uri Display
339 340 341
		const uriDisplayService = new UriDisplayService(this.environmentService, this.contextService);
		serviceCollection.set(IUriDisplayService, uriDisplayService);
		this.configurationService.acquireUriDisplayService(uriDisplayService);
342

343 344
		// Status bar
		this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
345
		this._register(toDisposable(() => this.statusbarPart.shutdown()));
346 347
		serviceCollection.set(IStatusbarService, this.statusbarPart);

348 349 350
		// Progress 2
		serviceCollection.set(IProgressService2, new SyncDescriptor(ProgressService2));

351
		// Keybindings
A
Alex Dima 已提交
352
		this.contextKeyService = this.instantiationService.createInstance(ContextKeyService);
353
		serviceCollection.set(IContextKeyService, this.contextKeyService);
354

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

358 359 360
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

J
Joao Moreno 已提交
361 362 363 364
		// Context view service
		this.contextViewService = this.instantiationService.createInstance(ContextViewService, this.workbench.getHTMLElement());
		serviceCollection.set(IContextViewService, this.contextViewService);

S
SteVen Batten 已提交
365
		// Use themable context menus when custom titlebar is enabled to match custom menubar
B
Benjamin Pasero 已提交
366
		if (!isMacintosh && this.getCustomTitleBarStyle() === 'custom') {
S
SteVen Batten 已提交
367
			serviceCollection.set(IContextMenuService, new SyncDescriptor(HTMLContextMenuService, null, this.telemetryService, this.notificationService, this.contextViewService));
S
SteVen Batten 已提交
368 369 370
		} else {
			serviceCollection.set(IContextMenuService, new SyncDescriptor(NativeContextMenuService));
		}
371

372 373
		// Menus/Actions
		serviceCollection.set(IMenuService, new SyncDescriptor(MenuService));
374

P
Pine Wu 已提交
375
		// Sidebar part
376
		this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
377
		this._register(toDisposable(() => this.sidebarPart.shutdown()));
P
Pine Wu 已提交
378 379 380 381

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

I
isidor 已提交
383
		// Panel service (panel part)
384
		this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
385
		this._register(toDisposable(() => this.panelPart.shutdown()));
386
		serviceCollection.set(IPanelService, this.panelPart);
I
isidor 已提交
387

388 389 390
		// views service
		const viewsService = this.instantiationService.createInstance(ViewsService);
		serviceCollection.set(IViewsService, viewsService);
S
Sandeep Somavarapu 已提交
391

E
Erich Gamma 已提交
392
		// Activity service (activitybar part)
393
		this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
394
		this._register(toDisposable(() => this.activitybarPart.shutdown()));
I
isidor 已提交
395 396
		const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
		serviceCollection.set(IActivityService, activityService);
E
Erich Gamma 已提交
397

398 399 400
		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
S
#47154  
Sandeep Somavarapu 已提交
401
		this.configurationService.acquireFileService(this.fileService);
A
Alex Dima 已提交
402
		this.themeService.acquireFileService(this.fileService);
403

404 405
		// Editor and Group services
		const restorePreviousEditorState = !this.hasInitialFilesToOpen;
406
		this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
407
		this._register(toDisposable(() => this.editorPart.shutdown()));
B
Benjamin Pasero 已提交
408
		this.editorGroupService = this.editorPart;
409 410 411
		serviceCollection.set(IEditorGroupsService, this.editorPart);
		this.editorService = this.instantiationService.createInstance(EditorService);
		serviceCollection.set(IEditorService, this.editorService);
E
Erich Gamma 已提交
412

413 414
		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
415
		this._register(toDisposable(() => this.titlebarPart.shutdown()));
416
		serviceCollection.set(ITitleService, this.titlebarPart);
B
Benjamin Pasero 已提交
417

418
		// History
419
		serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService));
420

B
Benjamin Pasero 已提交
421 422 423
		// Menubar
		this.menubarPart = this.instantiationService.createInstance(MenubarPart, Identifiers.MENUBAR_PART);

424
		// Backup File Service
B
Benjamin Pasero 已提交
425 426 427 428 429
		if (this.workbenchParams.configuration.backupPath) {
			this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.workbenchParams.configuration.backupPath);
		} else {
			this.backupFileService = new InMemoryBackupFileService();
		}
430
		serviceCollection.set(IBackupFileService, this.backupFileService);
431

432
		// Text File Service
433
		serviceCollection.set(ITextFileService, new SyncDescriptor(TextFileService));
434

435
		// File Decorations
J
Johannes Rieken 已提交
436
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));
437

J
Joao Moreno 已提交
438
		// SCM Service
439
		serviceCollection.set(ISCMService, new SyncDescriptor(SCMService));
440

J
Joao Moreno 已提交
441
		// Inactive extension URL handler
J
Joao Moreno 已提交
442
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));
J
Joao Moreno 已提交
443

B
Benjamin Pasero 已提交
444
		// Text Model Resolver Service
445
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));
B
Benjamin Pasero 已提交
446

447 448 449 450
		// JSON Editing
		const jsonEditingService = this.instantiationService.createInstance(JSONEditingService);
		serviceCollection.set(IJSONEditingService, jsonEditingService);

451 452 453
		// Workspace Editing
		serviceCollection.set(IWorkspaceEditingService, new SyncDescriptor(WorkspaceEditingService));

454 455 456
		// Keybinding Editing
		serviceCollection.set(IKeybindingEditingService, this.instantiationService.createInstance(KeybindingsEditingService));

457
		// Configuration Resolver
B
Benjamin Pasero 已提交
458
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, process.env));
459

E
Erich Gamma 已提交
460
		// Quick open service (quick open controller)
461
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
462
		this._register(toDisposable(() => this.quickOpen.shutdown()));
463
		serviceCollection.set(IQuickOpenService, this.quickOpen);
464

C
Christof Marti 已提交
465 466
		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
467
		this._register(toDisposable(() => this.quickInput.shutdown()));
C
Christof Marti 已提交
468 469
		serviceCollection.set(IQuickInputService, this.quickInput);

S
Sandeep Somavarapu 已提交
470 471 472
		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

B
polish  
Benjamin Pasero 已提交
473
		// Contributed services
B
Benjamin Pasero 已提交
474
		const contributedServices = getServices();
E
Erich Gamma 已提交
475
		for (let contributedService of contributedServices) {
476
			serviceCollection.set(contributedService.id, contributedService.descriptor);
E
Erich Gamma 已提交
477 478 479
		}

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

484
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
485

S
#47154  
Sandeep Somavarapu 已提交
486
		this.configurationService.acquireInstantiationService(this.getInstantiationService());
E
Erich Gamma 已提交
487 488
	}

489
	//#region event handling
E
Erich Gamma 已提交
490

491
	private registerListeners(): void {
I
isidor 已提交
492

493
		// Listen to visible editor changes
494
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
B
Benjamin Pasero 已提交
495

496 497 498 499 500
		// 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);
501
			const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
I
isidor 已提交
502

503
			this._register(listenerDispose);
504
		}
S
Sanders Lauture 已提交
505

506
		// Configuration changes
507
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
I
isidor 已提交
508

509
		// Fullscreen changes
510
		this._register(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
511
	}
512

513 514 515 516
	private onFullscreenChanged(): void {
		if (!this.isCreated) {
			return; // we need to be ready
		}
S
SrTobi 已提交
517

518 519 520 521 522 523 524 525 526 527
		// 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();
			}
		}
E
Erich Gamma 已提交
528

529 530 531 532 533 534
		// 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
		}
535 536
	}

537
	private onEditorClosed(listenerDispose: IDisposable, resourcesToWaitFor: URI[], waitMarkerFile: URI): void {
E
Erich Gamma 已提交
538

539 540 541
		// 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.
542
		if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
543 544 545
			listenerDispose.dispose();
			this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError);
		}
E
Erich Gamma 已提交
546 547
	}

548
	private onDidVisibleEditorsChange(): void {
549
		const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
550

551 552 553 554 555 556 557 558 559
		// 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();
			}
		}
560 561
	}

562
	private onAllEditorsClosed(): void {
563
		const visibleEditors = this.editorService.visibleControls.length;
564 565
		if (visibleEditors === 0) {
			this.windowService.closeWindow();
E
Erich Gamma 已提交
566 567 568
		}
	}

569 570 571 572 573
	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);
574
		}
E
Erich Gamma 已提交
575

576
		this.setPanelPositionFromStorageOrConfig();
E
Erich Gamma 已提交
577

578 579 580
		const fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
		if (fontAliasing !== this.fontAliasing) {
			this.setFontAliasing(fontAliasing);
581 582
		}

583 584 585 586 587
		if (!this.zenMode.active) {
			const newStatusbarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.statusbarVisibleConfigurationKey);
			if (newStatusbarHiddenValue !== this.statusBarHidden) {
				this.setStatusBarHidden(newStatusbarHiddenValue, skipLayout);
			}
588

589 590 591 592
			const newActivityBarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.activityBarVisibleConfigurationKey);
			if (newActivityBarHiddenValue !== this.activityBarHidden) {
				this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout);
			}
B
Benjamin Pasero 已提交
593
		}
S
SteVen Batten 已提交
594

595
		const newMenubarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
S
SteVen Batten 已提交
596
		this.setMenubarVisibility(newMenubarVisibility, skipLayout);
597
	}
B
Benjamin Pasero 已提交
598

599
	//#endregion
B
Benjamin Pasero 已提交
600

601 602
	private handleContextKeys(): void {
		this.inZenMode = InEditorZenModeContext.bindTo(this.contextKeyService);
603

604 605
		const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
		this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);
606

607 608 609 610
		const editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
		const textCompareEditorVisible = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
		const activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
		const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
611

612
		const updateEditorContextKeys = () => {
613
			const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
614

615
			textCompareEditorVisible.set(visibleEditors.some(control => control.getId() === TEXT_DIFF_EDITOR_ID));
I
isidor 已提交
616

617 618 619 620
			if (visibleEditors.length > 0) {
				editorsVisibleContext.set(true);
			} else {
				editorsVisibleContext.reset();
621
			}
B
Benjamin Pasero 已提交
622

623
			if (!this.editorService.activeEditor) {
624 625 626
				activeEditorGroupEmpty.set(true);
			} else {
				activeEditorGroupEmpty.reset();
627
			}
628

B
Benjamin Pasero 已提交
629
			if (this.editorGroupService.count > 1) {
630 631 632 633 634
				multipleEditorGroups.set(true);
			} else {
				multipleEditorGroups.reset();
			}
		};
B
Benjamin Pasero 已提交
635

636
		this.editorPart.whenRestored.then(() => updateEditorContextKeys());
637 638
		this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
		this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
B
Benjamin Pasero 已提交
639 640
		this._register(this.editorGroupService.onDidAddGroup(() => updateEditorContextKeys()));
		this._register(this.editorGroupService.onDidRemoveGroup(() => updateEditorContextKeys()));
641

642 643 644 645 646 647 648 649 650 651
		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 已提交
652

653 654 655 656 657
		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);
		}));
658

659
		const splitEditorsVerticallyContext = SplitEditorsVertically.bindTo(this.contextKeyService);
S
Sanders Lauture 已提交
660

661 662 663 664
		const updateSplitEditorsVerticallyContext = () => {
			const direction = preferredSideBySideGroupDirection(this.configurationService);
			splitEditorsVerticallyContext.set(direction === GroupDirection.DOWN);
		};
S
Sanders Lauture 已提交
665

666 667 668 669 670
		this._register(this.configurationService.onDidChangeConfiguration(e => {
			if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) {
				updateSplitEditorsVerticallyContext();
			}
		}));
E
Erich Gamma 已提交
671

672
		updateSplitEditorsVerticallyContext();
673
	}
E
Erich Gamma 已提交
674

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

678 679
		// Restore Editorpart
		perf.mark('willRestoreEditors');
680
		restorePromises.push(this.editorPart.whenRestored.then(() => {
681 682
			return this.resolveEditorsToOpen().then(inputs => {
				if (inputs.length) {
683
					return this.editorService.openEditors(inputs);
684
				}
E
Erich Gamma 已提交
685

686 687 688 689 690
				return TPromise.as(void 0);
			});
		}).then(() => {
			perf.mark('didRestoreEditors');
		}));
E
Erich Gamma 已提交
691

692 693 694 695
		// Restore Sidebar
		let viewletIdToRestore: string;
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);
696

697 698
			if (this.shouldRestoreLastOpenedViewlet()) {
				viewletIdToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE);
699
			}
700

701 702
			if (!viewletIdToRestore) {
				viewletIdToRestore = this.viewletService.getDefaultViewletId();
703
			}
E
Erich Gamma 已提交
704

705
			perf.mark('willRestoreViewlet');
706 707 708 709 710
			restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore)
				.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId()))
				.then(() => {
					perf.mark('didRestoreViewlet');
				}));
711 712
		}

713 714 715 716
		// Restore Panel
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
		const panelId = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
		if (!this.panelHidden && !!panelId) {
717 718 719 720 721 722
			const isPanelToRestoreEnabled = !!this.panelPart.getPanels().filter(p => p.id === panelId).length;
			if (isPanelToRestoreEnabled) {
				restorePromises.push(this.panelPart.openPanel(panelId, false));
			} else {
				restorePromises.push(this.panelPart.openPanel(panelRegistry.getDefaultPanelId(), false));
			}
I
isidor 已提交
723 724
		}

725
		// Restore Zen Mode if active
I
isidor 已提交
726
		if (this.storageService.getBoolean(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE, false)) {
I
isidor 已提交
727
			this.toggleZenMode(true, true);
I
isidor 已提交
728 729
		}

B
Benjamin Pasero 已提交
730
		// Restore Forced Editor Center Mode
731
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
I
isidor 已提交
732
			this.centerEditorLayout(true);
S
SrTobi 已提交
733
		}
734

735
		const onRestored = (error?: Error): IWorkbenchStartedInfo => {
B
Benjamin Pasero 已提交
736
			this.workbenchCreated = true;
737

738 739
			if (error) {
				errors.onUnexpectedError(error);
740
			}
I
isidor 已提交
741

742 743 744 745
			return {
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
				pinnedViewlets: this.activitybarPart.getPinned(),
				restoredViewlet: viewletIdToRestore,
746
				restoredEditorsCount: this.editorService.visibleEditors.length
747 748
			};
		};
749

750
		return TPromise.join(restorePromises).then(() => onRestored(), error => onRestored(error));
E
Erich Gamma 已提交
751 752
	}

753 754 755
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
E
Erich Gamma 已提交
756 757
		}

758 759 760 761
		const restore = this.storageService.getBoolean(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE);
		if (restore) {
			this.storageService.remove(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE); // only support once
		}
762

763
		return restore;
E
Erich Gamma 已提交
764 765
	}

766
	private resolveEditorsToOpen(): TPromise<IResourceEditor[]> {
767
		const config = this.workbenchParams.configuration;
I
isidor 已提交
768

B
Benjamin Pasero 已提交
769
		// Files to open, diff or create
770
		if (this.hasInitialFilesToOpen) {
I
isidor 已提交
771

B
Benjamin Pasero 已提交
772
			// Files to diff is exclusive
773
			const filesToDiff = this.toInputs(config.filesToDiff, false);
774
			if (filesToDiff && filesToDiff.length === 2) {
775 776 777 778 779
				return TPromise.as([<IResourceDiffInput>{
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
					options: { pinned: true }
				}]);
B
Benjamin Pasero 已提交
780
			}
I
isidor 已提交
781

782 783
			const filesToCreate = this.toInputs(config.filesToCreate, true);
			const filesToOpen = this.toInputs(config.filesToOpen, false);
I
isidor 已提交
784

785 786
			// Otherwise: Open/Create files
			return TPromise.as([...filesToOpen, ...filesToCreate]);
B
Benjamin Pasero 已提交
787
		}
I
isidor 已提交
788

789
		// Empty workbench
790
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
B
Benjamin Pasero 已提交
791
			const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
792 793
			if (!isEmpty) {
				return TPromise.as([]); // do not open any empty untitled file if we restored editors from previous session
794
			}
B
Benjamin Pasero 已提交
795

796 797 798 799
			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 已提交
800

801
				return TPromise.as([<IUntitledResourceInput>{}]);
802
			});
803
		}
804

B
Benjamin Pasero 已提交
805 806
		return TPromise.as([]);
	}
807

808
	private toInputs(paths: IPath[], isNew: boolean): (IResourceInput | IUntitledResourceInput)[] {
B
Benjamin Pasero 已提交
809 810
		if (!paths || !paths.length) {
			return [];
811
		}
I
isidor 已提交
812

B
Benjamin Pasero 已提交
813
		return paths.map(p => {
814 815 816 817 818 819
			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;
820
			}
E
Erich Gamma 已提交
821

822
			if (!isNew && p.lineNumber) {
B
Benjamin Pasero 已提交
823 824 825 826 827
				input.options.selection = {
					startLineNumber: p.lineNumber,
					startColumn: p.columnNumber
				};
			}
828

B
Benjamin Pasero 已提交
829 830
			return input;
		});
831 832
	}

833
	private openUntitledFile() {
834
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');
B
Benjamin Pasero 已提交
835 836

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

844
		return startupEditor.value === 'newUntitledFile';
845
	}
E
Erich Gamma 已提交
846 847

	private initSettings(): void {
848

E
Erich Gamma 已提交
849
		// Sidebar visibility
I
isidor 已提交
850
		this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenStorageKey, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY);
851

I
isidor 已提交
852
		// Panel part visibility
853
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
I
isidor 已提交
854
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
855 856
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
857 858
		}

E
Erich Gamma 已提交
859
		// Sidebar position
860
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
861
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
862

I
isidor 已提交
863
		// Panel position
864
		this.setPanelPositionFromStorageOrConfig();
865

866
		// Menubar visibility
867
		const menuBarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
S
SteVen Batten 已提交
868
		this.setMenubarVisibility(menuBarVisibility, true);
869

B
Benjamin Pasero 已提交
870
		// Statusbar visibility
871
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
872
		this.statusBarHidden = !statusBarVisible;
873

S
Sanders Lauture 已提交
874
		// Activity bar visibility
875
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
S
Sanders Lauture 已提交
876
		this.activityBarHidden = !activityBarVisible;
877

878
		// Font aliasing
879
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
880

I
isidor 已提交
881 882
		// Zen mode
		this.zenMode = {
I
isidor 已提交
883
			active: false,
884
			transitionedToFullScreen: false,
885
			transitionedToCenteredEditorLayout: false,
886
			wasSideBarVisible: false,
887 888
			wasPanelVisible: false,
			transitionDisposeables: []
I
isidor 已提交
889
		};
E
Erich Gamma 已提交
890 891
	}

892 893 894 895 896
	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;
	}
897

898 899
	private getCustomTitleBarStyle(): 'custom' {
		const isDev = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
B
Benjamin Pasero 已提交
900
		if (isMacintosh && isDev) {
901 902
			return null; // not enabled when developing due to https://github.com/electron/electron/issues/3647
		}
E
Erich Gamma 已提交
903

904 905 906 907 908 909 910 911 912 913
		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
			}

			const style = windowConfig.window.titleBarStyle;
			if (style === 'custom') {
				return style;
914 915 916
			}
		}

917
		return null;
B
Benjamin Pasero 已提交
918 919
	}

920 921
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
922

923 924 925
		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nostatusbar');
E
Erich Gamma 已提交
926
		} else {
927
			this.workbench.removeClass('nostatusbar');
E
Erich Gamma 已提交
928 929
		}

930 931 932
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
933 934 935
		}
	}

936
	private setFontAliasing(aliasing: FontAliasingOption) {
937
		this.fontAliasing = aliasing;
S
Sanders Lauture 已提交
938

B
Benjamin Pasero 已提交
939 940 941 942 943
		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
944
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
945
		}
946 947
	}

E
Erich Gamma 已提交
948
	private createWorkbenchLayout(): void {
949 950
		this.workbenchLayout = this.instantiationService.createInstance(
			WorkbenchLayout,
951 952
			this.container,
			this.workbench.getHTMLElement(),
I
isidor 已提交
953
			{
954
				titlebar: this.titlebarPart,
B
Benjamin Pasero 已提交
955
				menubar: this.menubarPart,
956 957 958 959 960
				activitybar: this.activitybarPart,
				editor: this.editorPart,
				sidebar: this.sidebarPart,
				panel: this.panelPart,
				statusbar: this.statusbarPart,
I
isidor 已提交
961
			},
962 963 964 965
			this.quickOpen,
			this.quickInput,
			this.notificationsCenter,
			this.notificationsToasts
E
Erich Gamma 已提交
966 967 968 969 970 971 972 973 974
		);
	}

	private renderWorkbench(): void {

		// Apply sidebar state as CSS class
		if (this.sideBarHidden) {
			this.workbench.addClass('nosidebar');
		}
975 976 977
		if (this.panelHidden) {
			this.workbench.addClass('nopanel');
		}
978 979 980
		if (this.statusBarHidden) {
			this.workbench.addClass('nostatusbar');
		}
E
Erich Gamma 已提交
981

B
Benjamin Pasero 已提交
982
		// Apply font aliasing
983 984
		this.setFontAliasing(this.fontAliasing);

985 986 987
		// Apply fullscreen state
		if (browser.isFullscreen()) {
			this.workbench.addClass('fullscreen');
B
Benjamin Pasero 已提交
988 989
		}

E
Erich Gamma 已提交
990
		// Create Parts
B
Benjamin Pasero 已提交
991
		this.createTitlebarPart();
992
		this.createMenubarPart();
E
Erich Gamma 已提交
993 994 995
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
996
		this.createPanelPart();
E
Erich Gamma 已提交
997 998
		this.createStatusbarPart();

999 1000
		// Notification Handlers
		this.createNotificationsHandlers();
1001

E
Erich Gamma 已提交
1002
		// Add Workbench to DOM
J
Joao Moreno 已提交
1003
		this.workbench.appendTo(this.container);
E
Erich Gamma 已提交
1004 1005
	}

B
Benjamin Pasero 已提交
1006 1007 1008 1009 1010 1011 1012
	private createTitlebarPart(): void {
		const titlebarContainer = $(this.workbench).div({
			'class': ['part', 'titlebar'],
			id: Identifiers.TITLEBAR_PART,
			role: 'contentinfo'
		});

1013
		this.titlebarPart.create(titlebarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
1014 1015
	}

1016
	private createMenubarPart(): void {
1017 1018 1019 1020 1021
		const menubarContainer = $(this.workbench).div({
			'class': ['part', 'menubar'],
			id: Identifiers.MENUBAR_PART,
			role: 'menubar'
		});
B
Benjamin Pasero 已提交
1022

1023
		this.menubarPart.create(menubarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
1024 1025

		this._register(this.menubarPart.onVisibilityChange((dimension => {
1026
			this._onMenubarVisibilityChange.fire(dimension);
B
Benjamin Pasero 已提交
1027
		})));
1028 1029
	}

E
Erich Gamma 已提交
1030
	private createActivityBarPart(): void {
B
Benjamin Pasero 已提交
1031
		const activitybarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
1032 1033
			.div({
				'class': ['part', 'activitybar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
1034 1035
				id: Identifiers.ACTIVITYBAR_PART,
				role: 'navigation'
E
Erich Gamma 已提交
1036 1037
			});

1038
		this.activitybarPart.create(activitybarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1039 1040 1041
	}

	private createSidebarPart(): void {
B
Benjamin Pasero 已提交
1042
		const sidebarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
1043 1044
			.div({
				'class': ['part', 'sidebar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
1045 1046
				id: Identifiers.SIDEBAR_PART,
				role: 'complementary'
E
Erich Gamma 已提交
1047 1048
			});

1049
		this.sidebarPart.create(sidebarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1050 1051
	}

I
isidor 已提交
1052
	private createPanelPart(): void {
B
Benjamin Pasero 已提交
1053
		const panelPartContainer = $(this.workbench)
I
isidor 已提交
1054
			.div({
1055
				'class': ['part', 'panel', this.panelPosition === Position.BOTTOM ? 'bottom' : 'right'],
1056 1057
				id: Identifiers.PANEL_PART,
				role: 'complementary'
I
isidor 已提交
1058 1059
			});

1060
		this.panelPart.create(panelPartContainer.getHTMLElement());
I
isidor 已提交
1061 1062
	}

E
Erich Gamma 已提交
1063
	private createEditorPart(): void {
B
Benjamin Pasero 已提交
1064
		const editorContainer = $(this.workbench)
E
Erich Gamma 已提交
1065
			.div({
1066
				'class': ['part', 'editor'],
1067 1068
				id: Identifiers.EDITOR_PART,
				role: 'main'
E
Erich Gamma 已提交
1069 1070
			});

1071
		this.editorPart.create(editorContainer.getHTMLElement());
E
Erich Gamma 已提交
1072 1073 1074
	}

	private createStatusbarPart(): void {
B
Benjamin Pasero 已提交
1075
		const statusbarContainer = $(this.workbench).div({
E
Erich Gamma 已提交
1076
			'class': ['part', 'statusbar'],
1077 1078
			id: Identifiers.STATUSBAR_PART,
			role: 'contentinfo'
E
Erich Gamma 已提交
1079 1080
		});

1081
		this.statusbarPart.create(statusbarContainer.getHTMLElement());
E
Erich Gamma 已提交
1082 1083
	}

1084 1085
	private createNotificationsHandlers(): void {

1086
		// Notifications Center
1087
		this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench.getHTMLElement(), this.notificationService.model));
1088

1089
		// Notifications Toasts
1090
		this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench.getHTMLElement(), this.notificationService.model));
1091

1092
		// Notifications Alerts
1093
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1094 1095 1096 1097

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

1098
		// Eventing
1099
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1100 1101 1102 1103 1104 1105 1106 1107

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

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

1108
		// Register Commands
1109
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1110 1111
	}

1112
	getInstantiationService(): IInstantiationService {
E
Erich Gamma 已提交
1113 1114 1115
		return this.instantiationService;
	}

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
	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

B
Benjamin Pasero 已提交
1141
	private _onTitleBarVisibilityChange: Emitter<void> = this._register(new Emitter<void>());
1142
	get onTitleBarVisibilityChange(): Event<void> { return this._onTitleBarVisibilityChange.event; }
1143

B
Benjamin Pasero 已提交
1144
	private _onMenubarVisibilityChange: Emitter<DOM.Dimension> = this._register(new Emitter<DOM.Dimension>());
1145 1146
	get onMenubarVisibilityChange(): Event<DOM.Dimension> { return this._onMenubarVisibilityChange.event; }

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

1149 1150 1151
	isCreated(): boolean {
		return this.workbenchCreated && this.workbenchStarted;
	}
1152

1153 1154 1155 1156 1157
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1158

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

1163 1164 1165 1166 1167 1168
	getContainer(part: Parts): HTMLElement {
		let container: HTMLElement = null;
		switch (part) {
			case Parts.TITLEBAR_PART:
				container = this.titlebarPart.getContainer();
				break;
B
Benjamin Pasero 已提交
1169 1170 1171
			case Parts.MENUBAR_PART:
				container = this.menubarPart.getContainer();
				break;
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
			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;
		}
1188

1189 1190
		return container;
	}
1191

1192 1193 1194
	isVisible(part: Parts): boolean {
		switch (part) {
			case Parts.TITLEBAR_PART:
B
Benjamin Pasero 已提交
1195
				return this.getCustomTitleBarStyle() === 'custom' && !browser.isFullscreen();
B
Benjamin Pasero 已提交
1196
			case Parts.MENUBAR_PART:
S
SteVen Batten 已提交
1197
				return !isMacintosh && this.isVisible(Parts.TITLEBAR_PART) && !(this.menubarVisibility === 'hidden' || (this.menubarVisibility === 'default' && browser.isFullscreen()));
1198 1199 1200 1201 1202 1203 1204 1205
			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 已提交
1206
		}
1207

1208
		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1209 1210
	}

1211 1212 1213
	getTitleBarOffset(): number {
		let offset = 0;
		if (this.isVisible(Parts.TITLEBAR_PART)) {
S
SteVen Batten 已提交
1214
			offset = this.workbenchLayout.partLayoutInfo.titlebar.height;
E
Erich Gamma 已提交
1215
		}
1216 1217

		return offset;
E
Erich Gamma 已提交
1218
	}
1219

1220
	getWorkbenchElementId(): string {
1221 1222
		return Identifiers.WORKBENCH_CONTAINER;
	}
1223

I
isidor 已提交
1224
	toggleZenMode(skipLayout?: boolean, restoring = false): void {
I
isidor 已提交
1225
		this.zenMode.active = !this.zenMode.active;
1226
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1227

1228 1229
		// 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)
1230
		let toggleFullScreen = false;
1231 1232

		// Zen Mode Active
I
isidor 已提交
1233
		if (this.zenMode.active) {
1234
			const config = this.configurationService.getValue<IZenModeSettings>('zenMode');
1235

I
isidor 已提交
1236
			toggleFullScreen = !browser.isFullscreen() && config.fullScreen;
I
isidor 已提交
1237
			this.zenMode.transitionedToFullScreen = restoring ? config.fullScreen : toggleFullScreen;
1238
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1239 1240
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
1241

1242 1243
			this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
			this.setSideBarHidden(true, true).done(void 0, errors.onUnexpectedError);
I
isidor 已提交
1244

1245 1246 1247
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1248

I
isidor 已提交
1249
			if (config.hideStatusBar) {
I
isidor 已提交
1250 1251
				this.setStatusBarHidden(true, true);
			}
1252

1253 1254
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1255
			}
1256 1257 1258 1259

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1260 1261 1262 1263
		}

		// Zen Mode Inactive
		else {
1264
			if (this.zenMode.wasPanelVisible) {
1265
				this.setPanelHidden(false, true).done(void 0, errors.onUnexpectedError);
1266
			}
1267

1268
			if (this.zenMode.wasSideBarVisible) {
1269
				this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError);
1270
			}
1271

1272 1273 1274
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
1275

1276 1277
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1278

B
Benjamin Pasero 已提交
1279
			this.editorGroupService.activeGroup.focus();
1280

1281
			toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen();
I
isidor 已提交
1282
		}
1283

1284
		this.inZenMode.set(this.zenMode.active);
I
isidor 已提交
1285

I
isidor 已提交
1286
		if (!skipLayout) {
1287
			this.layout();
I
isidor 已提交
1288
		}
1289

1290
		if (toggleFullScreen) {
1291
			this.windowService.toggleFullScreen().done(void 0, errors.onUnexpectedError);
1292
		}
I
isidor 已提交
1293 1294
	}

1295
	layout(options?: ILayoutOptions): void {
J
Joao Moreno 已提交
1296 1297
		this.contextViewService.layout();

1298 1299 1300 1301 1302
		if (this.workbenchStarted && !this.workbenchShutdown) {
			this.workbenchLayout.layout(options);
		}
	}

1303
	isEditorLayoutCentered(): boolean {
I
isidor 已提交
1304
		return this.editorPart.isLayoutCentered();
S
SrTobi 已提交
1305 1306
	}

1307
	centerEditorLayout(active: boolean, skipLayout?: boolean): void {
I
isidor 已提交
1308
		this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, active, StorageScope.WORKSPACE);
B
Benjamin Pasero 已提交
1309

1310
		// Enter Centered Editor Layout
I
isidor 已提交
1311
		this.editorPart.centerLayout(active);
1312

1313 1314 1315
		if (!skipLayout) {
			this.layout();
		}
S
SrTobi 已提交
1316 1317
	}

1318
	resizePart(part: Parts, sizeChange: number): void {
1319 1320 1321 1322 1323 1324 1325
		switch (part) {
			case Parts.SIDEBAR_PART:
			case Parts.PANEL_PART:
			case Parts.EDITOR_PART:
				this.workbenchLayout.resizePart(part, sizeChange);
				break;
			default:
B
Benjamin Pasero 已提交
1326
				return; // Cannot resize other parts
1327 1328 1329
		}
	}

1330 1331
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1332

1333 1334 1335
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
1336
		}
1337
	}
1338

1339 1340 1341 1342 1343 1344 1345
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nosidebar');
1346
		} else {
1347
			this.workbench.removeClass('nosidebar');
1348 1349
		}

1350 1351 1352 1353 1354 1355 1356 1357 1358
		// 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();
B
Benjamin Pasero 已提交
1359 1360
				} else {
					this.editorGroupService.activeGroup.focus();
1361 1362 1363 1364 1365 1366 1367 1368
				}
			});
		}

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

1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
		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();
			}
		});
1389
	}
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404

	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(() => {
B
Benjamin Pasero 已提交
1405
				this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
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
			});
		}

		// 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();
	}

S
SteVen Batten 已提交
1468 1469
	setMenubarVisibility(visibility: MenuBarVisibility, skipLayout: boolean): void {
		this.menubarVisibility = visibility;
1470 1471 1472 1473 1474 1475

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

1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
	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();
		});
1497
	}
1498 1499

	//#endregion
I
isidor 已提交
1500
}