workbench.ts 57.3 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';
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';
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 { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
B
Benjamin Pasero 已提交
34
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
35
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
J
Johannes Rieken 已提交
36 37
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
C
Christof Marti 已提交
38 39
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput';
J
Johannes Rieken 已提交
40
import { getServices } from 'vs/platform/instantiation/common/extensions';
41
import { Position, Parts, IPartService, ILayoutOptions, IDimension } from 'vs/workbench/services/part/common/partService';
42
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
J
Johannes Rieken 已提交
43 44 45 46
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';
47
import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService';
48 49
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
J
Johannes Rieken 已提交
50
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
51 52
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
53
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
I
isidor 已提交
54
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
B
Benjamin Pasero 已提交
55
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
P
Pine Wu 已提交
56
import { ViewletService } from 'vs/workbench/services/viewlet/browser/viewletService';
57
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
J
Johannes Rieken 已提交
58 59
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
60
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService';
J
Johannes Rieken 已提交
61
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
B
Benjamin Pasero 已提交
62
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
J
Johannes Rieken 已提交
63
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
64 65
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
J
Johannes Rieken 已提交
66 67 68 69 70
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 已提交
71 72
import { ISCMService } from 'vs/workbench/services/scm/common/scm';
import { SCMService } from 'vs/workbench/services/scm/common/scmService';
73
import { IProgressService2 } from 'vs/workbench/services/progress/common/progress';
74
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
75
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
76
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
77
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
78
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
79
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
B
Benjamin Pasero 已提交
80
import { IWindowService, IWindowConfiguration as IWindowSettings, IWindowConfiguration, IPath } from 'vs/platform/windows/common/windows';
J
Johannes Rieken 已提交
81
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
82
import { IMenuService, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
83
import { MenuService } from 'vs/workbench/services/actions/common/menuService';
J
Johannes Rieken 已提交
84 85
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
86
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
87
import { OpenRecentAction, ToggleDevToolsAction, ReloadWindowAction, ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions';
88
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
89
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
B
Benjamin Pasero 已提交
90
import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService';
91
import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService';
J
Johannes Rieken 已提交
92
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
I
isidor 已提交
93
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
B
Benjamin Pasero 已提交
94
import URI from 'vs/base/common/uri';
J
Joao Moreno 已提交
95
import { IListService, ListService } from 'vs/platform/list/browser/listService';
J
Joao Moreno 已提交
96
import { InputFocusedContext } from 'vs/platform/workbench/common/contextkeys';
97
import { IViewsService } from 'vs/workbench/common/views';
S
Sandeep Somavarapu 已提交
98
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
99 100
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
101 102
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
103
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
104
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
105
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
J
Joao Moreno 已提交
106 107
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
S
Sandeep Somavarapu 已提交
108 109
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
110
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
111
import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService';
112
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
J
Joao Moreno 已提交
113
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler';
A
Alex Dima 已提交
114 115
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
116

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

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

131 132 133
export interface IWorkbenchStartedInfo {
	customKeybindingsCount: number;
	pinnedViewlets: string[];
134
	restoredViewlet: string;
135
	restoredEditorsCount: number;
136 137
}

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

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

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

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';
	}
}

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 172 173 174
	private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
	private static readonly sidebarRestoreStorageKey = 'workbench.sidebar.restore';
	private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
	private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
175
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
176
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
177
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
178 179 180 181 182
	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';
183

184
	_serviceBrand: any;
185

E
Erich Gamma 已提交
186 187 188 189 190 191
	private workbenchParams: WorkbenchParams;
	private workbenchContainer: Builder;
	private workbench: Builder;
	private workbenchStarted: boolean;
	private workbenchCreated: boolean;
	private workbenchShutdown: boolean;
192

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

	private workbenchLayout: WorkbenchLayout;

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

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

I
isidor 已提交
225
	private inZenMode: IContextKey<boolean>;
226
	private sideBarVisibleContext: IContextKey<boolean>;
227 228

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

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

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

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

256
	startup(): TPromise<IWorkbenchStartedInfo> {
257
		this.workbenchStarted = true;
E
Erich Gamma 已提交
258

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

262 263
		// Install some global actions
		this.createGlobalActions();
264

265 266
		// Services
		this.initServices();
E
Erich Gamma 已提交
267

268 269
		// Context Keys
		this.handleContextKeys();
J
Joao Moreno 已提交
270

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

274 275
		// Settings
		this.initSettings();
E
Erich Gamma 已提交
276

277 278
		// Create Workbench and Parts
		this.renderWorkbench();
279

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

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

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

B
Benjamin Pasero 已提交
292 293 294 295 296 297
	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);
298
	}
