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

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

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

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

140 141
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';

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

144 145
const Identifiers = {
	WORKBENCH_CONTAINER: 'workbench.main.container',
B
Benjamin Pasero 已提交
146
	TITLEBAR_PART: 'workbench.parts.titlebar',
147 148 149 150 151 152 153
	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 已提交
154 155 156 157 158 159 160 161
function getWorkbenchStateString(state: WorkbenchState): string {
	switch (state) {
		case WorkbenchState.EMPTY: return 'empty';
		case WorkbenchState.FOLDER: return 'folder';
		case WorkbenchState.WORKSPACE: return 'workspace';
	}
}

162 163 164 165 166 167 168 169 170 171
interface IZenMode {
	active: boolean;
	transitionedToFullScreen: boolean;
	transitionedToCenteredEditorLayout: boolean;
	transitionDisposeables: IDisposable[];
	wasSideBarVisible: boolean;
	wasPanelVisible: boolean;
}

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

173 174 175 176
	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';
177
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
178
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
179
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
180 181 182 183 184
	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';
185

186
	_serviceBrand: any;
E
Erich Gamma 已提交
187 188 189 190 191 192

	private workbenchParams: WorkbenchParams;
	private workbenchContainer: Builder;
	private workbench: Builder;
	private workbenchStarted: boolean;
	private workbenchCreated: boolean;
193 194
	private workbenchShutdown: boolean;

195 196
	private editorService: INextEditorService;
	private editorGroupsService: INextEditorGroupsService;
P
Pine Wu 已提交
197
	private viewletService: IViewletService;
198
	private contextKeyService: IContextKeyService;
199
	private keybindingService: IKeybindingService;
200
	private backupFileService: IBackupFileService;
201
	private fileService: IFileService;
202 203 204 205
	private quickInput: QuickInputService;

	private workbenchLayout: WorkbenchLayout;

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

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

	private inZenMode: IContextKey<boolean>;
228
	private sideBarVisibleContext: IContextKey<boolean>;
229 230 231

	private closeEmptyWindowScheduler: RunOnceScheduler = new RunOnceScheduler(() => this.onAllEditorsClosed(), 50);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

293 294 295 296 297 298 299
	private createWorkbench(): void {
		this.workbenchContainer = $('.monaco-workbench-container');
		this.workbench = $().div({
			'class': `monaco-workbench ${isWindows ? 'windows' : isLinux ? 'linux' : 'mac'}`,
			id: Identifiers.WORKBENCH_CONTAINER
		}).appendTo(this.workbenchContainer);
	}
300

301 302
	private createGlobalActions(): void {
		const isDeveloping = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
303

304 305 306 307 308 309
		// Actions registered here to adjust for developing vs built workbench
		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');
310

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

322 323
	private initServices(): void {
		const { serviceCollection } = this.workbenchParams;
324

325 326
		// Services we contribute
		serviceCollection.set(IPartService, this);
327

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

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

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

339 340 341
		// Keybindings
		this.contextKeyService = this.instantiationService.createInstance(ContextKeyService);
		serviceCollection.set(IContextKeyService, this.contextKeyService);
342

343 344
		this.keybindingService = this.instantiationService.createInstance(WorkbenchKeybindingService, window);
		serviceCollection.set(IKeybindingService, this.keybindingService);
345

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

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

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

		// Sidebar part
		this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
		this._register(toDisposable(() => this.sidebarPart.shutdown()));

		// Viewlet service
		this.viewletService = this.instantiationService.createInstance(ViewletService, this.sidebarPart);
		serviceCollection.set(IViewletService, this.viewletService);

		// Panel service (panel part)
		this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
		this._register(toDisposable(() => this.panelPart.shutdown()));
		serviceCollection.set(IPanelService, this.panelPart);

		// Custom views service
		const customViewsService = this.instantiationService.createInstance(CustomViewsService);
		serviceCollection.set(IViewsService, customViewsService);

		// Activity service (activitybar part)
		this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
		this._register(toDisposable(() => this.activitybarPart.shutdown()));
		const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
		serviceCollection.set(IActivityService, activityService);

		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
		this.configurationService.acquireFileService(this.fileService);

		// Editor and Group services
		const restorePreviousEditorState = !this.hasInitialFilesToOpen;
		this.editorPart = this.instantiationService.createInstance(NextEditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
		this._register(toDisposable(() => this.editorPart.shutdown()));
387
		this.editorGroupsService = this.editorPart;
388
		serviceCollection.set(INextEditorGroupsService, this.editorPart);
389 390
		this.editorService = this.instantiationService.createInstance(NextEditorService);
		serviceCollection.set(INextEditorService, this.editorService);
391

392 393 394
		// Opener service
		serviceCollection.set(IOpenerService, new SyncDescriptor(OpenerService));

395
		// TODO@grid Remove Legacy Editor Services
396 397 398
		const noOpEditorPart = new NoOpEditorPart(this.instantiationService);
		serviceCollection.set(IWorkbenchEditorService, this.instantiationService.createInstance(WorkbenchEditorService, noOpEditorPart));
		serviceCollection.set(IEditorGroupService, noOpEditorPart);
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
		this._register(toDisposable(() => this.titlebarPart.shutdown()));
		serviceCollection.set(ITitleService, this.titlebarPart);

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

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

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

		// File Decorations
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));

		// SCM Service
		serviceCollection.set(ISCMService, new SyncDescriptor(SCMService));

		// Inactive extension URL handler
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));

		// Text Model Resolver Service
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));

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

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

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

		// Configuration Resolver
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, process.env));

		// Quick open service (quick open controller)
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
		this._register(toDisposable(() => this.quickOpen.shutdown()));
		serviceCollection.set(IQuickOpenService, this.quickOpen);

		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
		this._register(toDisposable(() => this.quickInput.shutdown()));
		serviceCollection.set(IQuickInputService, this.quickInput);

		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

		// Contributed services
		const contributedServices = getServices();
		for (let contributedService of contributedServices) {
			serviceCollection.set(contributedService.id, contributedService.descriptor);
		}

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

		this.instantiationService.createInstance(DefaultConfigurationExportHelper);

		this.configurationService.acquireInstantiationService(this.getInstantiationService());
