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

6
import 'vs/workbench/browser/style';
7

8 9
import { localize } from 'vs/nls';
import { setFileNameComparer } from 'vs/base/common/comparers';
B
Benjamin Pasero 已提交
10
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
11 12
import { Event, Emitter, setGlobalLeakWarningThreshold } from 'vs/base/common/event';
import { EventType, addDisposableListener, addClasses, addClass, removeClass, isAncestor, getClientArea, position, size, removeClasses } from 'vs/base/browser/dom';
13
import { runWhenIdle, IdleValue } from 'vs/base/common/async';
14 15 16
import { getZoomLevel, onDidChangeFullscreen, isFullscreen, getZoomFactor } from 'vs/base/browser/browser';
import { mark } from 'vs/base/common/performance';
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
17
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
18
import { Registry } from 'vs/platform/registry/common/platform';
19
import { isWindows, isLinux, isMacintosh, language } from 'vs/base/common/platform';
20
import { IResourceInput } from 'vs/platform/editor/common/editor';
J
Johannes Rieken 已提交
21
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
22
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, IUntitledResourceInput, IResourceDiffInput, InEditorZenModeContext } from 'vs/workbench/common/editor';
J
Johannes Rieken 已提交
23
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
24
import { SidebarPart, SidebarVisibleContext } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
J
Johannes Rieken 已提交
25 26
import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { StatusbarPart } from 'vs/workbench/browser/parts/statusbar/statusbarPart';
B
Benjamin Pasero 已提交
27
import { TitlebarPart } from 'vs/workbench/browser/parts/titlebar/titlebarPart';
28
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
29
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
J
Johannes Rieken 已提交
30 31
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
C
Christof Marti 已提交
32 33
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput';
J
Johannes Rieken 已提交
34
import { getServices } from 'vs/platform/instantiation/common/extensions';
35
import { Position, Parts, IPartService, IDimension, PositionToString, ILayoutOptions } from 'vs/workbench/services/part/common/partService';
36
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
37
import { IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage';
S
SteVen Batten 已提交
38
import { ContextMenuService as HTMLContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
J
Johannes Rieken 已提交
39
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
40
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
J
Johannes Rieken 已提交
41
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
42 43
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
44
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
I
isidor 已提交
45
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
B
Benjamin Pasero 已提交
46
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
J
Johannes Rieken 已提交
47 48 49
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
B
Benjamin Pasero 已提交
50
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
J
Johannes Rieken 已提交
51
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
52
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
J
Johannes Rieken 已提交
53 54 55
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';
56
import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService';
J
Johannes Rieken 已提交
57
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
58
import { IProgressService2 } from 'vs/platform/progress/common/progress';
59
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
60
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
61
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
62
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
63
import { LifecyclePhase, StartupKind, ILifecycleService, WillShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle';
64
import { IWindowService, IWindowConfiguration, IPath, MenuBarVisibility, getTitleBarStyle, IWindowsService } from 'vs/platform/windows/common/windows';
J
Johannes Rieken 已提交
65
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
66
import { IMenuService } from 'vs/platform/actions/common/actions';
67
import { MenuService } from 'vs/platform/actions/common/menuService';
S
SteVen Batten 已提交
68
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
J
Johannes Rieken 已提交
69
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
70
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
71
import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService';
J
Johannes Rieken 已提交
72
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
I
isidor 已提交
73
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
J
Joao Moreno 已提交
74
import { IListService, ListService } from 'vs/platform/list/browser/listService';
75
import { IViewsService } from 'vs/workbench/common/views';
S
Sandeep Somavarapu 已提交
76
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
77 78
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
79 80
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
81
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
82
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
83
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
S
Sandeep Somavarapu 已提交
84 85
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
86
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
87
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
88
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
S
SteVen Batten 已提交
89
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
A
Alex Dima 已提交
90
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
91
import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs';
S
SteVen Batten 已提交
92
import { Sizing, Direction, Grid, View } from 'vs/base/browser/ui/grid/grid';
I
isidor 已提交
93
import { IEditor } from 'vs/editor/common/editorCommon';
94
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
95 96 97 98 99 100
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { setARIAContainer } from 'vs/base/browser/ui/aria/aria';
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { ILogService } from 'vs/platform/log/common/log';
import { toErrorMessage } from 'vs/base/common/errorMessage';
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
import { ILabelService } from 'vs/platform/label/common/label';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
import { IHashService } from 'vs/workbench/services/hash/common/hashService';
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { combinedAppender, LogAppender, NullTelemetryService, configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
import { IDownloadService } from 'vs/platform/download/common/download';
import { IExtensionGalleryService, IExtensionManagementServerService, IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/workbench/services/commands/common/commandService';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { MarkerService } from 'vs/platform/markers/common/markerService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
import { ITextResourceConfigurationService, ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsServiceImpl';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ISearchService, ISearchHistoryService } from 'vs/workbench/services/search/common/search';
import { SearchHistoryService } from 'vs/workbench/services/search/common/searchHistoryService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorService } from 'vs/workbench/services/editor/browser/codeEditorService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
135
import { HistoryService } from 'vs/workbench/services/history/browser/history';
136
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
137
import { WorkbenchThemeService } from 'vs/workbench/services/themes/browser/workbenchThemeService';
138 139 140
import { IProductService } from 'vs/platform/product/common/product';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { ITextMateService } from 'vs/workbench/services/textMate/common/textMateService';
141
import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys';
142 143

// import@node
144 145 146 147
import { BackupFileService, InMemoryBackupFileService } from 'vs/workbench/services/backup/node/backupFileService';
import { WorkspaceService, DefaultConfigurationExportHelper } from 'vs/workbench/services/configuration/node/configurationService';
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
import { WorkspaceEditingService } from 'vs/workbench/services/workspace/node/workspaceEditingService';
148
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
import { HashService } from 'vs/workbench/services/hash/node/hashService';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { resolveWorkbenchCommonProperties } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { IRequestService } from 'vs/platform/request/node/request';
import { RequestService } from 'vs/platform/request/node/requestService';
import { DownloadService } from 'vs/platform/download/node/downloadService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/node/remoteAgentService';
import { DownloadServiceChannel } from 'vs/platform/download/node/downloadIpc';
import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
import { ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { MultiExtensionManagementService } from 'vs/workbench/services/extensionManagement/node/multiExtensionManagement';
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { IntegrityServiceImpl } from 'vs/workbench/services/integrity/node/integrityServiceImpl';
import { LocalizationsChannelClient } from 'vs/platform/localizations/node/localizationsIpc';
167 168
import { AccessibilityService } from 'vs/platform/accessibility/node/accessibilityService';
import { ProductService } from 'vs/platform/product/node/productService';
B
Benjamin Pasero 已提交
169
import { TextResourcePropertiesService } from 'vs/workbench/services/textfile/node/textResourcePropertiesService';
170 171

// import@electron-browser
172
import { ContextMenuService as NativeContextMenuService } from 'vs/workbench/services/contextmenu/electron-browser/contextmenuService';
173
import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
B
Benjamin Pasero 已提交
174
import { RemoteFileService } from 'vs/workbench/services/files/node/remoteFileService';
175 176 177
import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler';
178
import { DialogService, FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
179 180 181 182 183 184
import { IBroadcastService, BroadcastService } from 'vs/workbench/services/broadcast/electron-browser/broadcastService';
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionService } from 'vs/workbench/services/extensions/electron-browser/extensionService';
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
185

I
isidor 已提交
186 187
interface IZenModeSettings {
	fullScreen: boolean;
188
	centerLayout: boolean;
I
isidor 已提交
189
	hideTabs: boolean;
190
	hideActivityBar: boolean;
I
isidor 已提交
191
	hideStatusBar: boolean;
I
isidor 已提交
192
	hideLineNumbers: boolean;
I
isidor 已提交
193
	restore: boolean;
I
isidor 已提交
194 195
}

196
interface IWorkbenchStartedInfo {
197 198
	customKeybindingsCount: number;
	pinnedViewlets: string[];
199
	restoredViewlet: string;
200
	restoredEditorsCount: number;
201
}
202 203
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';

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

206 207
const Identifiers = {
	WORKBENCH_CONTAINER: 'workbench.main.container',
B
Benjamin Pasero 已提交
208
	TITLEBAR_PART: 'workbench.parts.titlebar',
209 210 211 212
	ACTIVITYBAR_PART: 'workbench.parts.activitybar',
	SIDEBAR_PART: 'workbench.parts.sidebar',
	PANEL_PART: 'workbench.parts.panel',
	EDITOR_PART: 'workbench.parts.editor',
S
SteVen Batten 已提交
213
	STATUSBAR_PART: 'workbench.parts.statusbar'
214 215
};

216 217 218 219 220 221 222 223 224
interface IZenMode {
	active: boolean;
	transitionedToFullScreen: boolean;
	transitionedToCenteredEditorLayout: boolean;
	transitionDisposeables: IDisposable[];
	wasSideBarVisible: boolean;
	wasPanelVisible: boolean;
}

225 226 227 228 229 230
interface IWorkbenchUIState {
	lastPanelHeight?: number;
	lastPanelWidth?: number;
	lastSidebarDimension?: number;
}

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

233
	private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
234
	private static readonly menubarVisibilityConfigurationKey = 'window.menuBarVisibility';
235 236
	private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
	private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
237
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
238
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
239
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
240 241 242 243
	private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
	private static readonly statusbarVisibleConfigurationKey = 'workbench.statusBar.visible';
	private static readonly activityBarVisibleConfigurationKey = 'workbench.activityBar.visible';
	private static readonly fontAliasingConfigurationKey = 'workbench.fontAliasing';
244

B
Benjamin Pasero 已提交
245 246
	_serviceBrand: any;

B
Benjamin Pasero 已提交
247 248 249 250 251 252
	private readonly _onShutdown = this._register(new Emitter<void>());
	get onShutdown(): Event<void> { return this._onShutdown.event; }

	private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
	get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }

253 254 255
	private previousErrorValue: string;
	private previousErrorTime: number = 0;

B
Benjamin Pasero 已提交
256
	private workbench: HTMLElement;
E
Erich Gamma 已提交
257
	private workbenchStarted: boolean;
B
Benjamin Pasero 已提交
258
	private workbenchRestored: boolean;
E
Erich Gamma 已提交
259
	private workbenchShutdown: boolean;
260

261 262
	private editorService: EditorService;
	private editorGroupService: IEditorGroupsService;
J
Joao Moreno 已提交
263
	private contextViewService: ContextViewService;
264
	private contextKeyService: IContextKeyService;
265
	private keybindingService: IKeybindingService;
266
	private backupFileService: IBackupFileService;
267 268 269 270 271
	private notificationService: NotificationService;
	private themeService: WorkbenchThemeService;
	private telemetryService: ITelemetryService;
	private windowService: IWindowService;
	private lifecycleService: LifecycleService;
272
	private fileService: IFileService;
273 274
	private quickInput: QuickInputService;

S
SteVen Batten 已提交
275
	private workbenchGrid: Grid<View> | WorkbenchLayout;
276

B
Benjamin Pasero 已提交
277
	private titlebarPart: TitlebarPart;
E
Erich Gamma 已提交
278 279
	private activitybarPart: ActivitybarPart;
	private sidebarPart: SidebarPart;
I
isidor 已提交
280
	private panelPart: PanelPart;
E
Erich Gamma 已提交
281 282
	private editorPart: EditorPart;
	private statusbarPart: StatusbarPart;
S
SteVen Batten 已提交
283 284 285 286 287 288 289 290

	private titlebarPartView: View;
	private activitybarPartView: View;
	private sidebarPartView: View;
	private panelPartView: View;
	private editorPartView: View;
	private statusbarPartView: View;

E
Erich Gamma 已提交
291
	private quickOpen: QuickOpenController;
292
	private notificationsCenter: NotificationsCenter;
293
	private notificationsToasts: NotificationsToasts;
294

S
SteVen Batten 已提交
295
	private editorHidden: boolean;
E
Erich Gamma 已提交
296
	private sideBarHidden: boolean;
297
	private statusBarHidden: boolean;
S
Sanders Lauture 已提交
298
	private activityBarHidden: boolean;
299
	private menubarToggled: boolean;
E
Erich Gamma 已提交
300
	private sideBarPosition: Position;
I
isidor 已提交
301
	private panelPosition: Position;
I
isidor 已提交
302
	private panelHidden: boolean;
S
SteVen Batten 已提交
303
	private menubarVisibility: MenuBarVisibility;
304 305
	private zenMode: IZenMode;
	private fontAliasing: FontAliasingOption;
306
	private hasInitialFilesToOpen: boolean;
307
	private shouldCenterLayout = false;
308 309 310 311 312
	private uiState: IWorkbenchUIState = {
		lastPanelHeight: 350,
		lastPanelWidth: 350,
		lastSidebarDimension: 300,
	};
313

314
	private inZenModeContext: IContextKey<boolean>;
315
	private sideBarVisibleContext: IContextKey<boolean>;
316

317
	constructor(
318
		private container: HTMLElement,
J
Joao Moreno 已提交
319
		private configuration: IWindowConfiguration,
B
Benjamin Pasero 已提交
320
		private serviceCollection: ServiceCollection,
321 322
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
B
Benjamin Pasero 已提交
323
		@IStorageService private readonly storageService: IStorageService,
324 325
		@IConfigurationService private readonly configurationService: WorkspaceService,
		@IEnvironmentService private readonly environmentService: IEnvironmentService,
326 327
		@ILogService private readonly logService: ILogService,
		@IWindowsService private readonly windowsService: IWindowsService
328
	) {
329
		super();
E
Erich Gamma 已提交
330

331
		this.hasInitialFilesToOpen = !!(
B
Benjamin Pasero 已提交
332 333
			(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
			(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
334
			(configuration.filesToDiff && configuration.filesToDiff.length > 0));
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352

		this.registerErrorHandler();
	}

	private registerErrorHandler(): void {

		// Listen on unhandled rejection events
		window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {

			// See https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
			onUnexpectedError(event.reason);

			// Prevent the printing of this event to the console
			event.preventDefault();
		});

		// Install handler for unexpected errors
		setUnexpectedErrorHandler(error => this.handleUnexpectedError(error));
353 354 355 356 357 358 359 360 361

		// Inform user about loading issues from the loader
		(<any>self).require.config({
			onError: err => {
				if (err.errorCode === 'load') {
					onUnexpectedError(new Error(localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err))));
				}
			}
		});
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
	}

	private handleUnexpectedError(error: any): void {
		const errorMsg = toErrorMessage(error, true);
		if (!errorMsg) {
			return;
		}

		const now = Date.now();
		if (errorMsg === this.previousErrorValue && now - this.previousErrorTime <= 1000) {
			return; // Return if error message identical to previous and shorter than 1 second
		}

		this.previousErrorTime = now;
		this.previousErrorValue = errorMsg;

		// Log it
		this.logService.error(errorMsg);

		// Show to user if friendly message provided
		if (error && error.friendlyMessage && this.notificationService) {
			this.notificationService.error(error.friendlyMessage);
		}
	}

387
	startup(): void {
388
		try {
389
			this.doStartup().then(undefined, error => this.logService.error(toErrorMessage(error, true)));
390 391 392 393 394
		} catch (error) {
			this.logService.error(toErrorMessage(error, true));

			throw error; // rethrow because this is a critical issue we cannot handle properly here
		}
395 396
	}

397
	private doStartup(): Promise<void> {
398
		this.workbenchStarted = true;
E
Erich Gamma 已提交
399

B
Benjamin Pasero 已提交
400 401 402
		// Logging
		this.logService.trace('workbench configuration', JSON.stringify(this.configuration));

403 404 405 406 407 408 409 410 411 412 413 414
		// Configure emitter leak warning threshold
		setGlobalLeakWarningThreshold(175);

		// Setup Intl for comparers
		setFileNameComparer(new IdleValue(() => {
			const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
			return {
				collator: collator,
				collatorIsNumeric: collator.resolvedOptions().numeric
			};
		}));

415 416 417 418 419 420 421 422 423 424
		// ARIA
		setARIAContainer(document.body);

		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getValue('editor'), getZoomLevel()));
		this._register(this.storageService.onWillSaveState(() => {
			saveFontInfo(this.storageService); // Keep font info for next startup around
		}));

B
Benjamin Pasero 已提交
425
		// Create Workbench Container
426
		this.createWorkbench();
E
Erich Gamma 已提交
427

428
		// Services
B
Benjamin Pasero 已提交
429
		this.initServices(this.serviceCollection);
E
Erich Gamma 已提交
430

431
		// Context Keys
432 433 434
		this._register(this.instantiationService.createInstance(WorkbenchContextKeysHandler));
		this.inZenModeContext = InEditorZenModeContext.bindTo(this.contextKeyService);
		this.sideBarVisibleContext = SidebarVisibleContext.bindTo(this.contextKeyService);
J
Joao Moreno 已提交
435

436 437
		// Register Listeners
		this.registerListeners();
E
Erich Gamma 已提交
438

439 440
		// Settings
		this.initSettings();
E
Erich Gamma 已提交
441

442 443
		// Create Workbench and Parts
		this.renderWorkbench();
444

445 446
		// Workbench Layout
		this.createWorkbenchLayout();
B
polish  
Benjamin Pasero 已提交
447

448 449 450 451
		// Layout
		this.layout();

		// Handle case where workbench is not starting up properly
452
		const timeoutHandle = setTimeout(() => this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.'), 10000);
453
		this.lifecycleService.when(LifecyclePhase.Restored).then(() => clearTimeout(timeoutHandle));
454

455
		// Restore Parts
B
Benjamin Pasero 已提交
456 457
		return this.restoreParts();
	}
458

B
Benjamin Pasero 已提交
459
	private createWorkbench(): void {
B
Benjamin Pasero 已提交
460 461
		this.workbench = document.createElement('div');
		this.workbench.id = Identifiers.WORKBENCH_CONTAINER;
462

463 464 465 466
		const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac';

		addClasses(this.workbench, 'monaco-workbench', platformClass);
		addClasses(document.body, platformClass); // used by our fonts
467
	}
E
Erich Gamma 已提交
468

B
Benjamin Pasero 已提交
469
	private initServices(serviceCollection: ServiceCollection): void {
470

471
		// Parts
472
		serviceCollection.set(IPartService, this);
E
Erich Gamma 已提交
473

474 475 476
		// Labels
		serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true));

477
		// Clipboard
J
Johannes Rieken 已提交
478
		serviceCollection.set(IClipboardService, new SyncDescriptor(ClipboardService));
479

480 481 482 483 484 485 486 487 488 489 490
		// Broadcast
		serviceCollection.set(IBroadcastService, new SyncDescriptor(BroadcastService, [this.configuration.windowId]));

		// Notifications
		this.notificationService = new NotificationService();
		serviceCollection.set(INotificationService, this.notificationService);

		// Window
		this.windowService = this.instantiationService.createInstance(WindowService, this.configuration);
		serviceCollection.set(IWindowService, this.windowService);

491 492 493 494
		// Product
		const productService = new ProductService();
		serviceCollection.set(IProductService, productService);

495 496 497 498 499 500 501 502 503 504
		// Shared Process
		const sharedProcess = this.windowsService.whenSharedProcessReady()
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${this.configuration.windowId}`))
			.then(client => {
				client.registerChannel('dialog', this.instantiationService.createInstance(DialogChannel));

				return client;
			});

		// Telemetry
505
		if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!productService.enableTelemetry) {
506 507 508
			const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender')));
			const config: ITelemetryServiceConfig = {
				appender: combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(this.logService)),
509
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, productService.commit, productService.version, this.configuration.machineId, this.environmentService.installSourcePath),
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
			};

			this.telemetryService = this._register(this.instantiationService.createInstance(TelemetryService, config));
			this._register(new ErrorTelemetry(this.telemetryService));
		} else {
			this.telemetryService = NullTelemetryService;
		}

		serviceCollection.set(ITelemetryService, this.telemetryService);
		this._register(configurationTelemetry(this.telemetryService, this.configurationService));

		// Dialogs
		serviceCollection.set(IDialogService, this.instantiationService.createInstance(DialogService));

		// Lifecycle
		this.lifecycleService = this.instantiationService.createInstance(LifecycleService);
		this.lifecycleService.phase = LifecyclePhase.Ready; // Set lifecycle phase to `Ready`

		serviceCollection.set(ILifecycleService, this.lifecycleService);

B
Benjamin Pasero 已提交
531 532 533 534 535
		this._register(this.lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event)));
		this._register(this.lifecycleService.onShutdown(() => {
			this._onShutdown.fire();
			this.dispose();
		}));
536 537 538 539 540 541 542 543 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 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627

		// Request Service
		serviceCollection.set(IRequestService, new SyncDescriptor(RequestService, undefined, true));

		// Download Service
		serviceCollection.set(IDownloadService, new SyncDescriptor(DownloadService, undefined, true));

		// Extension Gallery
		serviceCollection.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService, undefined, true));

		// Remote Resolver
		const remoteAuthorityResolverService = new RemoteAuthorityResolverService();
		serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);

		// Remote Agent
		const remoteAgentService = new RemoteAgentService(this.configuration, this.notificationService, this.environmentService, remoteAuthorityResolverService);
		serviceCollection.set(IRemoteAgentService, remoteAgentService);

		const remoteAgentConnection = remoteAgentService.getConnection();
		if (remoteAgentConnection) {
			remoteAgentConnection.registerChannel('dialog', this.instantiationService.createInstance(DialogChannel));
			remoteAgentConnection.registerChannel('download', new DownloadServiceChannel());
			remoteAgentConnection.registerChannel('loglevel', new LogLevelSetterChannel(this.logService));
		}

		// Extensions Management
		const extensionManagementChannel = getDelayedChannel(sharedProcess.then(c => c.getChannel('extensions')));
		const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
		serviceCollection.set(IExtensionManagementServerService, new SyncDescriptor(ExtensionManagementServerService, [extensionManagementChannelClient]));
		serviceCollection.set(IExtensionManagementService, new SyncDescriptor(MultiExtensionManagementService));

		// Extension Enablement
		const extensionEnablementService = this._register(this.instantiationService.createInstance(ExtensionEnablementService));
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);

		// Extensions
		serviceCollection.set(IExtensionService, this.instantiationService.createInstance(ExtensionService));

		// Theming
		this.themeService = this.instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

		// Commands
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService, undefined, true));

		// Markers
		serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService, undefined, true));

		// Editor Mode
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));

		// Text Resource Config
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

		// Text Resource Properties
		serviceCollection.set(ITextResourcePropertiesService, new SyncDescriptor(TextResourcePropertiesService));

		// Editor Models
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl, undefined, true));

		// Marker Decorations
		serviceCollection.set(IMarkerDecorationsService, new SyncDescriptor(MarkerDecorationsService));

		// Editor Worker
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));

		// Untitled Editors
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService, undefined, true));

		// Text Mate
		serviceCollection.set(ITextMateService, new SyncDescriptor(TextMateService));

		// Search
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
		serviceCollection.set(ISearchHistoryService, new SyncDescriptor(SearchHistoryService));

		// Code Editor
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorService));

		// Opener
		serviceCollection.set(IOpenerService, new SyncDescriptor(OpenerService, undefined, true));

		// Integrity
		serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));

		// Localization
		const localizationsChannel = getDelayedChannel(sharedProcess.then(c => c.getChannel('localizations')));
		serviceCollection.set(ILocalizationsService, new SyncDescriptor(LocalizationsChannelClient, [localizationsChannel]));

		// Hash
		serviceCollection.set(IHashService, new SyncDescriptor(HashService, undefined, true));

628 629 630 631
		// Status bar
		this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
		serviceCollection.set(IStatusbarService, this.statusbarPart);

632 633 634
		// Progress 2
		serviceCollection.set(IProgressService2, new SyncDescriptor(ProgressService2));

635
		// Keybindings
A
Alex Dima 已提交
636
		this.contextKeyService = this.instantiationService.createInstance(ContextKeyService);
637
		serviceCollection.set(IContextKeyService, this.contextKeyService);
638

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

642 643 644
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

J
Joao Moreno 已提交
645
		// Context view service
B
Benjamin Pasero 已提交
646
		this.contextViewService = this.instantiationService.createInstance(ContextViewService, this.workbench);
J
Joao Moreno 已提交
647 648
		serviceCollection.set(IContextViewService, this.contextViewService);

S
SteVen Batten 已提交
649
		// Use themable context menus when custom titlebar is enabled to match custom menubar
B
Benjamin Pasero 已提交
650
		if (!isMacintosh && this.useCustomTitleBarStyle()) {
J
fix npe  
Johannes Rieken 已提交
651
			serviceCollection.set(IContextMenuService, new SyncDescriptor(HTMLContextMenuService, [null]));
S
SteVen Batten 已提交
652 653 654
		} else {
			serviceCollection.set(IContextMenuService, new SyncDescriptor(NativeContextMenuService));
		}
655

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

P
Pine Wu 已提交
659
		// Sidebar part
660
		this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
P
Pine Wu 已提交
661 662

		// Viewlet service
I
isidor 已提交
663
		serviceCollection.set(IViewletService, this.sidebarPart);
E
Erich Gamma 已提交
664

I
isidor 已提交
665
		// Panel service (panel part)
666 667
		this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
		serviceCollection.set(IPanelService, this.panelPart);
I
isidor 已提交
668

669 670 671
		// views service
		const viewsService = this.instantiationService.createInstance(ViewsService);
		serviceCollection.set(IViewsService, viewsService);
S
Sandeep Somavarapu 已提交
672

E
Erich Gamma 已提交
673
		// Activity service (activitybar part)
674
		this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
I
isidor 已提交
675 676
		const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
		serviceCollection.set(IActivityService, activityService);
E
Erich Gamma 已提交
677

678 679 680
		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
S
#47154  
Sandeep Somavarapu 已提交
681
		this.configurationService.acquireFileService(this.fileService);
A
Alex Dima 已提交
682
		this.themeService.acquireFileService(this.fileService);
683

684 685
		// Editor and Group services
		const restorePreviousEditorState = !this.hasInitialFilesToOpen;
686
		this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
B
Benjamin Pasero 已提交
687
		this.editorGroupService = this.editorPart;
688 689 690
		serviceCollection.set(IEditorGroupsService, this.editorPart);
		this.editorService = this.instantiationService.createInstance(EditorService);
		serviceCollection.set(IEditorService, this.editorService);
E
Erich Gamma 已提交
691

692 693 694
		// Accessibility
		serviceCollection.set(IAccessibilityService, new SyncDescriptor(AccessibilityService, undefined, true));

695 696 697
		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
		serviceCollection.set(ITitleService, this.titlebarPart);
B
Benjamin Pasero 已提交
698

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

M
Martin Aeschlimann 已提交
702
		// File Dialogs
703
		serviceCollection.set(IFileDialogService, new SyncDescriptor(FileDialogService));
M
Martin Aeschlimann 已提交
704

705
		// Backup File Service
B
Benjamin Pasero 已提交
706 707
		if (this.configuration.backupPath) {
			this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.configuration.backupPath);
B
Benjamin Pasero 已提交
708 709 710
		} else {
			this.backupFileService = new InMemoryBackupFileService();
		}
711
		serviceCollection.set(IBackupFileService, this.backupFileService);
712

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

716
		// File Decorations
J
Johannes Rieken 已提交
717
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));
718

J
Joao Moreno 已提交
719
		// Inactive extension URL handler
J
Joao Moreno 已提交
720
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));
J
Joao Moreno 已提交
721

B
Benjamin Pasero 已提交
722
		// Text Model Resolver Service
723
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));
B
Benjamin Pasero 已提交
724

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

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

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

735
		// Configuration Resolver
736
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, [process.env]));
737

E
Erich Gamma 已提交
738
		// Quick open service (quick open controller)
739 740
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
		serviceCollection.set(IQuickOpenService, this.quickOpen);
741

C
Christof Marti 已提交
742 743 744 745
		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
		serviceCollection.set(IQuickInputService, this.quickInput);

S
Sandeep Somavarapu 已提交
746 747 748
		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

B
polish  
Benjamin Pasero 已提交
749
		// Contributed services
B
Benjamin Pasero 已提交
750
		const contributedServices = getServices();
E
Erich Gamma 已提交
751
		for (let contributedService of contributedServices) {
752
			serviceCollection.set(contributedService.id, contributedService.descriptor);
E
Erich Gamma 已提交
753 754 755
		}

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

760
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
761

B
Benjamin Pasero 已提交
762
		this.configurationService.acquireInstantiationService(this.instantiationService);
E
Erich Gamma 已提交
763 764
	}

765
	//#region event handling
E
Erich Gamma 已提交
766

767
	private registerListeners(): void {
I
isidor 已提交
768

769
		// Storage
770
		this._register(this.storageService.onWillSaveState(e => this.saveState(e)));
771

772 773 774
		// Restore editor if hidden and it changes
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.restoreHiddenEditor()));
		this._register(this.editorPart.onDidActivateGroup(() => this.restoreHiddenEditor()));
S
Sanders Lauture 已提交
775

776
		// Configuration changes
777
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
I
isidor 已提交
778

779
		// Fullscreen changes
780
		this._register(onDidChangeFullscreen(() => this.onFullscreenChanged()));
B
Benjamin Pasero 已提交
781 782 783 784

		// Group changes
		this._register(this.editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.shouldCenterLayout)));
		this._register(this.editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.shouldCenterLayout)));
785 786

		// Prevent workbench from scrolling #55456
787
		this._register(addDisposableListener(this.workbench, EventType.SCROLL, () => this.workbench.scrollTop = 0));
788
	}
789

790
	private onFullscreenChanged(): void {
S
SrTobi 已提交
791

792
		// Apply as CSS class
793 794
		if (isFullscreen()) {
			addClass(this.workbench, 'fullscreen');
795
		} else {
796
			removeClass(this.workbench, 'fullscreen');
B
Benjamin Pasero 已提交
797

798 799 800 801
			if (this.zenMode.transitionedToFullScreen && this.zenMode.active) {
				this.toggleZenMode();
			}
		}
E
Erich Gamma 已提交
802

803
		// Changing fullscreen state of the window has an impact on custom title bar visibility, so we need to update
B
Benjamin Pasero 已提交
804
		if (this.useCustomTitleBarStyle()) {
805 806 807
			this._onTitleBarVisibilityChange.fire();
			this.layout(); // handle title bar when fullscreen changes
		}
808 809
	}

810 811 812 813
	private onMenubarToggled(visible: boolean) {
		if (visible !== this.menubarToggled) {
			this.menubarToggled = visible;

814
			if (isFullscreen() && (this.menubarVisibility === 'toggle' || this.menubarVisibility === 'default')) {
815
				this._onTitleBarVisibilityChange.fire();
816 817 818 819 820
				this.layout();
			}
		}
	}

821
	private restoreHiddenEditor(): void {
822 823 824
		if (this.editorHidden) {
			this.setEditorHidden(false);
		}
825 826
	}

827 828 829 830 831
	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);
832
		}
E
Erich Gamma 已提交
833

834
		this.setPanelPositionFromStorageOrConfig();
E
Erich Gamma 已提交
835

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

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

847 848 849 850
			const newActivityBarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.activityBarVisibleConfigurationKey);
			if (newActivityBarHiddenValue !== this.activityBarHidden) {
				this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout);
			}
B
Benjamin Pasero 已提交
851
		}
S
SteVen Batten 已提交
852

853
		const newMenubarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
854
		this.setMenubarVisibility(newMenubarVisibility, !!skipLayout);
855
	}
B
Benjamin Pasero 已提交
856

857
	//#endregion
B
Benjamin Pasero 已提交
858

859
	private restoreParts(): Promise<void> {
J
Johannes Rieken 已提交
860
		const restorePromises: Promise<any>[] = [];
B
Benjamin Pasero 已提交
861

862
		// Restore Editorpart
863
		mark('willRestoreEditors');
864
		restorePromises.push(this.editorPart.whenRestored.then(() => {
B
Benjamin Pasero 已提交
865 866 867 868

			function openEditors(editors: IResourceEditor[], editorService: IEditorService) {
				if (editors.length) {
					return editorService.openEditors(editors);
869
				}
E
Erich Gamma 已提交
870

J
Johannes Rieken 已提交
871
				return Promise.resolve(undefined);
B
Benjamin Pasero 已提交
872 873 874 875 876 877 878 879 880
			}

			const editorsToOpen = this.resolveEditorsToOpen();

			if (Array.isArray(editorsToOpen)) {
				return openEditors(editorsToOpen, this.editorService);
			}

			return editorsToOpen.then(editors => openEditors(editors, this.editorService));
881
		}).then(() => mark('didRestoreEditors')));
E
Erich Gamma 已提交
882

883
		// Restore Sidebar
884
		let viewletIdToRestore: string | undefined;
885 886
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);
887

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

892
			if (!viewletIdToRestore) {
I
isidor 已提交
893
				viewletIdToRestore = this.sidebarPart.getDefaultViewletId();
894
			}
E
Erich Gamma 已提交
895

896
			mark('willRestoreViewlet');
I
isidor 已提交
897 898
			restorePromises.push(this.sidebarPart.openViewlet(viewletIdToRestore)
				.then(viewlet => viewlet || this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId()))
899
				.then(() => mark('didRestoreViewlet')));
900 901
		}

902 903
		// Restore Panel
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
904
		const panelId = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
905
		if (!this.panelHidden && !!panelId) {
906
			mark('willRestorePanel');
907
			const isPanelToRestoreEnabled = !!this.panelPart.getPanels().filter(p => p.id === panelId).length;
908
			const panelIdToRestore = isPanelToRestoreEnabled ? panelId : panelRegistry.getDefaultPanelId();
909
			this.panelPart.openPanel(panelIdToRestore, false);
910
			mark('didRestorePanel');
I
isidor 已提交
911 912
		}

913 914 915
		// Restore Zen Mode if active and supported for restore on startup
		const zenConfig = this.configurationService.getValue<IZenModeSettings>('zenMode');
		const wasZenActive = this.storageService.getBoolean(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE, false);
916
		if (wasZenActive && zenConfig.restore) {
I
isidor 已提交
917
			this.toggleZenMode(true, true);
I
isidor 已提交
918 919
		}

B
Benjamin Pasero 已提交
920
		// Restore Forced Editor Center Mode
921
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
I
isidor 已提交
922
			this.centerEditorLayout(true);
S
SrTobi 已提交
923
		}
924

925
		const onRestored = (error?: Error): void => {
B
Benjamin Pasero 已提交
926 927 928 929 930
			this.workbenchRestored = true;

			// Set lifecycle phase to `Restored`
			this.lifecycleService.phase = LifecyclePhase.Restored;

931 932 933 934 935 936 937
			// Set lifecycle phase to `Eventually` after a short delay and when
			// idle (min 2.5sec, max 5sec)
			setTimeout(() => {
				this._register(runWhenIdle(() => {
					this.lifecycleService.phase = LifecyclePhase.Eventually;
				}, 2500));
			}, 2500);
938

939
			if (error) {
940
				onUnexpectedError(error);
941
			}
I
isidor 已提交
942

943
			this.logStartupTelemetry({
944
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
P
Pine Wu 已提交
945
				pinnedViewlets: this.activitybarPart.getPinnedViewletIds(),
946
				restoredViewlet: viewletIdToRestore,
947
				restoredEditorsCount: this.editorService.visibleEditors.length
948
			});
949
		};
950

B
Benjamin Pasero 已提交
951
		return Promise.all(restorePromises).then(() => onRestored(), error => onRestored(error));
E
Erich Gamma 已提交
952 953
	}

954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
	private logStartupTelemetry(info: IWorkbenchStartedInfo): void {
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;

		/* __GDPR__
			"workspaceLoad" : {
				"userAgent" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"windowSize.innerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"windowSize.innerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"windowSize.outerHeight": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"windowSize.outerWidth": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"emptyWorkbench": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"workbench.filesToOpen": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"workbench.filesToCreate": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"workbench.filesToDiff": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"customKeybindingsCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"theme": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"language": { "classification": "SystemMetaData", "purpose": "BusinessInsight" },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredViewlet": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"restoredEditors": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
				"pinnedViewlets": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
				"startupKind": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
			}
		*/
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
			emptyWorkbench: this.contextService.getWorkbenchState() === WorkbenchState.EMPTY,
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || 0,
			customKeybindingsCount: info.customKeybindingsCount,
			theme: this.themeService.getColorTheme().id,
			language,
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
			restoredEditors: info.restoredEditorsCount,
			startupKind: this.lifecycleService.startupKind
		});

		// Telemetry: startup metrics
		mark('didStartWorkbench');
	}

998 999 1000
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
E
Erich Gamma 已提交
1001 1002
		}

1003 1004
		// always restore sidebar when the window was reloaded
		return this.lifecycleService.startupKind === StartupKind.ReloadedWindow;
E
Erich Gamma 已提交
1005 1006
	}

J
Johannes Rieken 已提交
1007
	private resolveEditorsToOpen(): Promise<IResourceEditor[]> | IResourceEditor[] {
I
isidor 已提交
1008

B
Benjamin Pasero 已提交
1009
		// Files to open, diff or create
1010
		if (this.hasInitialFilesToOpen) {
I
isidor 已提交
1011

B
Benjamin Pasero 已提交
1012
			// Files to diff is exclusive
B
Benjamin Pasero 已提交
1013
			const filesToDiff = this.toInputs(this.configuration.filesToDiff, false);
1014
			if (filesToDiff && filesToDiff.length === 2) {
B
Benjamin Pasero 已提交
1015
				return [<IResourceDiffInput>{
1016 1017
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
B
Benjamin Pasero 已提交
1018
					options: { pinned: true },
B
Benjamin Pasero 已提交
1019
					forceFile: true
B
Benjamin Pasero 已提交
1020
				}];
B
Benjamin Pasero 已提交
1021
			}
I
isidor 已提交
1022

B
Benjamin Pasero 已提交
1023 1024
			const filesToCreate = this.toInputs(this.configuration.filesToCreate, true);
			const filesToOpen = this.toInputs(this.configuration.filesToOpen, false);
I
isidor 已提交
1025

1026
			// Otherwise: Open/Create files
B
Benjamin Pasero 已提交
1027
			return [...filesToOpen, ...filesToCreate];
B
Benjamin Pasero 已提交
1028
		}
I
isidor 已提交
1029

1030
		// Empty workbench
1031
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
B
Benjamin Pasero 已提交
1032
			const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
1033
			if (!isEmpty) {
B
Benjamin Pasero 已提交
1034
				return []; // do not open any empty untitled file if we restored editors from previous session
1035
			}
B
Benjamin Pasero 已提交
1036

1037 1038
			return this.backupFileService.hasBackups().then(hasBackups => {
				if (hasBackups) {
B
Benjamin Pasero 已提交
1039
					return []; // do not open any empty untitled file if we have backups to restore
1040
				}
B
Benjamin Pasero 已提交
1041

B
Benjamin Pasero 已提交
1042
				return [<IUntitledResourceInput>{}];
1043
			});
1044
		}
1045

B
Benjamin Pasero 已提交
1046
		return [];
B
Benjamin Pasero 已提交
1047
	}
1048

1049
	private toInputs(paths: IPath[], isNew: boolean): Array<IResourceInput | IUntitledResourceInput> {
B
Benjamin Pasero 已提交
1050 1051
		if (!paths || !paths.length) {
			return [];
1052
		}
I
isidor 已提交
1053

B
Benjamin Pasero 已提交
1054
		return paths.map(p => {
1055
			const resource = p.fileUri;
1056 1057 1058 1059
			let input: IResourceInput | IUntitledResourceInput;
			if (isNew) {
				input = { filePath: resource.fsPath, options: { pinned: true } } as IUntitledResourceInput;
			} else {
B
Benjamin Pasero 已提交
1060
				input = { resource, options: { pinned: true }, forceFile: true } as IResourceInput;
1061
			}
E
Erich Gamma 已提交
1062

1063
			if (!isNew && p.lineNumber) {
B
Benjamin Pasero 已提交
1064 1065 1066 1067 1068
				input.options.selection = {
					startLineNumber: p.lineNumber,
					startColumn: p.columnNumber
				};
			}
1069

B
Benjamin Pasero 已提交
1070 1071
			return input;
		});
1072 1073
	}

1074
	private openUntitledFile() {
1075
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');
B
Benjamin Pasero 已提交
1076 1077

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

1085
		return startupEditor.value === 'newUntitledFile';
1086
	}
E
Erich Gamma 已提交
1087 1088

	private initSettings(): void {
1089

S
SteVen Batten 已提交
1090 1091 1092
		// Editor visiblity
		this.editorHidden = false;

E
Erich Gamma 已提交
1093
		// Sidebar visibility
1094
		this.sideBarHidden = this.storageService.getBoolean(Workbench.sidebarHiddenStorageKey, StorageScope.WORKSPACE, this.contextService.getWorkbenchState() === WorkbenchState.EMPTY);
1095

I
isidor 已提交
1096
		// Panel part visibility
1097
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
1098
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
1099 1100
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
1101 1102
		}

E
Erich Gamma 已提交
1103
		// Sidebar position
1104
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
1105
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
1106

I
isidor 已提交
1107
		// Panel position
1108
		this.setPanelPositionFromStorageOrConfig();
1109

1110
		// Menubar visibility
1111
		const menuBarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
S
SteVen Batten 已提交
1112
		this.setMenubarVisibility(menuBarVisibility, true);
1113

B
Benjamin Pasero 已提交
1114
		// Statusbar visibility
1115
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
1116
		this.statusBarHidden = !statusBarVisible;
1117

S
Sanders Lauture 已提交
1118
		// Activity bar visibility
1119
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
S
Sanders Lauture 已提交
1120
		this.activityBarHidden = !activityBarVisible;
1121

1122
		// Font aliasing
1123
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
1124

I
isidor 已提交
1125 1126
		// Zen mode
		this.zenMode = {
I
isidor 已提交
1127
			active: false,
1128
			transitionedToFullScreen: false,
1129
			transitionedToCenteredEditorLayout: false,
1130
			wasSideBarVisible: false,
1131 1132
			wasPanelVisible: false,
			transitionDisposeables: []
I
isidor 已提交
1133
		};
E
Erich Gamma 已提交
1134 1135
	}

1136 1137
	private setPanelPositionFromStorageOrConfig() {
		const defaultPanelPosition = this.configurationService.getValue<string>(Workbench.defaultPanelPositionStorageKey);
1138
		const panelPosition = this.storageService.get(Workbench.panelPositionStorageKey, StorageScope.WORKSPACE, defaultPanelPosition);
1139

1140 1141
		this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
	}
1142

B
Benjamin Pasero 已提交
1143 1144
	private useCustomTitleBarStyle(): boolean {
		return getTitleBarStyle(this.configurationService, this.environmentService) === 'custom';
B
Benjamin Pasero 已提交
1145 1146
	}

1147
	private saveLastPanelDimension(): void {
S
SteVen Batten 已提交
1148
		if (!(this.workbenchGrid instanceof Grid)) {
1149 1150 1151 1152
			return;
		}

		if (this.panelPosition === Position.BOTTOM) {
S
SteVen Batten 已提交
1153
			this.uiState.lastPanelHeight = this.workbenchGrid.getViewSize(this.panelPartView);
1154
		} else {
S
SteVen Batten 已提交
1155
			this.uiState.lastPanelWidth = this.workbenchGrid.getViewSize(this.panelPartView);
1156 1157 1158 1159 1160 1161 1162
		}
	}

	private getLastPanelDimension(position: Position): number | undefined {
		return position === Position.BOTTOM ? this.uiState.lastPanelHeight : this.uiState.lastPanelWidth;
	}

1163 1164
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
1165

1166 1167
		// Adjust CSS
		if (hidden) {
1168
			addClass(this.workbench, 'nostatusbar');
E
Erich Gamma 已提交
1169
		} else {
1170
			removeClass(this.workbench, 'nostatusbar');
E
Erich Gamma 已提交
1171 1172
		}

1173 1174
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1175
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1176
				this.layout();
1177 1178 1179
			} else {
				this.workbenchGrid.layout();
			}
1180 1181 1182
		}
	}

1183
	private setFontAliasing(aliasing: FontAliasingOption) {
1184
		this.fontAliasing = aliasing;
S
Sanders Lauture 已提交
1185

B
Benjamin Pasero 已提交
1186
		// Remove all
1187
		removeClasses(this.workbench, ...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));
B
Benjamin Pasero 已提交
1188 1189 1190

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
1191
			addClass(this.workbench, `monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
1192
		}
1193 1194
	}

E
Erich Gamma 已提交
1195
	private createWorkbenchLayout(): void {
1196
		if (this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
1197

S
SteVen Batten 已提交
1198 1199 1200 1201 1202 1203 1204 1205 1206
			// Create view wrappers for all parts
			this.titlebarPartView = new View(this.titlebarPart);
			this.sidebarPartView = new View(this.sidebarPart);
			this.activitybarPartView = new View(this.activitybarPart);
			this.editorPartView = new View(this.editorPart);
			this.panelPartView = new View(this.panelPart);
			this.statusbarPartView = new View(this.statusbarPart);

			this.workbenchGrid = new Grid(this.editorPartView, { proportionalLayout: false });
1207

1208
			this.workbench.prepend(this.workbenchGrid.element);
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
		} else {
			this.workbenchGrid = this.instantiationService.createInstance(
				WorkbenchLayout,
				this.container,
				this.workbench,
				{
					titlebar: this.titlebarPart,
					activitybar: this.activitybarPart,
					editor: this.editorPart,
					sidebar: this.sidebarPart,
					panel: this.panelPart,
					statusbar: this.statusbarPart,
				},
				this.quickOpen,
				this.quickInput,
				this.notificationsCenter,
				this.notificationsToasts
			);
		}
E
Erich Gamma 已提交
1228 1229 1230 1231 1232 1233
	}

	private renderWorkbench(): void {

		// Apply sidebar state as CSS class
		if (this.sideBarHidden) {
1234
			addClass(this.workbench, 'nosidebar');
E
Erich Gamma 已提交
1235
		}
B
Benjamin Pasero 已提交
1236

1237
		if (this.panelHidden) {
1238
			addClass(this.workbench, 'nopanel');
1239
		}
B
Benjamin Pasero 已提交
1240

1241
		if (this.statusBarHidden) {
1242
			addClass(this.workbench, 'nostatusbar');
1243
		}
E
Erich Gamma 已提交
1244

B
Benjamin Pasero 已提交
1245
		// Apply font aliasing
1246 1247
		this.setFontAliasing(this.fontAliasing);

1248
		// Apply fullscreen state
1249 1250
		if (isFullscreen()) {
			addClass(this.workbench, 'fullscreen');
B
Benjamin Pasero 已提交
1251 1252
		}

E
Erich Gamma 已提交
1253
		// Create Parts
B
Benjamin Pasero 已提交
1254
		this.createTitlebarPart();
E
Erich Gamma 已提交
1255 1256 1257
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
1258
		this.createPanelPart();
E
Erich Gamma 已提交
1259 1260
		this.createStatusbarPart();

1261 1262
		// Notification Handlers
		this.createNotificationsHandlers();
1263

1264 1265

		// Menubar visibility changes
B
Benjamin Pasero 已提交
1266
		if ((isWindows || isLinux) && this.useCustomTitleBarStyle()) {
1267 1268 1269
			this.titlebarPart.onMenubarVisibilityChange()(e => this.onMenubarToggled(e));
		}

E
Erich Gamma 已提交
1270
		// Add Workbench to DOM
B
Benjamin Pasero 已提交
1271
		this.container.appendChild(this.workbench);
E
Erich Gamma 已提交
1272 1273
	}

B
Benjamin Pasero 已提交
1274
	private createTitlebarPart(): void {
B
Benjamin Pasero 已提交
1275
		const titlebarContainer = this.createPart(Identifiers.TITLEBAR_PART, ['part', 'titlebar'], 'contentinfo');
B
Benjamin Pasero 已提交
1276

B
Benjamin Pasero 已提交
1277
		this.titlebarPart.create(titlebarContainer);
B
Benjamin Pasero 已提交
1278 1279
	}

E
Erich Gamma 已提交
1280
	private createActivityBarPart(): void {
B
Benjamin Pasero 已提交
1281
		const activitybarPartContainer = this.createPart(Identifiers.ACTIVITYBAR_PART, ['part', 'activitybar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'], 'navigation');
E
Erich Gamma 已提交
1282

B
Benjamin Pasero 已提交
1283
		this.activitybarPart.create(activitybarPartContainer);
E
Erich Gamma 已提交
1284 1285 1286
	}

	private createSidebarPart(): void {
B
Benjamin Pasero 已提交
1287
		const sidebarPartContainer = this.createPart(Identifiers.SIDEBAR_PART, ['part', 'sidebar', this.sideBarPosition === Position.LEFT ? 'left' : 'right'], 'complementary');
E
Erich Gamma 已提交
1288

B
Benjamin Pasero 已提交
1289
		this.sidebarPart.create(sidebarPartContainer);
E
Erich Gamma 已提交
1290 1291
	}

I
isidor 已提交
1292
	private createPanelPart(): void {
B
Benjamin Pasero 已提交
1293
		const panelPartContainer = this.createPart(Identifiers.PANEL_PART, ['part', 'panel', this.panelPosition === Position.BOTTOM ? 'bottom' : 'right'], 'complementary');
I
isidor 已提交
1294

B
Benjamin Pasero 已提交
1295
		this.panelPart.create(panelPartContainer);
I
isidor 已提交
1296 1297
	}

E
Erich Gamma 已提交
1298
	private createEditorPart(): void {
B
Benjamin Pasero 已提交
1299
		const editorContainer = this.createPart(Identifiers.EDITOR_PART, ['part', 'editor'], 'main');
E
Erich Gamma 已提交
1300

B
Benjamin Pasero 已提交
1301
		this.editorPart.create(editorContainer);
E
Erich Gamma 已提交
1302 1303 1304
	}

	private createStatusbarPart(): void {
B
Benjamin Pasero 已提交
1305 1306 1307 1308 1309 1310 1311
		const statusbarContainer = this.createPart(Identifiers.STATUSBAR_PART, ['part', 'statusbar'], 'contentinfo');

		this.statusbarPart.create(statusbarContainer);
	}

	private createPart(id: string, classes: string[], role: string): HTMLElement {
		const part = document.createElement('div');
1312
		classes.forEach(clazz => addClass(part, clazz));
B
Benjamin Pasero 已提交
1313 1314 1315
		part.id = id;
		part.setAttribute('role', role);

1316 1317 1318 1319 1320
		if (!this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
			// Insert all workbench parts at the beginning. Issue #52531
			// This is primarily for the title bar to allow overriding -webkit-app-region
			this.workbench.insertBefore(part, this.workbench.lastChild);
		}
E
Erich Gamma 已提交
1321

B
Benjamin Pasero 已提交
1322
		return part;
E
Erich Gamma 已提交
1323 1324
	}

1325 1326
	private createNotificationsHandlers(): void {

1327
		// Notifications Center
B
Benjamin Pasero 已提交
1328
		this.notificationsCenter = this._register(this.instantiationService.createInstance(NotificationsCenter, this.workbench, this.notificationService.model));
1329

1330
		// Notifications Toasts
B
Benjamin Pasero 已提交
1331
		this.notificationsToasts = this._register(this.instantiationService.createInstance(NotificationsToasts, this.workbench, this.notificationService.model));
1332

1333
		// Notifications Alerts
1334
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1335 1336 1337 1338

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

1339
		// Eventing
1340
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1341 1342 1343 1344 1345 1346 1347 1348

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

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

1349
		// Register Commands
1350
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1351 1352
	}

1353
	private saveState(e: IWillSaveStateEvent): void {
1354
		if (this.zenMode.active) {
B
Benjamin Pasero 已提交
1355
			this.storageService.store(Workbench.zenModeActiveStorageKey, true, StorageScope.WORKSPACE);
1356
		} else {
B
Benjamin Pasero 已提交
1357
			this.storageService.remove(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE);
1358
		}
1359 1360 1361 1362 1363 1364 1365 1366

		if (e.reason === WillSaveStateReason.SHUTDOWN && this.zenMode.active) {
			const zenConfig = this.configurationService.getValue<IZenModeSettings>('zenMode');
			if (!zenConfig.restore) {
				// We will not restore zen mode, need to clear all zen mode state changes
				this.toggleZenMode(true);
			}
		}
1367 1368
	}

1369
	dispose(): void {
1370
		super.dispose();
1371 1372 1373 1374 1375 1376

		this.workbenchShutdown = true;
	}

	//#region IPartService

M
Matt Bierner 已提交
1377
	private readonly _onTitleBarVisibilityChange: Emitter<void> = this._register(new Emitter<void>());
1378
	get onTitleBarVisibilityChange(): Event<void> { return this._onTitleBarVisibilityChange.event; }
1379

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

B
Benjamin Pasero 已提交
1382 1383
	isRestored(): boolean {
		return !!(this.workbenchRestored && this.workbenchStarted);
1384
	}
1385

1386 1387 1388 1389 1390
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1391

1392
		const container = this.getContainer(part);
1393
		return isAncestor(activeElement, container);
1394
	}