E
Erich Gamma 已提交
299

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

B
Benjamin Pasero 已提交
303
		// Actions registered here to adjust for developing vs built workbench
304 305 306 307 308
		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');
309

310
		// Actions for macOS native tabs management (only when enabled)
311
		const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
312
		if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) {
313 314 315 316 317
			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');
318
		}
319 320
	}

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

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

327 328 329
		// Clipboard
		serviceCollection.set(IClipboardService, new ClipboardService());

330 331
		// Status bar
		this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
332
		this._register(toDisposable(() => this.statusbarPart.shutdown()));
333 334
		serviceCollection.set(IStatusbarService, this.statusbarPart);

335 336 337
		// Progress 2
		serviceCollection.set(IProgressService2, new SyncDescriptor(ProgressService2));

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

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

345 346 347
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

348
		// Context Menu
349
		serviceCollection.set(IContextMenuService, new SyncDescriptor(ContextMenuService));
350

351 352
		// Menus/Actions
		serviceCollection.set(IMenuService, new SyncDescriptor(MenuService));
353

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

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

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

367 368 369
		// views service
		const viewsService = this.instantiationService.createInstance(ViewsService);
		serviceCollection.set(IViewsService, viewsService);
S
Sandeep Somavarapu 已提交
370

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

377 378 379
		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
S
#47154  
Sandeep Somavarapu 已提交
380
		this.configurationService.acquireFileService(this.fileService);
A
Alex Dima 已提交
381
		this.themeService.acquireFileService(this.fileService);
382

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

392 393
		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
394
		this._register(toDisposable(() => this.titlebarPart.shutdown()));
395
		serviceCollection.set(ITitleService, this.titlebarPart);
396
		// History
397
		serviceCollection.set(IHistoryService, new SyncDescriptor(HistoryService));
398

399
		// Backup File Service
400
		this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.workbenchParams.configuration.backupPath);
401
		serviceCollection.set(IBackupFileService, this.backupFileService);
402

403
		// Text File Service
404
		serviceCollection.set(ITextFileService, new SyncDescriptor(TextFileService));
405

406
		// File Decorations
J
Johannes Rieken 已提交
407
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));
408

J
Joao Moreno 已提交
409
		// SCM Service
410
		serviceCollection.set(ISCMService, new SyncDescriptor(SCMService));
411

J
Joao Moreno 已提交
412
		// Inactive extension URL handler
J
Joao Moreno 已提交
413
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));
J
Joao Moreno 已提交
414

B
Benjamin Pasero 已提交
415
		// Text Model Resolver Service
416
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));
B
Benjamin Pasero 已提交
417

418 419 420 421
		// JSON Editing
		const jsonEditingService = this.instantiationService.createInstance(JSONEditingService);
		serviceCollection.set(IJSONEditingService, jsonEditingService);

422 423 424
		// Workspace Editing
		serviceCollection.set(IWorkspaceEditingService, new SyncDescriptor(WorkspaceEditingService));

425 426 427
		// Keybinding Editing
		serviceCollection.set(IKeybindingEditingService, this.instantiationService.createInstance(KeybindingsEditingService));

428
		// Configuration Resolver
B
Benjamin Pasero 已提交
429
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, process.env));
430

E
Erich Gamma 已提交
431
		// Quick open service (quick open controller)
432
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
433
		this._register(toDisposable(() => this.quickOpen.shutdown()));
434
		serviceCollection.set(IQuickOpenService, this.quickOpen);