467 468
	}

469 470
	//#region event handling

471 472
	private registerListeners(): void {

473
		// Listen to visible editor changes
474
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
475 476 477 478 479 480

		// 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);
481
			const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
482

483
			this._register(listenerDispose);
484 485 486
		}

		// Configuration changes
487
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
488 489

		// Fullscreen changes
490
		this._register(browser.onDidChangeFullscreen(() => this.onFullscreenChanged()));
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
	}

	private onFullscreenChanged(): void {
		if (!this.isCreated) {
			return; // we need to be ready
		}

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

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

	private onEditorClosed(listenerDispose: IDisposable, resourcesToWaitFor: URI[], waitMarkerFile: URI): void {

		// 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.
522
		if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
523 524 525 526 527
			listenerDispose.dispose();
			this.fileService.del(waitMarkerFile).done(null, errors.onUnexpectedError);
		}
	}

528
	private onDidVisibleEditorsChange(): void {
529
		const visibleEditors = this.editorService.visibleControls;
530 531 532 533 534 535 536 537 538 539 540 541 542

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

	private onAllEditorsClosed(): void {
543
		const visibleEditors = this.editorService.visibleControls.length;
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
		if (visibleEditors === 0) {
			this.windowService.closeWindow();
		}
	}

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

		this.setPanelPositionFromStorageOrConfig();

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

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

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

576
	//#endregion
E
Erich Gamma 已提交
577

578 579
	private handleContextKeys(): void {
		this.inZenMode = InEditorZenModeContext.bindTo(this.contextKeyService);
580

581 582
		const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
		this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);
583

584 585 586 587
		const editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
		const textCompareEditorVisible = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
		const activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
		const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
588

589
		const updateEditorContextKeys = () => {
590
			const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
591

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

594 595 596 597
			if (visibleEditors.length > 0) {
				editorsVisibleContext.set(true);
			} else {
				editorsVisibleContext.reset();
598
			}
599

600
			if (!this.editorService.activeEditor) {
601 602 603
				activeEditorGroupEmpty.set(true);
			} else {
				activeEditorGroupEmpty.reset();
604
			}
605

606
			if (this.editorGroupsService.count > 1) {
607 608 609 610 611
				multipleEditorGroups.set(true);
			} else {
				multipleEditorGroups.reset();
			}
		};
E
Erich Gamma 已提交
612

613 614
		this.editorGroupsService.whenRestored.then(() => updateEditorContextKeys());

615 616 617 618
		this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
		this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
		this._register(this.editorGroupsService.onDidAddGroup(() => updateEditorContextKeys()));
		this._register(this.editorGroupsService.onDidRemoveGroup(() => updateEditorContextKeys()));
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642

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

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

	private restoreParts(): TPromise<IWorkbenchStartedInfo> {
		const restorePromises: Thenable<any>[] = [];

		// Restore Editorpart
		perf.mark('willRestoreEditors');
643
		restorePromises.push(this.editorGroupsService.whenRestored.then(() => {
644 645
			return this.resolveEditorsToOpen().then(inputs => {
				if (inputs.length) {
646
					return this.editorService.openEditors(inputs);
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
				}

				return TPromise.as(void 0);
			});
		}).then(() => {
			perf.mark('didRestoreEditors');
		}));

		// Restore Sidebar
		let viewletIdToRestore: string;
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);

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

			if (!viewletIdToRestore) {
				viewletIdToRestore = this.viewletService.getDefaultViewletId();
			}

			perf.mark('willRestoreViewlet');
			restorePromises.push(this.viewletService.openViewlet(viewletIdToRestore).then(() => {
				perf.mark('didRestoreViewlet');
			}));
		}

		// 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));
		}