1395

1396
	getContainer(part: Parts): HTMLElement | null {
1397 1398
		switch (part) {
			case Parts.TITLEBAR_PART:
1399
				return this.titlebarPart.getContainer();
1400
			case Parts.ACTIVITYBAR_PART:
1401
				return this.activitybarPart.getContainer();
1402
			case Parts.SIDEBAR_PART:
1403
				return this.sidebarPart.getContainer();
1404
			case Parts.PANEL_PART:
1405
				return this.panelPart.getContainer();
1406
			case Parts.EDITOR_PART:
1407
				return this.editorPart.getContainer();
1408
			case Parts.STATUSBAR_PART:
1409
				return this.statusbarPart.getContainer();
1410
		}
1411

1412
		return null;
1413
	}
1414

1415 1416 1417
	isVisible(part: Parts): boolean {
		switch (part) {
			case Parts.TITLEBAR_PART:
B
Benjamin Pasero 已提交
1418
				if (!this.useCustomTitleBarStyle()) {
1419
					return false;
1420
				} else if (!isFullscreen()) {
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
					return true;
				} else if (isMacintosh) {
					return false;
				} else if (this.menubarVisibility === 'visible') {
					return true;
				} else if (this.menubarVisibility === 'toggle' || this.menubarVisibility === 'default') {
					return this.menubarToggled;
				}

				return false;
1431 1432 1433 1434 1435 1436 1437 1438
			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;
1439 1440
			case Parts.EDITOR_PART:
				return this.workbenchGrid instanceof Grid ? !this.editorHidden : true;
E
Erich Gamma 已提交
1441
		}
1442

1443
		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1444 1445
	}