435

C
Christof Marti 已提交
436 437
		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
438
		this._register(toDisposable(() => this.quickInput.shutdown()));
C
Christof Marti 已提交
439 440
		serviceCollection.set(IQuickInputService, this.quickInput);

S
Sandeep Somavarapu 已提交
441 442 443
		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

B
polish  
Benjamin Pasero 已提交
444
		// Contributed services
B
Benjamin Pasero 已提交
445
		const contributedServices = getServices();
E
Erich Gamma 已提交
446
		for (let contributedService of contributedServices) {
447
			serviceCollection.set(contributedService.id, contributedService.descriptor);
E
Erich Gamma 已提交
448 449 450
		}

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

455
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
456

S
#47154  
Sandeep Somavarapu 已提交
457
		this.configurationService.acquireInstantiationService(this.getInstantiationService());
E
Erich Gamma 已提交
458 459
	}

460
	//#region event handling
E
Erich Gamma 已提交
461

462
	private registerListeners(): void {
I
isidor 已提交
463

464
		// Listen to visible editor changes
465
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
B
Benjamin Pasero 已提交
466

467 468 469 470 471
		// 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);
472
			const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
I
isidor 已提交
473

474
			this._register(listenerDispose);
475
		}
S
Sanders Lauture 已提交
476

477
		// Configuration changes
478
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
I
isidor 已提交
479

480
		// Fullscreen changes
481
		this._register(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
482
	}
483

484 485 486 487
	private onFullscreenChanged(): void {
		if (!this.isCreated) {
			return; // we need to be ready
		}
S
SrTobi 已提交
488

489 490 491 492 493 494 495 496 497 498
		// 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 已提交
499

500 501 502 503 504 505
		// 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
		}
506 507
	}

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

510 511 512
		// 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.
513
		if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
514 515 516
			listenerDispose.dispose();
			this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError);
		}
E
Erich Gamma 已提交
517 518
	}

519
	private onDidVisibleEditorsChange(): void {
520
		const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
521

522 523 524 525 526 527 528 529 530
		// 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();
			}
		}
531 532
	}

533
	private onAllEditorsClosed(): void {
534
		const visibleEditors = this.editorService.visibleControls.length;
535 536
		if (visibleEditors === 0) {
			this.windowService.closeWindow();
E
Erich Gamma 已提交
537 538 539
		}
	}

540 541 542 543 544
	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);
545
		}
E
Erich Gamma 已提交
546

547
		this.setPanelPositionFromStorageOrConfig();
E
Erich Gamma 已提交
548

549 550 551
		const fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
		if (fontAliasing !== this.fontAliasing) {
			this.setFontAliasing(fontAliasing);
552 553
		}

554 555 556 557 558
		if (!this.zenMode.active) {
			const newStatusbarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.statusbarVisibleConfigurationKey);
			if (newStatusbarHiddenValue !== this.statusBarHidden) {
				this.setStatusBarHidden(newStatusbarHiddenValue, skipLayout);
			}
559

560 561 562 563
			const newActivityBarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.activityBarVisibleConfigurationKey);
			if (newActivityBarHiddenValue !== this.activityBarHidden) {
				this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout);
			}
B
Benjamin Pasero 已提交
564
		}
565
	}
B
Benjamin Pasero 已提交
566

567
	//#endregion
B
Benjamin Pasero 已提交
568

569 570
	private handleContextKeys(): void {
		this.inZenMode = InEditorZenModeContext.bindTo(this.contextKeyService);
571

572 573
		const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
		this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);
574

575 576 577 578
		const editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
		const textCompareEditorVisible = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
		const activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
		const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
579

580
		const updateEditorContextKeys = () => {
581
			const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
582

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

585 586 587 588
			if (visibleEditors.length > 0) {
				editorsVisibleContext.set(true);
			} else {
				editorsVisibleContext.reset();
589
			}
B
Benjamin Pasero 已提交
590

591
			if (!this.editorService.activeEditor) {
592 593 594
				activeEditorGroupEmpty.set(true);
			} else {
				activeEditorGroupEmpty.reset();
595
			}
596

B
Benjamin Pasero 已提交
597
			if (this.editorGroupService.count > 1) {
598 599 600 601 602
				multipleEditorGroups.set(true);
			} else {
				multipleEditorGroups.reset();
			}
		};
