workbench.ts 56.1 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';
I
isidor 已提交
111
import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection } 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
	private zenMode: IZenMode;
	private fontAliasing: FontAliasingOption;
222
	private hasInitialFilesToOpen: boolean;
223

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

454
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
455

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	private initSettings(): void {
810

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

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

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

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

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

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

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

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

850 851 852 853 854
	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;
	}
855

856 857 858
	private getCustomTitleBarStyle(): 'custom' {
		if (!isMacintosh) {
			return null; // custom title bar is only supported on Mac currently
859 860
		}

861 862 863 864
		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 已提交
865

866 867 868 869 870 871 872 873 874 875
		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;
876 877 878
			}
		}

879
		return null;
B
Benjamin Pasero 已提交
880 881
	}

882 883
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
884

885 886 887
		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nostatusbar');
E
Erich Gamma 已提交
888
		} else {
889
			this.workbench.removeClass('nostatusbar');
E
Erich Gamma 已提交
890 891
		}

892 893 894
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
895 896 897
		}
	}

898
	private setFontAliasing(aliasing: FontAliasingOption) {
899
		this.fontAliasing = aliasing;
S
Sanders Lauture 已提交
900

B
Benjamin Pasero 已提交
901 902 903 904 905
		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
906
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
907
		}
908 909
	}

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

	private renderWorkbench(): void {

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

B
Benjamin Pasero 已提交
943
		// Apply font aliasing
944 945
		this.setFontAliasing(this.fontAliasing);

B
Benjamin Pasero 已提交
946
		// Apply title style if shown
947 948 949 950 951 952 953 954
		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 已提交
955 956
		}

E
Erich Gamma 已提交
957
		// Create Parts
B
Benjamin Pasero 已提交
958
		this.createTitlebarPart();
E
Erich Gamma 已提交
959 960 961
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
962
		this.createPanelPart();
E
Erich Gamma 已提交
963 964
		this.createStatusbarPart();

965 966
		// Notification Handlers
		this.createNotificationsHandlers();
967

E
Erich Gamma 已提交
968 969 970 971
		// Add Workbench to DOM
		this.workbenchContainer.build(this.container);
	}

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

979
		this.titlebarPart.create(titlebarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
980 981
	}

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

990
		this.activitybarPart.create(activitybarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
991 992 993
	}

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

1001
		this.sidebarPart.create(sidebarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
1002 1003
	}

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

1012
		this.panelPart.create(panelPartContainer.getHTMLElement());
I
isidor 已提交
1013 1014
	}

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

1023
		this.editorPart.create(editorContainer.getHTMLElement());
E
Erich Gamma 已提交
1024 1025 1026
	}

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

1033
		this.statusbarPart.create(statusbarContainer.getHTMLElement());
E
Erich Gamma 已提交
1034 1035
	}

1036 1037
	private createNotificationsHandlers(): void {

1038
		// Notifications Center
1039
		this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench.getHTMLElement(), this.notificationService.model));
1040

1041
		// Notifications Toasts
1042
		this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench.getHTMLElement(), this.notificationService.model));
1043

1044
		// Notifications Alerts
1045
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1046 1047 1048 1049

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

1050
		// Eventing
1051
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1052 1053 1054 1055 1056 1057 1058 1059

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

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

1060
		// Register Commands
1061
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1062 1063
	}

1064
	getInstantiationService(): IInstantiationService {
E
Erich Gamma 已提交
1065 1066 1067
		return this.instantiationService;
	}

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

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

1098 1099 1100
	isCreated(): boolean {
		return this.workbenchCreated && this.workbenchStarted;
	}
1101

1102 1103 1104 1105 1106
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1107

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

1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
	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;
		}
1134

1135 1136
		return container;
	}
1137

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
	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 已提交
1150
		}
1151

1152
		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1153 1154
	}

1155 1156 1157 1158
	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 已提交
1159
		}
1160 1161

		return offset;
E
Erich Gamma 已提交
1162
	}
1163