1446 1447 1448
	getTitleBarOffset(): number {
		let offset = 0;
		if (this.isVisible(Parts.TITLEBAR_PART)) {
S
SteVen Batten 已提交
1449
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1450
				offset = this.titlebarPart.maximumHeight;
S
SteVen Batten 已提交
1451 1452 1453
			} else {
				offset = this.workbenchGrid.partLayoutInfo.titlebar.height;

B
Benjamin Pasero 已提交
1454 1455 1456
				if (isMacintosh || this.menubarVisibility === 'hidden') {
					offset /= getZoomFactor();
				}
1457
			}
E
Erich Gamma 已提交
1458
		}
1459 1460

		return offset;
E
Erich Gamma 已提交
1461
	}
1462

1463 1464
	getWorkbenchElement(): HTMLElement {
		return this.workbench;
1465
	}
1466

I
isidor 已提交
1467
	toggleZenMode(skipLayout?: boolean, restoring = false): void {
I
isidor 已提交
1468
		this.zenMode.active = !this.zenMode.active;
1469
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1470

1471 1472
		// 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)
1473
		let toggleFullScreen = false;
I
isidor 已提交
1474 1475 1476 1477 1478 1479 1480 1481
		const setLineNumbers = (lineNumbers: any) => {
			this.editorService.visibleControls.forEach(editor => {
				const control = <IEditor>editor.getControl();
				if (control) {
					control.updateOptions({ lineNumbers });
				}
			});
		};
1482 1483

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

1487
			toggleFullScreen = !isFullscreen() && config.fullScreen;
I
isidor 已提交
1488
			this.zenMode.transitionedToFullScreen = restoring ? config.fullScreen : toggleFullScreen;
1489
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1490 1491
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
1492

1493 1494
			this.setPanelHidden(true, true);
			this.setSideBarHidden(true, true);
I
isidor 已提交
1495

1496 1497 1498
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1499

I
isidor 已提交
1500
			if (config.hideStatusBar) {
I
isidor 已提交
1501 1502
				this.setStatusBarHidden(true, true);
			}
1503

I
isidor 已提交
1504 1505 1506 1507 1508
			if (config.hideLineNumbers) {
				setLineNumbers('off');
				this.zenMode.transitionDisposeables.push(this.editorService.onDidVisibleEditorsChange(() => setLineNumbers('off')));
			}

1509 1510
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1511
			}