B
Benjamin Pasero 已提交
603

604
		this.editorPart.whenRestored.then(() => updateEditorContextKeys());
605 606
		this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
		this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
B
Benjamin Pasero 已提交
607 608
		this._register(this.editorGroupService.onDidAddGroup(() => updateEditorContextKeys()));
		this._register(this.editorGroupService.onDidRemoveGroup(() => updateEditorContextKeys()));
609

610 611 612 613 614 615 616 617 618 619
		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 已提交
620

621 622 623 624 625
		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);
		}));
626

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

629 630 631 632
		const updateSplitEditorsVerticallyContext = () => {
			const direction = preferredSideBySideGroupDirection(this.configurationService);
			splitEditorsVerticallyContext.set(direction === GroupDirection.DOWN);
		};
S
Sanders Lauture 已提交
633

634 635 636 637 638
		this._register(this.configurationService.onDidChangeConfiguration(e => {
			if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) {
				updateSplitEditorsVerticallyContext();
			}
		}));
E
Erich Gamma 已提交
639

640
		updateSplitEditorsVerticallyContext();
641
	}
E
Erich Gamma 已提交
642

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

646 647
		// Restore Editorpart
		perf.mark('willRestoreEditors');
648
		restorePromises.push(this.editorPart.whenRestored.then(() => {
649 650
			return this.resolveEditorsToOpen().then(inputs => {
				if (inputs.length) {
651
					return this.editorService.openEditors(inputs);
652
				}
E
Erich Gamma 已提交
653

654 655 656 657 658
				return TPromise.as(void 0);
			});
		}).then(() => {
			perf.mark('didRestoreEditors');
		}));
E
Erich Gamma 已提交
659

660 661 662 663
		// Restore Sidebar
		let viewletIdToRestore: string;
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);
664

665 666
			if (this.shouldRestoreLastOpenedViewlet()) {
				viewletIdToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE);
667
			}
668

669 670
			if (!viewletIdToRestore) {
				viewletIdToRestore = this.viewletService.getDefaultViewletId();
671
			}
E
Erich Gamma 已提交
672

673
			perf.mark('willRestoreViewlet');
674 675 676 677 678
			restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore)
				.then(viewlet => viewlet || this.viewletService.openViewlet(this.viewletService.getDefaultViewletId()))
				.then(() => {
					perf.mark('didRestoreViewlet');
				}));
679 680
		}

681 682 683 684 685
		// 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 已提交
686 687
		}

688
		// Restore Zen Mode if active
I
isidor 已提交
689
		if (this.storageService.getBoolean(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE, false)) {
690
			this.toggleZenMode(true);
I
isidor 已提交
691 692
		}

B
Benjamin Pasero 已提交
693
		// Restore Forced Editor Center Mode
694
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
B
Benjamin Pasero 已提交
695
			this.centeredEditorLayoutActive = true;
S
SrTobi 已提交
696
		}
697

698
		const onRestored = (error?: Error): IWorkbenchStartedInfo => {
B
Benjamin Pasero 已提交
699
			this.workbenchCreated = true;
700

701 702
			if (error) {
				errors.onUnexpectedError(error);
703
			}
I
isidor 已提交
704

705 706 707 708
			return {
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
				pinnedViewlets: this.activitybarPart.getPinned(),
				restoredViewlet: viewletIdToRestore,
709
				restoredEditorsCount: this.editorService.visibleEditors.length
710 711
			};
		};
712

713
		return TPromise.join(restorePromises).then(() => onRestored(), error => onRestored(error));
E
Erich Gamma 已提交
714 715
	}

716 717 718
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
E
Erich Gamma 已提交
719 720
		}

721 722 723 724
		const restore = this.storageService.getBoolean(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE);
		if (restore) {
			this.storageService.remove(Workbench.sidebarRestoreStorageKey, StorageScope.WORKSPACE); // only support once
		}