E
Erich Gamma 已提交
680

681
		// Restore Zen Mode if active
I
isidor 已提交
682
		if (this.storageService.getBoolean(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE, false)) {
683
			this.toggleZenMode(true);
E
Erich Gamma 已提交
684
		}
685

B
Benjamin Pasero 已提交
686
		// Restore Forced Editor Center Mode
687
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
B
Benjamin Pasero 已提交
688
			this.centeredEditorLayoutActive = true;
S
SrTobi 已提交
689 690
		}

691
		const onRestored = (error?: Error): IWorkbenchStartedInfo => {
B
Benjamin Pasero 已提交
692 693
			this.workbenchCreated = true;

694 695 696 697 698 699 700 701
			if (error) {
				errors.onUnexpectedError(error);
			}

			return {
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
				pinnedViewlets: this.activitybarPart.getPinned(),
				restoredViewlet: viewletIdToRestore,
702
				restoredEditorsCount: this.editorService.visibleEditors.length
703 704 705 706
			};
		};

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

709 710 711 712 713 714 715 716 717 718 719 720 721
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
		}

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

		return restore;
	}

722
	private resolveEditorsToOpen(): TPromise<IResourceInputType[]> {
723
		const config = this.workbenchParams.configuration;
B
Benjamin Pasero 已提交
724 725

		// Files to open, diff or create
726
		if (this.hasInitialFilesToOpen) {
B
Benjamin Pasero 已提交
727 728

			// Files to diff is exclusive
729
			const filesToDiff = this.toInputs(config.filesToDiff, false);
730
			if (filesToDiff && filesToDiff.length === 2) {
731 732 733 734 735
				return TPromise.as([<IResourceDiffInput>{
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
					options: { pinned: true }
				}]);
B
Benjamin Pasero 已提交
736 737
			}

738 739
			const filesToCreate = this.toInputs(config.filesToCreate, true);
			const filesToOpen = this.toInputs(config.filesToOpen, false);
740

741 742
			// Otherwise: Open/Create files
			return TPromise.as([...filesToOpen, ...filesToCreate]);
B
Benjamin Pasero 已提交
743 744
		}

745
		// Empty workbench
746
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
747
			const isEmpty = this.editorGroupsService.count === 1 && this.editorGroupsService.activeGroup.count === 0;
748 749
			if (!isEmpty) {
				return TPromise.as([]); // do not open any empty untitled file if we restored editors from previous session
750 751
			}

752 753 754 755 756
			return this.backupFileService.hasBackups().then(hasBackups => {
				if (hasBackups) {
					return TPromise.as([]); // do not open any empty untitled file if we have backups to restore
				}

757
				return TPromise.as([<IUntitledResourceInput>{}]);
758
			});
B
Benjamin Pasero 已提交
759 760 761 762 763
		}

		return TPromise.as([]);
	}

764
	private toInputs(paths: IPath[], isNew: boolean): (IResourceInput | IUntitledResourceInput)[] {
B
Benjamin Pasero 已提交
765 766 767 768 769
		if (!paths || !paths.length) {
			return [];
		}

		return paths.map(p => {
770 771 772 773 774 775 776
			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;
			}
B
Benjamin Pasero 已提交
777

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

			return input;
		});
	}