1512 1513 1514 1515

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1516 1517 1518 1519
		}

		// Zen Mode Inactive
		else {
1520
			if (this.zenMode.wasPanelVisible) {
1521
				this.setPanelHidden(false, true);
1522
			}
1523

1524
			if (this.zenMode.wasSideBarVisible) {
1525
				this.setSideBarHidden(false, true);
1526
			}
1527

1528 1529 1530
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
I
isidor 已提交
1531
			setLineNumbers(this.configurationService.getValue('editor.lineNumbers'));
1532

1533 1534
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1535

B
Benjamin Pasero 已提交
1536
			this.editorGroupService.activeGroup.focus();
1537

1538
			toggleFullScreen = this.zenMode.transitionedToFullScreen && isFullscreen();
I
isidor 已提交
1539
		}
1540

1541
		this.inZenModeContext.set(this.zenMode.active);
I
isidor 已提交
1542

I
isidor 已提交
1543
		if (!skipLayout) {
1544
			this.layout();
I
isidor 已提交
1545
		}
1546

1547
		if (toggleFullScreen) {
1548
			this.windowService.toggleFullScreen();
1549
		}
I
isidor 已提交
1550 1551
	}

S
SteVen Batten 已提交
1552
	private updateGrid(): void {
S
SteVen Batten 已提交
1553
		if (!(this.workbenchGrid instanceof Grid)) {
1554 1555 1556
			return;
		}

S
SteVen Batten 已提交
1557 1558 1559 1560 1561
		let panelInGrid = this.workbenchGrid.hasView(this.panelPartView);
		let sidebarInGrid = this.workbenchGrid.hasView(this.sidebarPartView);
		let activityBarInGrid = this.workbenchGrid.hasView(this.activitybarPartView);
		let statusBarInGrid = this.workbenchGrid.hasView(this.statusbarPartView);
		let titlebarInGrid = this.workbenchGrid.hasView(this.titlebarPartView);
1562

S
SteVen Batten 已提交
1563 1564 1565
		// Add parts to grid
		if (!statusBarInGrid) {
			this.workbenchGrid.addView(this.statusbarPartView, Sizing.Split, this.editorPartView, Direction.Down);
S
SteVen Batten 已提交
1566 1567 1568
			statusBarInGrid = true;
		}

1569
		if (!titlebarInGrid && this.useCustomTitleBarStyle()) {
S
SteVen Batten 已提交
1570 1571 1572
			this.workbenchGrid.addView(this.titlebarPartView, Sizing.Split, this.editorPartView, Direction.Up);
			titlebarInGrid = true;
		}
S
SteVen Batten 已提交
1573

S
SteVen Batten 已提交
1574 1575 1576 1577
		if (!activityBarInGrid) {
			this.workbenchGrid.addView(this.activitybarPartView, Sizing.Split, panelInGrid && this.sideBarPosition === this.panelPosition ? this.panelPartView : this.editorPartView, this.sideBarPosition === Position.RIGHT ? Direction.Right : Direction.Left);
			activityBarInGrid = true;
		}
S
SteVen Batten 已提交
1578

S
SteVen Batten 已提交
1579 1580 1581 1582
		if (!sidebarInGrid) {
			this.workbenchGrid.addView(this.sidebarPartView, this.uiState.lastSidebarDimension !== undefined ? this.uiState.lastSidebarDimension : Sizing.Split, this.activitybarPartView, this.sideBarPosition === Position.LEFT ? Direction.Right : Direction.Left);
			sidebarInGrid = true;
		}
S
SteVen Batten 已提交
1583

S
SteVen Batten 已提交
1584 1585 1586
		if (!panelInGrid) {
			this.workbenchGrid.addView(this.panelPartView, this.getLastPanelDimension(this.panelPosition) !== undefined ? this.getLastPanelDimension(this.panelPosition) : Sizing.Split, this.editorPartView, this.panelPosition === Position.BOTTOM ? Direction.Down : Direction.Right);
			panelInGrid = true;
S
SteVen Batten 已提交
1587 1588
		}

S
SteVen Batten 已提交
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
		// Hide parts
		if (this.panelHidden) {
			this.panelPartView.hide();
		}

		if (this.statusBarHidden) {
			this.statusbarPartView.hide();
		}

		if (!this.isVisible(Parts.TITLEBAR_PART)) {
			this.titlebarPartView.hide();
		}

		if (this.activityBarHidden) {
			this.activitybarPartView.hide();
		}

		if (this.sideBarHidden) {
			this.sidebarPartView.hide();
		}

		if (this.editorHidden) {
			this.editorPartView.hide();
		}

S
SteVen Batten 已提交
1614
		// Show visible parts
S
SteVen Batten 已提交
1615 1616 1617 1618
		if (!this.editorHidden) {
			this.editorPartView.show();
		}

S
SteVen Batten 已提交
1619 1620 1621
		if (!this.statusBarHidden) {
			this.statusbarPartView.show();
		}
S
SteVen Batten 已提交
1622

S
SteVen Batten 已提交
1623 1624
		if (this.isVisible(Parts.TITLEBAR_PART)) {
			this.titlebarPartView.show();
S
SteVen Batten 已提交
1625 1626
		}

S
SteVen Batten 已提交
1627 1628 1629
		if (!this.activityBarHidden) {
			this.activitybarPartView.show();
		}
S
SteVen Batten 已提交
1630

S
SteVen Batten 已提交
1631 1632
		if (!this.sideBarHidden) {
			this.sidebarPartView.show();
S
SteVen Batten 已提交
1633 1634
		}

S
SteVen Batten 已提交
1635 1636
		if (!this.panelHidden) {
			this.panelPartView.show();
S
SteVen Batten 已提交
1637 1638 1639
		}
	}