725

726
		return restore;
E
Erich Gamma 已提交
727 728
	}

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

B
Benjamin Pasero 已提交
732
		// Files to open, diff or create
733
		if (this.hasInitialFilesToOpen) {
I
isidor 已提交
734

B
Benjamin Pasero 已提交
735
			// Files to diff is exclusive
736
			const filesToDiff = this.toInputs(config.filesToDiff, false);
737
			if (filesToDiff && filesToDiff.length === 2) {
738 739 740 741 742
				return TPromise.as([<IResourceDiffInput>{
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
					options: { pinned: true }
				}]);
B
Benjamin Pasero 已提交
743
			}
I
isidor 已提交
744

745 746
			const filesToCreate = this.toInputs(config.filesToCreate, true);
			const filesToOpen = this.toInputs(config.filesToOpen, false);
I
isidor 已提交
747

748 749
			// Otherwise: Open/Create files
			return TPromise.as([...filesToOpen, ...filesToCreate]);
B
Benjamin Pasero 已提交
750
		}
I
isidor 已提交
751

752
		// Empty workbench
753
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
B
Benjamin Pasero 已提交
754
			const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
755 756
			if (!isEmpty) {
				return TPromise.as([]); // do not open any empty untitled file if we restored editors from previous session
757
			}
B
Benjamin Pasero 已提交
758

759 760 761 762
			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 已提交
763

764
				return TPromise.as([<IUntitledResourceInput>{}]);
765
			});
766
		}
767

B
Benjamin Pasero 已提交
768 769
		return TPromise.as([]);
	}
770

771
	private toInputs(paths: IPath[], isNew: boolean): (IResourceInput | IUntitledResourceInput)[] {
B
Benjamin Pasero 已提交
772 773
		if (!paths || !paths.length) {
			return [];
774
		}
I
isidor 已提交
775

B
Benjamin Pasero 已提交
776
		return paths.map(p => {
777 778 779 780 781 782
			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;
783
			}
E
Erich Gamma 已提交
784

785
			if (!isNew && p.lineNumber) {
B
Benjamin Pasero 已提交
786 787 788 789 790
				input.options.selection = {
					startLineNumber: p.lineNumber,
					startColumn: p.columnNumber
				};
			}
791

B
Benjamin Pasero 已提交
792 793
			return input;
		});
794 795
	}

796
	private openUntitledFile() {
797
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');
B
Benjamin Pasero 已提交
798 799

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

807
		return startupEditor.value === 'newUntitledFile';
808
	}
E
Erich Gamma 已提交
809 810

	private initSettings(): void {
811

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

I
isidor 已提交
815
		// Panel part visibility
816
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
I
isidor 已提交
817
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
818 819
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
820 821
		}

E
Erich Gamma 已提交
822
		// Sidebar position
823
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
824
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
825

I
isidor 已提交
826
		// Panel position
827
		this.setPanelPositionFromStorageOrConfig();
828

B
Benjamin Pasero 已提交
829
		// Statusbar visibility
830
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
831
		this.statusBarHidden = !statusBarVisible;
832

S
Sanders Lauture 已提交
833
		// Activity bar visibility
834
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
S
Sanders Lauture 已提交
835
		this.activityBarHidden = !activityBarVisible;
836

837
		// Font aliasing
838
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
839

I
isidor 已提交
840 841
		// Zen mode
		this.zenMode = {
I
isidor 已提交
842
			active: false,
843
			transitionedToFullScreen: false,
844
			transitionedToCenteredEditorLayout: false,
845
			wasSideBarVisible: false,
846 847
			wasPanelVisible: false,
			transitionDisposeables: []
I
isidor 已提交
848
		};
S
SrTobi 已提交
849

B
Benjamin Pasero 已提交
850 851
		// Centered Editor Layout
		this.centeredEditorLayoutActive = false;
E
Erich Gamma 已提交
852 853
	}

854 855 856 857 858
	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;
	}
859