789
	private openUntitledFile() {
790
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');
B
Benjamin Pasero 已提交
791 792

		// Fallback to previous workbench.welcome.enabled setting in case startupEditor is not defined
793
		if (!startupEditor.user && !startupEditor.workspace) {
794 795 796
			const welcomeEnabledValue = this.configurationService.getValue('workbench.welcome.enabled');
			if (typeof welcomeEnabledValue === 'boolean') {
				return !welcomeEnabledValue;
797 798
			}
		}
B
Benjamin Pasero 已提交
799

800
		return startupEditor.value === 'newUntitledFile';
801 802
	}

E
Erich Gamma 已提交
803 804 805
	private initSettings(): void {

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

I
isidor 已提交
808
		// Panel part visibility
809
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
I
isidor 已提交
810
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
811 812
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
I
isidor 已提交
813
		}
I
isidor 已提交
814

E
Erich Gamma 已提交
815
		// Sidebar position
816
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
817
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
B
Benjamin Pasero 已提交
818

I
isidor 已提交
819
		// Panel position
820
		this.setPanelPositionFromStorageOrConfig();
I
isidor 已提交
821

B
Benjamin Pasero 已提交
822
		// Statusbar visibility
823
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
824
		this.statusBarHidden = !statusBarVisible;
S
Sanders Lauture 已提交
825 826

		// Activity bar visibility
827
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
S
Sanders Lauture 已提交
828
		this.activityBarHidden = !activityBarVisible;
I
isidor 已提交
829

830
		// Font aliasing
831
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
832

I
isidor 已提交
833 834
		// Zen mode
		this.zenMode = {
I
isidor 已提交
835
			active: false,
836
			transitionedToFullScreen: false,
837
			transitionedToCenteredEditorLayout: false,
838
			wasSideBarVisible: false,
839 840
			wasPanelVisible: false,
			transitionDisposeables: []
I
isidor 已提交
841
		};
S
SrTobi 已提交
842

B
Benjamin Pasero 已提交
843 844
		// Centered Editor Layout
		this.centeredEditorLayoutActive = false;
E
Erich Gamma 已提交
845 846
	}

847 848 849 850 851 852
	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;
	}

853 854 855 856
	private getCustomTitleBarStyle(): 'custom' {
		if (!isMacintosh) {
			return null; // custom title bar is only supported on Mac currently
		}
E
Erich Gamma 已提交
857

858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
		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
		}

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

		return null;
E
Erich Gamma 已提交
877 878
	}

879 880 881 882 883 884 885 886
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;

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

889 890 891 892
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
		}
I
isidor 已提交
893 894
	}

895
	private setFontAliasing(aliasing: FontAliasingOption) {
896
		this.fontAliasing = aliasing;
B
Benjamin Pasero 已提交
897 898 899 900 901 902

		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
903 904
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
		}
905 906
	}

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

	private renderWorkbench(): void {

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

B
Benjamin Pasero 已提交
940
		// Apply font aliasing
941 942
		this.setFontAliasing(this.fontAliasing);

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

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

962 963
		// Notification Handlers
		this.createNotificationsHandlers();
964

E
Erich Gamma 已提交
965 966 967 968
		// Add Workbench to DOM
		this.workbenchContainer.build(this.container);
	}

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

976
		this.titlebarPart.create(titlebarContainer.getHTMLElement());
B
Benjamin Pasero 已提交
977 978
	}

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

987
		this.activitybarPart.create(activitybarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
988 989 990
	}

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

998
		this.sidebarPart.create(sidebarPartContainer.getHTMLElement());
E
Erich Gamma 已提交
999 1000
	}

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

1009
		this.panelPart.create(panelPartContainer.getHTMLElement());
I
isidor 已提交
1010 1011
	}

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

1020
		this.editorPart.create(editorContainer.getHTMLElement());
E
Erich Gamma 已提交
1021 1022 1023
	}

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

1030
		this.statusbarPart.create(statusbarContainer.getHTMLElement());
E
Erich Gamma 已提交
1031 1032
	}

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
	private createNotificationsHandlers(): void {

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

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

		// Notifications Alerts
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));

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

		// Eventing
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {

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

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

		// Register Commands
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
	}

	getInstantiationService(): IInstantiationService {
		return this.instantiationService;
	}

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

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