1640
	layout(options?: ILayoutOptions): void {
S
SteVen Batten 已提交
1641 1642 1643
		this.contextViewService.layout();

		if (this.workbenchStarted && !this.workbenchShutdown) {
S
SteVen Batten 已提交
1644
			if (this.workbenchGrid instanceof Grid) {
1645 1646 1647
				const dimensions = getClientArea(this.container);
				position(this.workbench, 0, 0, 0, 0, 'relative');
				size(this.workbench, dimensions.width, dimensions.height);
S
SteVen Batten 已提交
1648

S
SteVen Batten 已提交
1649
				// Layout the grid
S
SteVen Batten 已提交
1650
				this.workbenchGrid.layout(dimensions.width, dimensions.height);
S
SteVen Batten 已提交
1651 1652 1653 1654 1655 1656 1657 1658

				// Layout non-view ui components
				this.quickInput.layout(dimensions);
				this.quickOpen.layout(dimensions);
				this.notificationsCenter.layout(dimensions);
				this.notificationsToasts.layout(dimensions);

				// Update grid view membership
1659
				this.updateGrid();
S
SteVen Batten 已提交
1660 1661
			} else {
				this.workbenchGrid.layout(options);
1662
			}
1663 1664 1665
		}
	}

1666
	isEditorLayoutCentered(): boolean {
1667
		return this.shouldCenterLayout;
S
SrTobi 已提交
1668 1669
	}