860 861 862
	private getCustomTitleBarStyle(): 'custom' {
		if (!isMacintosh) {
			return null; // custom title bar is only supported on Mac currently
863 864
		}

865 866 867 868
		const isDev = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
		if (isDev) {
			return null; // not enabled when developing due to https://github.com/electron/electron/issues/3647
		}
E
Erich Gamma 已提交
869

870 871 872 873 874 875 876 877 878 879
		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;
880 881 882
			}
		}

883
		return null;
B
Benjamin Pasero 已提交
884 885
	}

886 887
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
888

889 890 891
		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nostatusbar');
E
Erich Gamma 已提交
892
		} else {
893
			this.workbench.removeClass('nostatusbar');
E
Erich Gamma 已提交
894 895
		}

896 897 898
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
899 900 901
		}
	}

902
	private setFontAliasing(aliasing: FontAliasingOption) {
903
		this.fontAliasing = aliasing;
S
Sanders Lauture 已提交
904

B
Benjamin Pasero 已提交
905 906 907 908 909
		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
910
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
911
		}
912 913
	}

E
Erich Gamma 已提交
914
	private createWorkbenchLayout(): void {
915 916
		this.workbenchLayout = this.instantiationService.createInstance(
			WorkbenchLayout,
917 918
			this.container,
			this.workbench.getHTMLElement(),
I
isidor 已提交
919
			{
920 921 922 923 924 925
				titlebar: this.titlebarPart,
				activitybar: this.activitybarPart,
				editor: this.editorPart,
				sidebar: this.sidebarPart,
				panel: this.panelPart,
				statusbar: this.statusbarPart,
I
isidor 已提交
926
			},
927 928 929 930
			this.quickOpen,
			this.quickInput,
			this.notificationsCenter,
			this.notificationsToasts
E
Erich Gamma 已提交
931 932 933 934 935 936 937 938 939
		);
	}

	private renderWorkbench(): void {

		// Apply sidebar state as CSS class
		if (this.sideBarHidden) {
			this.workbench.addClass('nosidebar');
		}
940 941 942
		if (this.panelHidden) {
			this.workbench.addClass('nopanel');
		}
943 944 945
		if (this.statusBarHidden) {
			this.workbench.addClass('nostatusbar');
		}
E
Erich Gamma 已提交
946

B
Benjamin Pasero 已提交
947
		// Apply font aliasing
948 949
		this.setFontAliasing(this.fontAliasing);

B
Benjamin Pasero 已提交
950
		// Apply title style if shown
951 952 953 954 955 956 957 958
		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 已提交
959 960
		}

E
Erich Gamma 已提交
961
		// Create Parts
B
Benjamin Pasero 已提交
962
		this.createTitlebarPart();
E
Erich Gamma 已提交
963 964 965
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
966
		this.createPanelPart();
E
Erich Gamma 已提交
967 968
		this.createStatusbarPart();

969 970
		// Notification Handlers
		this.createNotificationsHandlers();
971

E
Erich Gamma 已提交
972 973 974 975
		// Add Workbench to DOM
		this.workbenchContainer.build(this.container);
	}