1095 1096 1097
	isCreated(): boolean {
		return this.workbenchCreated && this.workbenchStarted;
	}
1098

1099 1100 1101 1102 1103
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1104

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

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

1132 1133
		return container;
	}
1134

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
	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;
		}
1148

1149
		return true; // any other part cannot be hidden
1150 1151
	}

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

		return offset;
E
Erich Gamma 已提交
1159 1160
	}

1161
	getWorkbenchElementId(): string {
1162 1163
		return Identifiers.WORKBENCH_CONTAINER;
	}
1164

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

1169 1170
		// 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)
1171
		let toggleFullScreen = false;
1172 1173

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

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

1183 1184
			this.setPanelHidden(true, true).done(void 0, errors.onUnexpectedError);
			this.setSideBarHidden(true, true).done(void 0, errors.onUnexpectedError);
I
isidor 已提交
1185

1186 1187 1188
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1189

I
isidor 已提交
1190
			if (config.hideStatusBar) {
I
isidor 已提交
1191 1192
				this.setStatusBarHidden(true, true);
			}
1193

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

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1201 1202 1203 1204
		}

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

1209
			if (this.zenMode.wasSideBarVisible) {
1210
				this.setSideBarHidden(false, true).done(void 0, errors.onUnexpectedError);
1211
			}
1212

1213 1214 1215
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
1216

1217 1218
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1219

1220
			const activeEditor = this.editorService.activeControl;
I
isidor 已提交
1221 1222 1223
			if (activeEditor) {
				activeEditor.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 {
B
Benjamin Pasero 已提交
1246
		return this.centeredEditorLayoutActive;
S
SrTobi 已提交
1247 1248
	}

1249 1250 1251
	// TODO@grid support centered editor layout using empty groups or not? functionality missing:
	// - resize sashes left and right in sync
	// - IEditorInput.supportsCenteredEditorLayout() no longer supported
1252
	centerEditorLayout(active: boolean, skipLayout?: boolean): void {
1253
		this.centeredEditorLayoutActive = active;
1254
		this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, this.centeredEditorLayoutActive, StorageScope.WORKSPACE);
B
Benjamin Pasero 已提交
1255

1256 1257
		// Enter Centered Editor Layout
		if (active) {
1258 1259 1260 1261
			if (this.editorGroupsService.count === 1) {
				const activeGroup = this.editorGroupsService.activeGroup;
				this.editorGroupsService.addGroup(activeGroup, GroupDirection.LEFT);
				this.editorGroupsService.addGroup(activeGroup, GroupDirection.RIGHT);
1262 1263 1264 1265 1266
			}
		}

		// Leave Centered Editor Layout
		else {
1267 1268
			if (this.editorGroupsService.count === 3) {
				this.editorGroupsService.groups.forEach(group => {
1269
					if (group.count === 0) {
1270
						this.editorGroupsService.removeGroup(group);
1271 1272 1273 1274 1275
					}
				});
			}
		}

1276 1277 1278
		if (!skipLayout) {
			this.layout();
		}
S
SrTobi 已提交
1279 1280
	}

1281
	resizePart(part: Parts, sizeChange: number): void {
1282 1283 1284 1285 1286 1287 1288
		switch (part) {
			case Parts.SIDEBAR_PART:
			case Parts.PANEL_PART:
			case Parts.EDITOR_PART:
				this.workbenchLayout.resizePart(part, sizeChange);
				break;
			default:
B
Benjamin Pasero 已提交
1289
				return; // Cannot resize other parts
1290 1291 1292
		}
	}

1293 1294
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1295

1296 1297 1298
		// Layout
		if (!skipLayout) {
			this.workbenchLayout.layout();
1299
		}
1300
	}
1301

1302 1303 1304 1305 1306 1307 1308
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): TPromise<void> {
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
			this.workbench.addClass('nosidebar');
1309
		} else {
1310 1311 1312 1313 1314 1315 1316
			this.workbench.removeClass('nosidebar');
		}

		// 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(() => {
1317
				const activeEditor = this.editorService.activeControl;
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
				const activePanel = this.panelPart.getActivePanel();

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

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

1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
		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();
			}
		});
	}

	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(() => {

				// Pass Focus to Editor if Panel part is now hidden
1370
				const editor = this.editorService.activeControl;
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 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
				if (editor) {
					editor.focus();
				}
			});
		}

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

	//#endregion
J
Johannes Rieken 已提交
1460
}