1670
	centerEditorLayout(active: boolean, skipLayout?: boolean): void {
B
Benjamin Pasero 已提交
1671
		this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, active, StorageScope.WORKSPACE);
1672 1673
		this.shouldCenterLayout = active;
		let smartActive = active;
1674
		if (this.editorPart.groups.length > 1 && this.configurationService.getValue('workbench.editor.centeredLayoutAutoResize')) {
B
Benjamin Pasero 已提交
1675
			smartActive = false; // Respect the auto resize setting - do not go into centered layout if there is more than 1 group.
1676
		}
B
Benjamin Pasero 已提交
1677

1678
		// Enter Centered Editor Layout
1679 1680
		if (this.editorPart.isLayoutCentered() !== smartActive) {
			this.editorPart.centerLayout(smartActive);
1681

1682 1683 1684
			if (!skipLayout) {
				this.layout();
			}
1685
		}
S
SrTobi 已提交
1686 1687
	}

1688
	resizePart(part: Parts, sizeChange: number): void {
S
SteVen Batten 已提交
1689
		let view: View;
1690 1691
		switch (part) {
			case Parts.SIDEBAR_PART:
S
SteVen Batten 已提交
1692
				view = this.sidebarPartView;
1693
			case Parts.PANEL_PART:
S
SteVen Batten 已提交
1694
				view = this.panelPartView;
1695
			case Parts.EDITOR_PART:
S
SteVen Batten 已提交
1696 1697
				view = this.editorPartView;
				if (this.workbenchGrid instanceof Grid) {
1698 1699 1700 1701
					this.workbenchGrid.resizeView(view, this.workbenchGrid.getViewSize(view) + sizeChange);
				} else {
					this.workbenchGrid.resizePart(part, sizeChange);
				}
1702 1703
				break;
			default:
B
Benjamin Pasero 已提交
1704
				return; // Cannot resize other parts
1705 1706 1707
		}
	}