B
Benjamin Pasero 已提交
976 977 978 979 980 981 982
	private createTitlebarPart(): void {
		const titlebarContainer = $(this.workbench).div({
			'class': ['part', 'titlebar'],
			id: Identifiers.TITLEBAR_PART,
			role: 'contentinfo'
		});

983
		this.titlebarPart.create(titlebarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
984 985
	}

E
Erich Gamma 已提交
986
	private createActivityBarPart(): void {
B
Benjamin Pasero 已提交
987
		const activitybarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
988 989
			.div({
				'class': ['part', 'activitybar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
990 991
				id: Identifiers.ACTIVITYBAR_PART,
				role: 'navigation'
E
Erich Gamma 已提交
992 993
			});

994
		this.activitybarPart.create(activitybarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
995 996 997
	}

	private createSidebarPart(): void {
B
Benjamin Pasero 已提交
998
		const sidebarPartContainer = $(this.workbench)
E
Erich Gamma 已提交
999 1000
			.div({
				'class': ['part', 'sidebar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'],
1001 1002
				id: Identifiers.SIDEBAR_PART,
				role: 'complementary'
E
Erich Gamma 已提交
1003 1004
			});

1005
		this.sidebarPart.create(sidebarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1006 1007
	}

I
isidor 已提交
1008
	private createPanelPart(): void {
B
Benjamin Pasero 已提交
1009
		const panelPartContainer = $(this.workbench)
I
isidor 已提交
1010
			.div({
1011
				'class': ['part', 'panel', this.panelPosition === Position.BOTTOM ? 'bottom' : 'right'],
1012 1013
				id: Identifiers.PANEL_PART,
				role: 'complementary'
I
isidor 已提交
1014 1015
			});

1016
		this.panelPart.create(panelPartContainer.getHTMLElement());
I
isidor 已提交
1017 1018
	}

E
Erich Gamma 已提交
1019
	private createEditorPart(): void {
B
Benjamin Pasero 已提交
1020
		const editorContainer = $(this.workbench)
E
Erich Gamma 已提交
1021
			.div({
1022
				'class': ['part', 'editor'],
1023 1024
				id: Identifiers.EDITOR_PART,
				role: 'main'
E
Erich Gamma 已提交
1025 1026
			});

1027
		this.editorPart.create(editorContainer.getHTMLElement());
E
Erich Gamma 已提交
1028 1029 1030
	}

	private createStatusbarPart(): void {
B
Benjamin Pasero 已提交
1031
		const statusbarContainer = $(this.workbench).div({
E
Erich Gamma 已提交
1032
			'class': ['part', 'statusbar'],
1033 1034
			id: Identifiers.STATUSBAR_PART,
			role: 'contentinfo'
E
Erich Gamma 已提交
1035 1036
		});

1037
		this.statusbarPart.create(statusbarContainer.getHTMLElement());
E
Erich Gamma 已提交
1038 1039
	}

1040 1041
	private createNotificationsHandlers(): void {

1042
		// Notifications Center
1043
		this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench.getHTMLElement(), this.notificationService.model));
1044

1045
		// Notifications Toasts
1046
		this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench.getHTMLElement(), this.notificationService.model));
1047

1048
		// Notifications Alerts
1049
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1050 1051 1052 1053

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

1054
		// Eventing
1055
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1056 1057 1058 1059 1060 1061 1062 1063

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

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

1064
		// Register Commands
1065
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1066 1067
	}

1068
	getInstantiationService(): IInstantiationService {
E
Erich Gamma 已提交
1069 1070 1071
		return this.instantiationService;
	}

1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
	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; }
1099

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

1102 1103 1104
	isCreated(): boolean {
		return this.workbenchCreated && this.workbenchStarted;
	}
1105

1106 1107 1108 1109 1110
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1111

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

1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
	getContainer(part: Parts): HTMLElement {
		let container: HTMLElement = null;
		switch (part) {
			case Parts.TITLEBAR_PART:
				container = this.titlebarPart.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;
		}
1138

1139 1140
		return container;
	}
1141

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
	isVisible(part: Parts): boolean {
		switch (part) {
			case Parts.TITLEBAR_PART:
				return this.getCustomTitleBarStyle() && !browser.isFullscreen();
			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 已提交
1154
		}
1155

1156
		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1157 1158
	}

1159 1160 1161 1162
	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 已提交
1163
		}
1164 1165

		return offset;
E
Erich Gamma 已提交
1166
	}
1167

1168
	getWorkbenchElementId(): string {
1169 1170
		return Identifiers.WORKBENCH_CONTAINER;
	}
1171

1172
	toggleZenMode(skipLayout?: boolean): void {
I
isidor 已提交
1173
		this.zenMode.active = !this.zenMode.active;
1174
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1175

1176 1177
		// 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)
1178
		let toggleFullScreen = false;
1179 1180

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

I
isidor 已提交
1184
			toggleFullScreen = !browser.isFullscreen() && config.fullScreen;
I
isidor 已提交
1185
			this.zenMode.transitionedToFullScreen = toggleFullScreen;
1186
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1187 1188
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
1189

1190 1191
			this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
			this.setSideBarHidden(true, true).done(void 0, errors.onUnexpectedError);
I
isidor 已提交
1192

1193 1194 1195
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1196

I
isidor 已提交
1197
			if (config.hideStatusBar) {
I
isidor 已提交
1198 1199
				this.setStatusBarHidden(true, true);
			}
1200

1201 1202
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1203
			}