1164
	getWorkbenchElementId(): string {
1165 1166
		return Identifiers.WORKBENCH_CONTAINER;
	}
1167

1168
	toggleZenMode(skipLayout?: boolean): void {
I
isidor 已提交
1169
		this.zenMode.active = !this.zenMode.active;
1170
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1171

1172 1173
		// 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)
1174
		let toggleFullScreen = false;
1175 1176

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

I
isidor 已提交
1180
			toggleFullScreen = !browser.isFullscreen() && config.fullScreen;
I
isidor 已提交
1181
			this.zenMode.transitionedToFullScreen = toggleFullScreen;
1182
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1183 1184
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
1185

1186 1187
			this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
			this.setSideBarHidden(true, true).done(void 0, errors.onUnexpectedError);
I
isidor 已提交
1188

1189 1190 1191
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1192

I
isidor 已提交
1193
			if (config.hideStatusBar) {
I
isidor 已提交
1194 1195
				this.setStatusBarHidden(true, true);
			}
1196

1197 1198
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1199
			}
1200 1201 1202 1203

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1204 1205 1206 1207
		}

		// Zen Mode Inactive
		else {
1208
			if (this.zenMode.wasPanelVisible) {
1209
				this.setPanelHidden(false, true).done(void 0, errors.onUnexpectedError);
1210
			}
1211

1212
			if (this.zenMode.wasSideBarVisible) {
1213
				this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError);
1214
			}
1215

1216 1217 1218
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
1219

1220 1221
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1222

B
Benjamin Pasero 已提交
1223
			this.editorGroupService.activeGroup.focus();
1224

1225
			toggleFullScreen = this.zenMode.transitionedToFullScreen && browser.isFullscreen();
I
isidor 已提交
1226
		}
1227

1228
		this.inZenMode.set(this.zenMode.active);
I
isidor 已提交
1229

I
isidor 已提交
1230
		if (!skipLayout) {
1231
			this.layout();
I
isidor 已提交
1232
		}
1233

1234
		if (toggleFullScreen) {
1235
			this.windowService.toggleFullScreen().done(void 0, errors.onUnexpectedError);
1236
		}
I
isidor 已提交
1237 1238
	}

1239 1240 1241 1242 1243 1244
	layout(options?: ILayoutOptions): void {
		if (this.workbenchStarted && !this.workbenchShutdown) {
			this.workbenchLayout.layout(options);
		}
	}

1245
	isEditorLayoutCentered(): boolean {
I
isidor 已提交
1246
		return this.editorPart.isLayoutCentered();
S
SrTobi 已提交
1247 1248
	}

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

1252
		// Enter Centered Editor Layout
I
isidor 已提交
1253
		this.editorPart.centerLayout(active);
1254

1255 1256 1257
		if (!skipLayout) {
			this.layout();
		}
S
SrTobi 已提交
1258 1259
	}

1260
	resizePart(part: Parts, sizeChange: number): void {
1261 1262 1263 1264 1265 1266 1267
		switch (part) {
			case Parts.SIDEBAR_PART:
			case Parts.PANEL_PART:
			case Parts.EDITOR_PART:
				this.workbenchLayout.resizePart(part, sizeChange);
				break;
			default:
B
Benjamin Pasero 已提交
1268
				return; // Cannot resize other parts
1269 1270 1271
		}
	}

1272 1273
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1274

1275 1276 1277
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
1278
		}
1279
	}
1280

1281 1282 1283 1284 1285 1286 1287
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nosidebar');
1288
		} else {
1289
			this.workbench.removeClass('nosidebar');
1290 1291
		}

1292 1293 1294 1295 1296 1297 1298 1299 1300
		// 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 已提交
1301 1302
				} else {
					this.editorGroupService.activeGroup.focus();
1303 1304 1305 1306 1307 1308 1309 1310
				}
			});
		}

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

1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
		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();
			}
		});
1331
	}
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346

	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 已提交
1347
				this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 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
			});
		}

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

	//#endregion
I
isidor 已提交
1434
}