1708 1709
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1710

1711 1712
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1713
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1714
				this.layout();
1715 1716 1717
			} else {
				this.workbenchGrid.layout();
			}
1718
		}
1719
	}
1720

S
SteVen Batten 已提交
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737
	setEditorHidden(hidden: boolean, skipLayout?: boolean): void {
		if (!(this.workbenchGrid instanceof Grid)) {
			return;
		}

		this.editorHidden = hidden;

		// The editor and the panel cannot be hidden at the same time
		if (this.editorHidden && this.panelHidden) {
			this.setPanelHidden(false, true);
		}

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

1738
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): void {
1739 1740 1741 1742 1743
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
1744
			addClass(this.workbench, 'nosidebar');
1745
		} else {
1746
			removeClass(this.workbench, 'nosidebar');
1747 1748
		}

1749 1750
		// If sidebar becomes hidden, also hide the current active Viewlet if any
		if (hidden && this.sidebarPart.getActiveViewlet()) {
1751 1752 1753 1754 1755 1756 1757 1758 1759
			this.sidebarPart.hideActiveViewlet();
			const activePanel = this.panelPart.getActivePanel();

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

		// If sidebar becomes visible, show last active Viewlet or default viewlet
		else if (!hidden && !this.sidebarPart.getActiveViewlet()) {
			const viewletToOpen = this.sidebarPart.getLastActiveViewletId();
			if (viewletToOpen) {
I
isidor 已提交
1766
				const viewlet = this.sidebarPart.openViewlet(viewletToOpen, true);
1767
				if (!viewlet) {
I
isidor 已提交
1768
					this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId(), true);
1769
				}
1770
			}
1771 1772
		}