1204 1205 1206 1207

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1208 1209 1210 1211
		}

		// Zen Mode Inactive
		else {
1212
			if (this.zenMode.wasPanelVisible) {
1213
				this.setPanelHidden(false, true).done(void 0, errors.onUnexpectedError);
1214
			}
1215

1216
			if (this.zenMode.wasSideBarVisible) {
1217
				this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError);
1218
			}
1219

1220 1221 1222
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
1223

1224 1225
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1226

B
Benjamin Pasero 已提交
1227
			this.editorGroupService.activeGroup.focus();
1228

1229
			toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen();
I
isidor 已提交
1230
		}
1231

1232
		this.inZenMode.set(this.zenMode.active);
I
isidor 已提交
1233

I
isidor 已提交
1234
		if (!skipLayout) {
1235
			this.layout();
I
isidor 已提交
1236
		}
1237

1238
		if (toggleFullScreen) {
1239
			this.windowService.toggleFullScreen().done(void 0, errors.onUnexpectedError);
1240
		}
I
isidor 已提交
1241 1242
	}

1243 1244 1245 1246 1247 1248
	layout(options?: ILayoutOptions): void {
		if (this.workbenchStarted && !this.workbenchShutdown) {
			this.workbenchLayout.layout(options);
		}
	}

1249
	isEditorLayoutCentered(): boolean {
B
Benjamin Pasero 已提交
1250
		return this.centeredEditorLayoutActive;
S
SrTobi 已提交
1251 1252
	}

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

1262 1263
		// Enter Centered Editor Layout
		if (active) {
B
Benjamin Pasero 已提交
1264 1265 1266 1267
			if (this.editorGroupService.count === 1) {
				const activeGroup = this.editorGroupService.activeGroup;
				this.editorGroupService.addGroup(activeGroup, GroupDirection.LEFT);
				this.editorGroupService.addGroup(activeGroup, GroupDirection.RIGHT);
1268 1269

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

		// Leave Centered Editor Layout
		else {
B
Benjamin Pasero 已提交
1275 1276
			if (this.editorGroupService.count === 3) {
				this.editorGroupService.groups.forEach(group => {
1277
					if (group.count === 0) {
B
Benjamin Pasero 已提交
1278
						this.editorGroupService.removeGroup(group);
1279 1280 1281 1282 1283
					}
				});
			}
		}

1284 1285 1286
		if (!skipLayout) {
			this.layout();
		}
S
SrTobi 已提交
1287 1288
	}

1289
	resizePart(part: Parts, sizeChange: number): void {
1290 1291 1292 1293 1294 1295 1296
		switch (part) {
			case Parts.SIDEBAR_PART:
			case Parts.PANEL_PART:
			case Parts.EDITOR_PART:
				this.workbenchLayout.resizePart(part, sizeChange);
				break;
			default:
B
Benjamin Pasero 已提交
1297
				return; // Cannot resize other parts
1298 1299 1300
		}
	}

1301 1302
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1303

1304 1305 1306
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
1307
		}
1308
	}
1309

1310 1311 1312 1313 1314 1315 1316
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nosidebar');
1317
		} else {
1318
			this.workbench.removeClass('nosidebar');
1319 1320
		}

1321 1322 1323 1324 1325 1326 1327 1328 1329
		// 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 已提交
1330 1331
				} else {
					this.editorGroupService.activeGroup.focus();
1332 1333 1334 1335 1336 1337 1338 1339
				}
			});
		}

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

1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
		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();
			}
		});
1360
	}
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375

	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 已提交
1376
				this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 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
			});
		}

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

	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();
		});
1460
	}
1461 1462

	//#endregion
1463
}