1773 1774 1775 1776 1777 1778 1779
		// 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);
		}
1780

1781 1782
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1783
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1784
				this.layout();
1785 1786 1787
			} else {
				this.workbenchGrid.layout();
			}
1788
		}
1789
	}
1790

1791
	setPanelHidden(hidden: boolean, skipLayout?: boolean): void {
1792 1793 1794 1795
		this.panelHidden = hidden;

		// Adjust CSS
		if (hidden) {
1796
			addClass(this.workbench, 'nopanel');
1797
		} else {
1798
			removeClass(this.workbench, 'nopanel');
1799 1800 1801 1802
		}

		// If panel part becomes hidden, also hide the current active panel if any
		if (hidden && this.panelPart.getActivePanel()) {
1803 1804
			this.panelPart.hideActivePanel();
			this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
1805 1806 1807 1808 1809 1810
		}

		// 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) {
I
isidor 已提交
1811 1812
				const focus = !skipLayout;
				this.panelPart.openPanel(panelToOpen, focus);
1813 1814 1815
			}
		}

1816 1817 1818 1819 1820 1821
		// Remember in settings
		if (!hidden) {
			this.storageService.store(Workbench.panelHiddenStorageKey, 'false', StorageScope.WORKSPACE);
		} else {
			this.storageService.remove(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE);
		}
1822

S
SteVen Batten 已提交
1823 1824 1825 1826 1827
		// The editor and panel cannot be hiddne at the same time
		if (hidden && this.editorHidden) {
			this.setEditorHidden(false, true);
		}

1828 1829
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1830
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1831
				this.layout();
1832 1833 1834
			} else {
				this.workbenchGrid.layout();
			}
1835
		}
1836 1837 1838
	}

	toggleMaximizedPanel(): void {
S
SteVen Batten 已提交
1839 1840
		if (this.workbenchGrid instanceof Grid) {
			this.workbenchGrid.maximizeViewSize(this.panelPartView);
1841 1842 1843
		} else {
			this.workbenchGrid.layout({ toggleMaximizedPanel: true, source: Parts.PANEL_PART });
		}
1844 1845 1846
	}

	isPanelMaximized(): boolean {
S
SteVen Batten 已提交
1847
		if (this.workbenchGrid instanceof Grid) {
1848
			try {
S
SteVen Batten 已提交
1849
				return this.workbenchGrid.getViewSize2(this.panelPartView).height === this.panelPart.maximumHeight;
1850 1851 1852 1853 1854 1855
			} catch (e) {
				return false;
			}
		} else {
			return this.workbenchGrid.isPanelMaximized();
		}
1856 1857 1858 1859 1860 1861 1862
	}

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

	setSideBarPosition(position: Position): void {
1863 1864
		const wasHidden = this.sideBarHidden;

1865
		if (this.sideBarHidden) {
1866
			this.setSideBarHidden(false, true /* Skip Layout */);
1867 1868 1869 1870 1871 1872 1873
		}

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

		// Adjust CSS
1874 1875 1876 1877
		removeClass(this.activitybarPart.getContainer(), oldPositionValue);
		removeClass(this.sidebarPart.getContainer(), oldPositionValue);
		addClass(this.activitybarPart.getContainer(), newPositionValue);
		addClass(this.sidebarPart.getContainer(), newPositionValue);
1878 1879 1880 1881 1882 1883

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

		// Layout
S
SteVen Batten 已提交
1884
		if (this.workbenchGrid instanceof Grid) {
1885

S
SteVen Batten 已提交
1886
			if (!wasHidden) {
S
SteVen Batten 已提交
1887
				this.uiState.lastSidebarDimension = this.workbenchGrid.getViewSize(this.sidebarPartView);
1888 1889
			}

S
SteVen Batten 已提交
1890 1891
			this.workbenchGrid.removeView(this.sidebarPartView);
			this.workbenchGrid.removeView(this.activitybarPartView);
S
SteVen Batten 已提交
1892 1893 1894

			if (!this.panelHidden && this.panelPosition === Position.BOTTOM) {
				this.workbenchGrid.removeView(this.panelPartView);
1895 1896
			}

S
SteVen Batten 已提交
1897
			this.layout();
1898 1899 1900
		} else {
			this.workbenchGrid.layout();
		}
1901 1902
	}

S
SteVen Batten 已提交
1903
	setMenubarVisibility(visibility: MenuBarVisibility, skipLayout: boolean): void {
S
SteVen Batten 已提交
1904 1905
		if (this.menubarVisibility !== visibility) {
			this.menubarVisibility = visibility;
1906

1907
			// Layout
S
SteVen Batten 已提交
1908
			if (!skipLayout) {
S
SteVen Batten 已提交
1909
				if (this.workbenchGrid instanceof Grid) {
1910
					const dimensions = getClientArea(this.container);
1911 1912 1913 1914
					this.workbenchGrid.layout(dimensions.width, dimensions.height);
				} else {
					this.workbenchGrid.layout();
				}
S
SteVen Batten 已提交
1915
			}
1916 1917 1918
		}
	}

S
SteVen Batten 已提交
1919 1920 1921 1922
	getMenubarVisibility(): MenuBarVisibility {
		return this.menubarVisibility;
	}

1923 1924 1925 1926
	getPanelPosition(): Position {
		return this.panelPosition;
	}

1927
	setPanelPosition(position: Position): void {
1928 1929
		const wasHidden = this.panelHidden;

1930 1931
		if (this.panelHidden) {
			this.setPanelHidden(false, true /* Skip Layout */);
1932 1933
		} else {
			this.saveLastPanelDimension();
1934
		}
1935

1936 1937 1938 1939
		const newPositionValue = (position === Position.BOTTOM) ? 'bottom' : 'right';
		const oldPositionValue = (this.panelPosition === Position.BOTTOM) ? 'bottom' : 'right';
		this.panelPosition = position;
		this.storageService.store(Workbench.panelPositionStorageKey, PositionToString(this.panelPosition).toLowerCase(), StorageScope.WORKSPACE);
1940

1941
		// Adjust CSS
1942 1943
		removeClass(this.panelPart.getContainer(), oldPositionValue);
		addClass(this.panelPart.getContainer(), newPositionValue);
1944

1945 1946 1947 1948
		// Update Styles
		this.panelPart.updateStyles();

		// Layout
S
SteVen Batten 已提交
1949 1950 1951
		if (this.workbenchGrid instanceof Grid) {
			if (!wasHidden) {
				this.saveLastPanelDimension();
1952
			}
1953

1954
			this.workbenchGrid.removeView(this.panelPartView);
S
SteVen Batten 已提交
1955
			this.layout();
1956 1957 1958 1959
		} else {
			this.workbenchGrid.layout();
		}
	}
1960 1961

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