workbench.ts 87.4 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
import { localize } from 'vs/nls';
B
Benjamin Pasero 已提交
9
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
J
Joao Moreno 已提交
10
import { Event, Emitter } from 'vs/base/common/event';
11
import { EventType, addDisposableListener, addClasses, scheduleAtNextAnimationFrame, addClass, removeClass, trackFocus, isAncestor, getClientArea, position, size } from 'vs/base/browser/dom';
B
Benjamin Pasero 已提交
12
import { RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
13 14 15
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';
16
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
17
import { Registry } from 'vs/platform/registry/common/platform';
18
import { isWindows, isLinux, isMacintosh, language } from 'vs/base/common/platform';
19
import { IResourceInput } from 'vs/platform/editor/common/editor';
J
Johannes Rieken 已提交
20
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
21
import { IEditorInputFactoryRegistry, Extensions as EditorExtensions, TextCompareEditorVisibleContext, TEXT_DIFF_EDITOR_ID, EditorsVisibleContext, InEditorZenModeContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, IUntitledResourceInput, IResourceDiffInput, SplitEditorsVertically, TextCompareEditorActiveContext, ActiveEditorContext } from 'vs/workbench/common/editor';
J
Johannes Rieken 已提交
22 23 24 25
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { StatusbarPart } from 'vs/workbench/browser/parts/statusbar/statusbarPart';
B
Benjamin Pasero 已提交
26
import { TitlebarPart } from 'vs/workbench/browser/parts/titlebar/titlebarPart';
27
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
28
import { IActionBarRegistry, Extensions as ActionBarExtensions } from 'vs/workbench/browser/actions';
J
Johannes Rieken 已提交
29 30
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { QuickOpenController } from 'vs/workbench/browser/parts/quickopen/quickOpenController';
C
Christof Marti 已提交
31 32
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputService } from 'vs/workbench/browser/parts/quickinput/quickInput';
J
Johannes Rieken 已提交
33
import { getServices } from 'vs/platform/instantiation/common/extensions';
34
import { Position, Parts, IPartService, IDimension, PositionToString, ILayoutOptions } from 'vs/workbench/services/part/common/partService';
35
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
36
import { IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage';
S
SteVen Batten 已提交
37
import { ContextMenuService as HTMLContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
J
Johannes Rieken 已提交
38
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
39
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
J
Johannes Rieken 已提交
40
import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService';
41 42
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IKeybindingEditingService, KeybindingsEditingService } from 'vs/workbench/services/keybinding/common/keybindingEditing';
43
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
I
isidor 已提交
44
import { IActivityService } from 'vs/workbench/services/activity/common/activity';
B
Benjamin Pasero 已提交
45
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
J
Johannes Rieken 已提交
46 47 48
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 已提交
49
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
J
Johannes Rieken 已提交
50
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
51
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
J
Johannes Rieken 已提交
52 53 54
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';
55
import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService';
J
Johannes Rieken 已提交
56
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
57
import { IProgressService2 } from 'vs/platform/progress/common/progress';
58
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
59
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
60
import { ITextModelService } from 'vs/editor/common/services/resolverService';
J
Johannes Rieken 已提交
61
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
B
Benjamin Pasero 已提交
62
import { LifecyclePhase, StartupKind, ILifecycleService, WillShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle';
63
import { IWindowService, IWindowConfiguration, IPath, MenuBarVisibility, getTitleBarStyle, IWindowsService } from 'vs/platform/windows/common/windows';
J
Johannes Rieken 已提交
64
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
65
import { IMenuService, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
66
import { MenuService } from 'vs/platform/actions/common/menuService';
S
SteVen Batten 已提交
67
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
J
Johannes Rieken 已提交
68
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
69
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
70
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
71
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
72
import { FileDecorationsService } from 'vs/workbench/services/decorations/browser/decorationsService';
J
Johannes Rieken 已提交
73
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
I
isidor 已提交
74
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService';
75
import { URI } from 'vs/base/common/uri';
J
Joao Moreno 已提交
76
import { IListService, ListService } from 'vs/platform/list/browser/listService';
A
Alex Ross 已提交
77
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, SupportsOpenFileFolderContext, SupportsWorkspacesContext } from 'vs/platform/contextkey/common/contextkeys';
78
import { IViewsService } from 'vs/workbench/common/views';
S
Sandeep Somavarapu 已提交
79
import { ViewsService } from 'vs/workbench/browser/parts/views/views';
80 81
import { INotificationService } from 'vs/platform/notification/common/notification';
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
82 83
import { NotificationsCenter } from 'vs/workbench/browser/parts/notifications/notificationsCenter';
import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/notificationsAlerts';
84
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
85
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
86
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
S
Sandeep Somavarapu 已提交
87 88
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
89
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
90
import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService';
91
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
S
SteVen Batten 已提交
92
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
A
Alex Dima 已提交
93
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
94
import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs';
S
SteVen Batten 已提交
95
import { Sizing, Direction, Grid, View } from 'vs/base/browser/ui/grid/grid';
I
isidor 已提交
96
import { IEditor } from 'vs/editor/common/editorCommon';
97
import { WorkbenchLayout } from 'vs/workbench/browser/layout';
98 99 100 101 102 103
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';
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 135 136 137
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';
138
import { HistoryService } from 'vs/workbench/services/history/browser/history';
139
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
140 141 142 143 144 145 146 147 148

// import@node
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
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';
import { IPCClient, getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
B
Benjamin Pasero 已提交
149
import { LogStorageAction } from 'vs/platform/storage/node/storageService';
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
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';

// import@electron-browser
import { ContextMenuService as NativeContextMenuService } from 'vs/workbench/services/contextview/electron-browser/contextmenuService';
import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { RemoteFileService } from 'vs/workbench/services/files/electron-browser/remoteFileService';
import { ClipboardService } from 'vs/platform/clipboard/electron-browser/clipboardService';
import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecycleService';
import { ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler';
178
import { WorkbenchThemeService } from 'vs/workbench/services/themes/browser/workbenchThemeService';
179
import { DialogService, FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
180 181 182 183 184 185 186 187 188
import { ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, NewWindowTab, OpenRecentAction, ReloadWindowAction, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions/windowActions';
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 { TextResourcePropertiesService } from 'vs/workbench/services/textfile/electron-browser/textResourcePropertiesService';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
189

E
Erich Gamma 已提交
190
interface WorkbenchParams {
191
	configuration: IWindowConfiguration;
192
	serviceCollection: ServiceCollection;
E
Erich Gamma 已提交
193 194
}

I
isidor 已提交
195 196
interface IZenModeSettings {
	fullScreen: boolean;
197
	centerLayout: boolean;
I
isidor 已提交
198
	hideTabs: boolean;
199
	hideActivityBar: boolean;
I
isidor 已提交
200
	hideStatusBar: boolean;
I
isidor 已提交
201
	hideLineNumbers: boolean;
I
isidor 已提交
202
	restore: boolean;
I
isidor 已提交
203 204
}

205
interface IWorkbenchStartedInfo {
206 207
	customKeybindingsCount: number;
	pinnedViewlets: string[];
208
	restoredViewlet: string;
209
	restoredEditorsCount: number;
210
}
211 212
type FontAliasingOption = 'default' | 'antialiased' | 'none' | 'auto';

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

215 216
const Identifiers = {
	WORKBENCH_CONTAINER: 'workbench.main.container',
B
Benjamin Pasero 已提交
217
	TITLEBAR_PART: 'workbench.parts.titlebar',
218 219 220 221
	ACTIVITYBAR_PART: 'workbench.parts.activitybar',
	SIDEBAR_PART: 'workbench.parts.sidebar',
	PANEL_PART: 'workbench.parts.panel',
	EDITOR_PART: 'workbench.parts.editor',
S
SteVen Batten 已提交
222
	STATUSBAR_PART: 'workbench.parts.statusbar'
223 224
};

J
Joao Moreno 已提交
225 226 227 228 229 230 231 232
function getWorkbenchStateString(state: WorkbenchState): string {
	switch (state) {
		case WorkbenchState.EMPTY: return 'empty';
		case WorkbenchState.FOLDER: return 'folder';
		case WorkbenchState.WORKSPACE: return 'workspace';
	}
}

233 234 235 236 237 238 239 240 241
interface IZenMode {
	active: boolean;
	transitionedToFullScreen: boolean;
	transitionedToCenteredEditorLayout: boolean;
	transitionDisposeables: IDisposable[];
	wasSideBarVisible: boolean;
	wasPanelVisible: boolean;
}

242 243 244 245 246 247
interface IWorkbenchUIState {
	lastPanelHeight?: number;
	lastPanelWidth?: number;
	lastSidebarDimension?: number;
}

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

250
	private static readonly sidebarHiddenStorageKey = 'workbench.sidebar.hidden';
251
	private static readonly menubarVisibilityConfigurationKey = 'window.menuBarVisibility';
252 253
	private static readonly panelHiddenStorageKey = 'workbench.panel.hidden';
	private static readonly zenModeActiveStorageKey = 'workbench.zenmode.active';
254
	private static readonly centeredEditorLayoutActiveStorageKey = 'workbench.centerededitorlayout.active';
255
	private static readonly panelPositionStorageKey = 'workbench.panel.location';
256
	private static readonly defaultPanelPositionStorageKey = 'workbench.panel.defaultLocation';
257 258 259 260 261
	private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location';
	private static readonly statusbarVisibleConfigurationKey = 'workbench.statusBar.visible';
	private static readonly activityBarVisibleConfigurationKey = 'workbench.activityBar.visible';
	private static readonly closeWhenEmptyConfigurationKey = 'window.closeWhenEmpty';
	private static readonly fontAliasingConfigurationKey = 'workbench.fontAliasing';
262

B
Benjamin Pasero 已提交
263 264 265 266 267 268
	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; }

269
	_serviceBrand: any;
270

271 272 273
	private previousErrorValue: string;
	private previousErrorTime: number = 0;

E
Erich Gamma 已提交
274
	private workbenchParams: WorkbenchParams;
B
Benjamin Pasero 已提交
275
	private workbench: HTMLElement;
E
Erich Gamma 已提交
276
	private workbenchStarted: boolean;
B
Benjamin Pasero 已提交
277
	private workbenchRestored: boolean;
E
Erich Gamma 已提交
278
	private workbenchShutdown: boolean;
279

280 281
	private editorService: EditorService;
	private editorGroupService: IEditorGroupsService;
J
Joao Moreno 已提交
282
	private contextViewService: ContextViewService;
283
	private contextKeyService: IContextKeyService;
284
	private keybindingService: IKeybindingService;
285
	private backupFileService: IBackupFileService;
286 287 288 289 290
	private notificationService: NotificationService;
	private themeService: WorkbenchThemeService;
	private telemetryService: ITelemetryService;
	private windowService: IWindowService;
	private lifecycleService: LifecycleService;
291
	private fileService: IFileService;
292 293
	private quickInput: QuickInputService;

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

B
Benjamin Pasero 已提交
296
	private titlebarPart: TitlebarPart;
E
Erich Gamma 已提交
297 298
	private activitybarPart: ActivitybarPart;
	private sidebarPart: SidebarPart;
I
isidor 已提交
299
	private panelPart: PanelPart;
E
Erich Gamma 已提交
300 301
	private editorPart: EditorPart;
	private statusbarPart: StatusbarPart;
S
SteVen Batten 已提交
302 303 304 305 306 307 308 309

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

E
Erich Gamma 已提交
310
	private quickOpen: QuickOpenController;
311
	private notificationsCenter: NotificationsCenter;
312
	private notificationsToasts: NotificationsToasts;
313

S
SteVen Batten 已提交
314
	private editorHidden: boolean;
E
Erich Gamma 已提交
315
	private sideBarHidden: boolean;
316
	private statusBarHidden: boolean;
S
Sanders Lauture 已提交
317
	private activityBarHidden: boolean;
318
	private menubarToggled: boolean;
E
Erich Gamma 已提交
319
	private sideBarPosition: Position;
I
isidor 已提交
320
	private panelPosition: Position;
I
isidor 已提交
321
	private panelHidden: boolean;
S
SteVen Batten 已提交
322
	private menubarVisibility: MenuBarVisibility;
323 324
	private zenMode: IZenMode;
	private fontAliasing: FontAliasingOption;
325
	private hasInitialFilesToOpen: boolean;
326
	private shouldCenterLayout = false;
327 328 329 330 331
	private uiState: IWorkbenchUIState = {
		lastPanelHeight: 350,
		lastPanelWidth: 350,
		lastSidebarDimension: 300,
	};
332

I
isidor 已提交
333
	private inZenMode: IContextKey<boolean>;
334
	private sideBarVisibleContext: IContextKey<boolean>;
335

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

338
	constructor(
339
		private container: HTMLElement,
J
Joao Moreno 已提交
340
		private configuration: IWindowConfiguration,
341
		serviceCollection: ServiceCollection,
J
Joao Moreno 已提交
342
		private mainProcessClient: IPCClient,
343 344
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
B
Benjamin Pasero 已提交
345
		@IStorageService private readonly storageService: IStorageService,
346 347
		@IConfigurationService private readonly configurationService: WorkspaceService,
		@IEnvironmentService private readonly environmentService: IEnvironmentService,
348 349
		@ILogService private readonly logService: ILogService,
		@IWindowsService private readonly windowsService: IWindowsService
350
	) {
351
		super();
E
Erich Gamma 已提交
352

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

355
		this.hasInitialFilesToOpen = !!(
B
Benjamin Pasero 已提交
356 357
			(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
			(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
358
			(configuration.filesToDiff && configuration.filesToDiff.length > 0));
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409

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

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

	startup(): Promise<void> {
		try {
			return this.doStartup().then(undefined, error => this.logService.error(toErrorMessage(error, true)));
		} catch (error) {
			this.logService.error(toErrorMessage(error, true));

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

412
	private doStartup(): Promise<void> {
413
		this.workbenchStarted = true;
E
Erich Gamma 已提交
414

B
Benjamin Pasero 已提交
415 416 417
		// Logging
		this.logService.trace('workbench configuration', JSON.stringify(this.configuration));

418 419 420 421 422 423 424 425 426 427
		// 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 已提交
428
		// Create Workbench Container
429
		this.createWorkbench();
E
Erich Gamma 已提交
430

431 432
		// Install some global actions
		this.createGlobalActions();
433

434 435
		// Services
		this.initServices();
E
Erich Gamma 已提交
436

437 438
		// Context Keys
		this.handleContextKeys();
J
Joao Moreno 已提交
439

440 441
		// Register Listeners
		this.registerListeners();
E
Erich Gamma 已提交
442

443 444
		// Settings
		this.initSettings();
E
Erich Gamma 已提交
445

446 447
		// Create Workbench and Parts
		this.renderWorkbench();
448

449 450
		// Workbench Layout
		this.createWorkbenchLayout();
B
polish  
Benjamin Pasero 已提交
451

452 453 454
		// Layout
		this.layout();

J
Joao Moreno 已提交
455 456
		// Driver
		if (this.environmentService.driverHandle) {
457
			registerWindowDriver(this.mainProcessClient, this.configuration.windowId, this.instantiationService).then(disposable => this._register(disposable));
J
Joao Moreno 已提交
458 459
		}

460 461 462 463 464 465 466 467 468
		// Handle case where workbench is not starting up properly
		const timeoutHandle = setTimeout(() => {
			this.logService.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
		}, 10000);

		this.lifecycleService.when(LifecyclePhase.Restored).then(() => {
			clearTimeout(timeoutHandle);
		});

469
		// Restore Parts
B
Benjamin Pasero 已提交
470 471
		return this.restoreParts();
	}
472

B
Benjamin Pasero 已提交
473
	private createWorkbench(): void {
B
Benjamin Pasero 已提交
474 475
		this.workbench = document.createElement('div');
		this.workbench.id = Identifiers.WORKBENCH_CONTAINER;
476

477
		addClasses(this.workbench, 'monaco-workbench', isWindows ? 'windows' : isLinux ? 'linux' : 'mac');
478
	}
E
Erich Gamma 已提交
479

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

B
Benjamin Pasero 已提交
483
		// Actions registered here to adjust for developing vs built workbench
484
		const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
R
Rob Lourens 已提交
485 486
		registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyCode.KEY_R } : undefined), 'Reload Window');
		registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleDevToolsAction, ToggleDevToolsAction.ID, ToggleDevToolsAction.LABEL, isDeveloping ? { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_I } } : undefined), 'Developer: Toggle Developer Tools', localize('developer', "Developer"));
487 488
		registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: isDeveloping ? null : KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', localize('file', "File"));
		registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowWithExtensionsDisabledAction, ReloadWindowWithExtensionsDisabledAction.ID, ReloadWindowWithExtensionsDisabledAction.LABEL), 'Reload Window Without Extensions');
489
		registry.registerWorkbenchAction(new SyncActionDescriptor(LogStorageAction, LogStorageAction.ID, LogStorageAction.LABEL), 'Developer: Log Storage', localize('developer', "Developer"));
490

491
		// Actions for macOS native tabs management (only when enabled)
492
		const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
493
		if (windowConfig && windowConfig.window && windowConfig.window.nativeTabs) {
494
			registry.registerWorkbenchAction(new SyncActionDescriptor(NewWindowTab, NewWindowTab.ID, NewWindowTab.LABEL), 'New Window Tab');
495 496 497 498 499
			registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousWindowTab, ShowPreviousWindowTab.ID, ShowPreviousWindowTab.LABEL), 'Show Previous Window Tab');
			registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextWindowTab, ShowNextWindowTab.ID, ShowNextWindowTab.LABEL), 'Show Next Window Tab');
			registry.registerWorkbenchAction(new SyncActionDescriptor(MoveWindowTabToNewWindow, MoveWindowTabToNewWindow.ID, MoveWindowTabToNewWindow.LABEL), 'Move Window Tab to New Window');
			registry.registerWorkbenchAction(new SyncActionDescriptor(MergeAllWindowTabs, MergeAllWindowTabs.ID, MergeAllWindowTabs.LABEL), 'Merge All Windows');
			registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleWindowTabsBar, ToggleWindowTabsBar.ID, ToggleWindowTabsBar.LABEL), 'Toggle Window Tabs Bar');
500
		}
501 502
	}

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

506
		// Parts
507
		serviceCollection.set(IPartService, this);
E
Erich Gamma 已提交
508

509 510 511
		// Labels
		serviceCollection.set(ILabelService, new SyncDescriptor(LabelService, undefined, true));

512
		// Clipboard
J
Johannes Rieken 已提交
513
		serviceCollection.set(IClipboardService, new SyncDescriptor(ClipboardService));
514

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 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
		// 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);

		// 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
		if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
			const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender')));
			const config: ITelemetryServiceConfig = {
				appender: combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(this.logService)),
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, product.commit, pkg.version, this.configuration.machineId, this.environmentService.installSourcePath),
				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 已提交
562 563 564 565 566
		this._register(this.lifecycleService.onWillShutdown(event => this._onWillShutdown.fire(event)));
		this._register(this.lifecycleService.onShutdown(() => {
			this._onShutdown.fire();
			this.dispose();
		}));
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 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658

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

659 660 661 662
		// Status bar
		this.statusbarPart = this.instantiationService.createInstance(StatusbarPart, Identifiers.STATUSBAR_PART);
		serviceCollection.set(IStatusbarService, this.statusbarPart);

663 664 665
		// Progress 2
		serviceCollection.set(IProgressService2, new SyncDescriptor(ProgressService2));

666
		// Keybindings
A
Alex Dima 已提交
667
		this.contextKeyService = this.instantiationService.createInstance(ContextKeyService);
668
		serviceCollection.set(IContextKeyService, this.contextKeyService);
669

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

673 674 675
		// List
		serviceCollection.set(IListService, this.instantiationService.createInstance(ListService));

J
Joao Moreno 已提交
676
		// Context view service
B
Benjamin Pasero 已提交
677
		this.contextViewService = this.instantiationService.createInstance(ContextViewService, this.workbench);
J
Joao Moreno 已提交
678 679
		serviceCollection.set(IContextViewService, this.contextViewService);

S
SteVen Batten 已提交
680
		// Use themable context menus when custom titlebar is enabled to match custom menubar
B
Benjamin Pasero 已提交
681
		if (!isMacintosh && this.useCustomTitleBarStyle()) {
J
fix npe  
Johannes Rieken 已提交
682
			serviceCollection.set(IContextMenuService, new SyncDescriptor(HTMLContextMenuService, [null]));
S
SteVen Batten 已提交
683 684 685
		} else {
			serviceCollection.set(IContextMenuService, new SyncDescriptor(NativeContextMenuService));
		}
686

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

P
Pine Wu 已提交
690
		// Sidebar part
691
		this.sidebarPart = this.instantiationService.createInstance(SidebarPart, Identifiers.SIDEBAR_PART);
P
Pine Wu 已提交
692 693

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

I
isidor 已提交
696
		// Panel service (panel part)
697 698
		this.panelPart = this.instantiationService.createInstance(PanelPart, Identifiers.PANEL_PART);
		serviceCollection.set(IPanelService, this.panelPart);
I
isidor 已提交
699

700 701 702
		// views service
		const viewsService = this.instantiationService.createInstance(ViewsService);
		serviceCollection.set(IViewsService, viewsService);
S
Sandeep Somavarapu 已提交
703

E
Erich Gamma 已提交
704
		// Activity service (activitybar part)
705
		this.activitybarPart = this.instantiationService.createInstance(ActivitybarPart, Identifiers.ACTIVITYBAR_PART);
I
isidor 已提交
706 707
		const activityService = this.instantiationService.createInstance(ActivityService, this.activitybarPart, this.panelPart);
		serviceCollection.set(IActivityService, activityService);
E
Erich Gamma 已提交
708

709 710 711
		// File Service
		this.fileService = this.instantiationService.createInstance(RemoteFileService);
		serviceCollection.set(IFileService, this.fileService);
S
#47154  
Sandeep Somavarapu 已提交
712
		this.configurationService.acquireFileService(this.fileService);
A
Alex Dima 已提交
713
		this.themeService.acquireFileService(this.fileService);
714

715 716
		// Editor and Group services
		const restorePreviousEditorState = !this.hasInitialFilesToOpen;
717
		this.editorPart = this.instantiationService.createInstance(EditorPart, Identifiers.EDITOR_PART, restorePreviousEditorState);
B
Benjamin Pasero 已提交
718
		this.editorGroupService = this.editorPart;
719 720 721
		serviceCollection.set(IEditorGroupsService, this.editorPart);
		this.editorService = this.instantiationService.createInstance(EditorService);
		serviceCollection.set(IEditorService, this.editorService);
E
Erich Gamma 已提交
722

723 724 725
		// Title bar
		this.titlebarPart = this.instantiationService.createInstance(TitlebarPart, Identifiers.TITLEBAR_PART);
		serviceCollection.set(ITitleService, this.titlebarPart);
B
Benjamin Pasero 已提交
726

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

M
Martin Aeschlimann 已提交
730
		// File Dialogs
731
		serviceCollection.set(IFileDialogService, new SyncDescriptor(FileDialogService));
M
Martin Aeschlimann 已提交
732

733
		// Backup File Service
B
Benjamin Pasero 已提交
734 735 736 737 738
		if (this.workbenchParams.configuration.backupPath) {
			this.backupFileService = this.instantiationService.createInstance(BackupFileService, this.workbenchParams.configuration.backupPath);
		} else {
			this.backupFileService = new InMemoryBackupFileService();
		}
739
		serviceCollection.set(IBackupFileService, this.backupFileService);
740

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

744
		// File Decorations
J
Johannes Rieken 已提交
745
		serviceCollection.set(IDecorationsService, new SyncDescriptor(FileDecorationsService));
746

J
Joao Moreno 已提交
747
		// Inactive extension URL handler
J
Joao Moreno 已提交
748
		serviceCollection.set(IExtensionUrlHandler, new SyncDescriptor(ExtensionUrlHandler));
J
Joao Moreno 已提交
749

B
Benjamin Pasero 已提交
750
		// Text Model Resolver Service
751
		serviceCollection.set(ITextModelService, new SyncDescriptor(TextModelResolverService));
B
Benjamin Pasero 已提交
752

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

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

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

763
		// Configuration Resolver
764
		serviceCollection.set(IConfigurationResolverService, new SyncDescriptor(ConfigurationResolverService, [process.env]));
765

E
Erich Gamma 已提交
766
		// Quick open service (quick open controller)
767 768
		this.quickOpen = this.instantiationService.createInstance(QuickOpenController);
		serviceCollection.set(IQuickOpenService, this.quickOpen);
769

C
Christof Marti 已提交
770 771 772 773
		// Quick input service
		this.quickInput = this.instantiationService.createInstance(QuickInputService);
		serviceCollection.set(IQuickInputService, this.quickInput);

S
Sandeep Somavarapu 已提交
774 775 776
		// PreferencesService
		serviceCollection.set(IPreferencesService, this.instantiationService.createInstance(PreferencesService));

B
polish  
Benjamin Pasero 已提交
777
		// Contributed services
B
Benjamin Pasero 已提交
778
		const contributedServices = getServices();
E
Erich Gamma 已提交
779
		for (let contributedService of contributedServices) {
780
			serviceCollection.set(contributedService.id, contributedService.descriptor);
E
Erich Gamma 已提交
781 782 783
		}

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

788
		this.instantiationService.createInstance(DefaultConfigurationExportHelper);
789

B
Benjamin Pasero 已提交
790
		this.configurationService.acquireInstantiationService(this.instantiationService);
E
Erich Gamma 已提交
791 792
	}

793
	//#region event handling
E
Erich Gamma 已提交
794

795
	private registerListeners(): void {
I
isidor 已提交
796

797
		// Storage
798
		this._register(this.storageService.onWillSaveState(e => this.saveState(e)));
799

800
		// Listen to visible editor changes
801
		this._register(this.editorService.onDidVisibleEditorsChange(() => this.onDidVisibleEditorsChange()));
B
Benjamin Pasero 已提交
802

803 804 805
		// Listen to editor group activations when editor is hidden
		this._register(this.editorPart.onDidActivateGroup(() => { if (this.editorHidden) { this.setEditorHidden(false); } }));

806 807 808
		// Listen to editor closing (if we run with --wait)
		const filesToWait = this.workbenchParams.configuration.filesToWait;
		if (filesToWait) {
809
			const resourcesToWaitFor = filesToWait.paths.map(p => p.fileUri);
810
			const waitMarkerFile = URI.file(filesToWait.waitMarkerFilePath);
811
			const listenerDispose = this.editorService.onDidCloseEditor(() => this.onEditorClosed(listenerDispose, resourcesToWaitFor, waitMarkerFile));
I
isidor 已提交
812

813
			this._register(listenerDispose);
814
		}
S
Sanders Lauture 已提交
815

816
		// Configuration changes
817
		this._register(this.configurationService.onDidChangeConfiguration(() => this.onDidUpdateConfiguration()));
I
isidor 已提交
818

819
		// Fullscreen changes
820
		this._register(onDidChangeFullscreen(() => this.onFullscreenChanged()));
B
Benjamin Pasero 已提交
821 822 823 824

		// Group changes
		this._register(this.editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.shouldCenterLayout)));
		this._register(this.editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.shouldCenterLayout)));
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850

		// Layout
		this._register(addDisposableListener(window, EventType.RESIZE, e => this.onWindowResize(e, true)));

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

	private onWindowResize(e: any, retry: boolean): void {
		if (e.target === window) {
			if (window.document && window.document.body && window.document.body.clientWidth === 0) {
				// TODO@Ben this is an electron issue on macOS when simple fullscreen is enabled
				// where for some reason the window clientWidth is reported as 0 when switching
				// between simple fullscreen and normal screen. In that case we schedule the layout
				// call at the next animation frame once, in the hope that the dimensions are
				// proper then.
				if (retry) {
					scheduleAtNextAnimationFrame(() => this.onWindowResize(e, false));
				}
				return;
			}

			this.layout();
		}
851
	}
852

853
	private onFullscreenChanged(): void {
S
SrTobi 已提交
854

855
		// Apply as CSS class
856 857
		if (isFullscreen()) {
			addClass(this.workbench, 'fullscreen');
858
		} else {
859
			removeClass(this.workbench, 'fullscreen');
B
Benjamin Pasero 已提交
860

861 862 863 864
			if (this.zenMode.transitionedToFullScreen && this.zenMode.active) {
				this.toggleZenMode();
			}
		}
E
Erich Gamma 已提交
865

866
		// Changing fullscreen state of the window has an impact on custom title bar visibility, so we need to update
B
Benjamin Pasero 已提交
867
		if (this.useCustomTitleBarStyle()) {
868 869 870
			this._onTitleBarVisibilityChange.fire();
			this.layout(); // handle title bar when fullscreen changes
		}
871 872
	}

873 874 875 876
	private onMenubarToggled(visible: boolean) {
		if (visible !== this.menubarToggled) {
			this.menubarToggled = visible;

877
			if (isFullscreen() && (this.menubarVisibility === 'toggle' || this.menubarVisibility === 'default')) {
878
				this._onTitleBarVisibilityChange.fire();
879 880 881 882 883
				this.layout();
			}
		}
	}

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

886 887 888
		// In wait mode, listen to changes to the editors and wait until the files
		// are closed that the user wants to wait for. When this happens we delete
		// the wait marker file to signal to the outside that editing is done.
889
		if (resourcesToWaitFor.every(resource => !this.editorService.isOpen({ resource }))) {
890
			listenerDispose.dispose();
891
			this.fileService.del(waitMarkerFile);
892
		}
E
Erich Gamma 已提交
893 894
	}

895
	private onDidVisibleEditorsChange(): void {
896
		const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
897

898 899 900 901 902 903 904 905 906
		// Close when empty: check if we should close the window based on the setting
		// Overruled by: window has a workspace opened or this window is for extension development
		// or setting is disabled. Also enabled when running with --wait from the command line.
		if (visibleEditors.length === 0 && this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && !this.environmentService.isExtensionDevelopment) {
			const closeWhenEmpty = this.configurationService.getValue<boolean>(Workbench.closeWhenEmptyConfigurationKey);
			if (closeWhenEmpty || this.environmentService.args.wait) {
				this.closeEmptyWindowScheduler.schedule();
			}
		}
907 908 909 910

		if (this.editorHidden) {
			this.setEditorHidden(false);
		}
911 912
	}

913
	private onAllEditorsClosed(): void {
914
		const visibleEditors = this.editorService.visibleControls.length;
915 916
		if (visibleEditors === 0) {
			this.windowService.closeWindow();
E
Erich Gamma 已提交
917 918 919
		}
	}

920 921 922 923 924
	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);
925
		}
E
Erich Gamma 已提交
926

927
		this.setPanelPositionFromStorageOrConfig();
E
Erich Gamma 已提交
928

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

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

940 941 942 943
			const newActivityBarHiddenValue = !this.configurationService.getValue<boolean>(Workbench.activityBarVisibleConfigurationKey);
			if (newActivityBarHiddenValue !== this.activityBarHidden) {
				this.setActivityBarHidden(newActivityBarHiddenValue, skipLayout);
			}
B
Benjamin Pasero 已提交
944
		}
S
SteVen Batten 已提交
945

946
		const newMenubarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
947
		this.setMenubarVisibility(newMenubarVisibility, !!skipLayout);
948
	}
B
Benjamin Pasero 已提交
949

950
	//#endregion
B
Benjamin Pasero 已提交
951

952 953
	private handleContextKeys(): void {
		this.inZenMode = InEditorZenModeContext.bindTo(this.contextKeyService);
954

I
isidor 已提交
955 956 957
		IsMacContext.bindTo(this.contextKeyService);
		IsLinuxContext.bindTo(this.contextKeyService);
		IsWindowsContext.bindTo(this.contextKeyService);
958
		SupportsWorkspacesContext.bindTo(this.contextKeyService);
A
Alex Ross 已提交
959
		const supportsOpenFileFolderContextKey = SupportsOpenFileFolderContext.bindTo(this.contextKeyService);
960
		SupportsWorkspacesContext.bindTo(this.contextKeyService);
A
Alex Ross 已提交
961 962 963
		if (this.windowService.getConfiguration().remoteAuthority) {
			supportsOpenFileFolderContextKey.set(true);
		}
964

965 966
		const sidebarVisibleContextRaw = new RawContextKey<boolean>('sidebarVisible', false);
		this.sideBarVisibleContext = sidebarVisibleContextRaw.bindTo(this.contextKeyService);
967

968
		const activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService);
969 970
		const editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
		const textCompareEditorVisible = TextCompareEditorVisibleContext.bindTo(this.contextKeyService);
971
		const textCompareEditorActive = TextCompareEditorActiveContext.bindTo(this.contextKeyService);
972 973
		const activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
		const multipleEditorGroups = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
974

975
		const updateEditorContextKeys = () => {
976
			const activeControl = this.editorService.activeControl;
977
			const visibleEditors = this.editorService.visibleControls;
E
Erich Gamma 已提交
978

979
			textCompareEditorActive.set(!!activeControl && activeControl.getId() === TEXT_DIFF_EDITOR_ID);
980
			textCompareEditorVisible.set(visibleEditors.some(control => control.getId() === TEXT_DIFF_EDITOR_ID));
I
isidor 已提交
981

982 983 984 985
			if (visibleEditors.length > 0) {
				editorsVisibleContext.set(true);
			} else {
				editorsVisibleContext.reset();
986
			}
B
Benjamin Pasero 已提交
987

988
			if (!this.editorService.activeEditor) {
989 990 991
				activeEditorGroupEmpty.set(true);
			} else {
				activeEditorGroupEmpty.reset();
992
			}
993

B
Benjamin Pasero 已提交
994
			if (this.editorGroupService.count > 1) {
995 996 997 998
				multipleEditorGroups.set(true);
			} else {
				multipleEditorGroups.reset();
			}
999 1000 1001 1002 1003 1004

			if (activeControl) {
				activeEditorContext.set(activeControl.getId());
			} else {
				activeEditorContext.reset();
			}
1005
		};
B
Benjamin Pasero 已提交
1006

1007
		this.editorPart.whenRestored.then(() => updateEditorContextKeys());
1008 1009
		this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys()));
		this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys()));
B
Benjamin Pasero 已提交
1010 1011
		this._register(this.editorGroupService.onDidAddGroup(() => updateEditorContextKeys()));
		this._register(this.editorGroupService.onDidRemoveGroup(() => updateEditorContextKeys()));
1012

1013
		const inputFocused = InputFocusedContext.bindTo(this.contextKeyService);
B
Benjamin Pasero 已提交
1014 1015

		function activeElementIsInput(): boolean {
1016
			return !!document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA');
B
Benjamin Pasero 已提交
1017 1018 1019 1020 1021 1022 1023
		}

		function trackInputFocus(): void {
			const isInputFocused = activeElementIsInput();
			inputFocused.set(isInputFocused);

			if (isInputFocused) {
1024
				const tracker = trackFocus(document.activeElement as HTMLElement);
J
Joao Moreno 已提交
1025
				Event.once(tracker.onDidBlur)(() => {
B
Benjamin Pasero 已提交
1026 1027 1028 1029 1030 1031 1032
					inputFocused.set(activeElementIsInput());

					tracker.dispose();
				});
			}
		}

1033
		this._register(addDisposableListener(window, 'focusin', () => trackInputFocus(), true));
1034 1035 1036 1037 1038 1039

		const workbenchStateRawContext = new RawContextKey<string>('workbenchState', getWorkbenchStateString(this.configurationService.getWorkbenchState()));
		const workbenchStateContext = workbenchStateRawContext.bindTo(this.contextKeyService);
		this._register(this.configurationService.onDidChangeWorkbenchState(() => {
			workbenchStateContext.set(getWorkbenchStateString(this.configurationService.getWorkbenchState()));
		}));
I
isidor 已提交
1040

1041 1042 1043 1044 1045
		const workspaceFolderCountRawContext = new RawContextKey<number>('workspaceFolderCount', this.configurationService.getWorkspace().folders.length);
		const workspaceFolderCountContext = workspaceFolderCountRawContext.bindTo(this.contextKeyService);
		this._register(this.configurationService.onDidChangeWorkspaceFolders(() => {
			workspaceFolderCountContext.set(this.configurationService.getWorkspace().folders.length);
		}));
1046

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

1049 1050 1051 1052
		const updateSplitEditorsVerticallyContext = () => {
			const direction = preferredSideBySideGroupDirection(this.configurationService);
			splitEditorsVerticallyContext.set(direction === GroupDirection.DOWN);
		};
S
Sanders Lauture 已提交
1053

1054 1055 1056 1057 1058
		this._register(this.configurationService.onDidChangeConfiguration(e => {
			if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) {
				updateSplitEditorsVerticallyContext();
			}
		}));
E
Erich Gamma 已提交
1059

1060
		updateSplitEditorsVerticallyContext();
1061
	}
E
Erich Gamma 已提交
1062

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

1066
		// Restore Editorpart
1067
		mark('willRestoreEditors');
1068
		restorePromises.push(this.editorPart.whenRestored.then(() => {
B
Benjamin Pasero 已提交
1069 1070 1071 1072

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

J
Johannes Rieken 已提交
1075
				return Promise.resolve(undefined);
B
Benjamin Pasero 已提交
1076 1077 1078 1079 1080 1081 1082 1083 1084
			}

			const editorsToOpen = this.resolveEditorsToOpen();

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

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

1087
		// Restore Sidebar
1088
		let viewletIdToRestore: string | undefined;
1089 1090
		if (!this.sideBarHidden) {
			this.sideBarVisibleContext.set(true);
1091

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

1096
			if (!viewletIdToRestore) {
I
isidor 已提交
1097
				viewletIdToRestore = this.sidebarPart.getDefaultViewletId();
1098
			}
E
Erich Gamma 已提交
1099

1100
			mark('willRestoreViewlet');
I
isidor 已提交
1101 1102
			restorePromises.push(this.sidebarPart.openViewlet(viewletIdToRestore)
				.then(viewlet => viewlet || this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId()))
1103
				.then(() => mark('didRestoreViewlet')));
1104 1105
		}

1106 1107
		// Restore Panel
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
1108
		const panelId = this.storageService.get(PanelPart.activePanelSettingsKey, StorageScope.WORKSPACE, panelRegistry.getDefaultPanelId());
1109
		if (!this.panelHidden && !!panelId) {
1110
			mark('willRestorePanel');
1111
			const isPanelToRestoreEnabled = !!this.panelPart.getPanels().filter(p => p.id === panelId).length;
1112
			const panelIdToRestore = isPanelToRestoreEnabled ? panelId : panelRegistry.getDefaultPanelId();
1113
			this.panelPart.openPanel(panelIdToRestore, false);
1114
			mark('didRestorePanel');
I
isidor 已提交
1115 1116
		}

1117 1118 1119
		// 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);
1120
		if (wasZenActive && zenConfig.restore) {
I
isidor 已提交
1121
			this.toggleZenMode(true, true);
I
isidor 已提交
1122 1123
		}

B
Benjamin Pasero 已提交
1124
		// Restore Forced Editor Center Mode
1125
		if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) {
I
isidor 已提交
1126
			this.centerEditorLayout(true);
S
SrTobi 已提交
1127
		}
1128

1129
		const onRestored = (error?: Error): void => {
B
Benjamin Pasero 已提交
1130 1131 1132 1133 1134
			this.workbenchRestored = true;

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

1135 1136 1137 1138 1139 1140 1141
			// 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);
1142

1143
			if (error) {
1144
				onUnexpectedError(error);
1145
			}
I
isidor 已提交
1146

1147
			this.logStartupTelemetry({
1148
				customKeybindingsCount: this.keybindingService.customKeybindingsCount(),
P
Pine Wu 已提交
1149
				pinnedViewlets: this.activitybarPart.getPinnedViewletIds(),
1150
				restoredViewlet: viewletIdToRestore,
1151
				restoredEditorsCount: this.editorService.visibleEditors.length
1152
			});
1153
		};
1154

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

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
	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');
	}

1202 1203 1204
	private shouldRestoreLastOpenedViewlet(): boolean {
		if (!this.environmentService.isBuilt) {
			return true; // always restore sidebar when we are in development mode
E
Erich Gamma 已提交
1205 1206
		}

1207 1208
		// always restore sidebar when the window was reloaded
		return this.lifecycleService.startupKind === StartupKind.ReloadedWindow;
E
Erich Gamma 已提交
1209 1210
	}

J
Johannes Rieken 已提交
1211
	private resolveEditorsToOpen(): Promise<IResourceEditor[]> | IResourceEditor[] {
1212
		const config = this.workbenchParams.configuration;
I
isidor 已提交
1213

B
Benjamin Pasero 已提交
1214
		// Files to open, diff or create
1215
		if (this.hasInitialFilesToOpen) {
I
isidor 已提交
1216

B
Benjamin Pasero 已提交
1217
			// Files to diff is exclusive
1218
			const filesToDiff = this.toInputs(config.filesToDiff, false);
1219
			if (filesToDiff && filesToDiff.length === 2) {
B
Benjamin Pasero 已提交
1220
				return [<IResourceDiffInput>{
1221 1222
					leftResource: filesToDiff[0].resource,
					rightResource: filesToDiff[1].resource,
B
Benjamin Pasero 已提交
1223
					options: { pinned: true },
B
Benjamin Pasero 已提交
1224
					forceFile: true
B
Benjamin Pasero 已提交
1225
				}];
B
Benjamin Pasero 已提交
1226
			}
I
isidor 已提交
1227

1228 1229
			const filesToCreate = this.toInputs(config.filesToCreate, true);
			const filesToOpen = this.toInputs(config.filesToOpen, false);
I
isidor 已提交
1230

1231
			// Otherwise: Open/Create files
B
Benjamin Pasero 已提交
1232
			return [...filesToOpen, ...filesToCreate];
B
Benjamin Pasero 已提交
1233
		}
I
isidor 已提交
1234

1235
		// Empty workbench
1236
		else if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY && this.openUntitledFile()) {
B
Benjamin Pasero 已提交
1237
			const isEmpty = this.editorGroupService.count === 1 && this.editorGroupService.activeGroup.count === 0;
1238
			if (!isEmpty) {
B
Benjamin Pasero 已提交
1239
				return []; // do not open any empty untitled file if we restored editors from previous session
1240
			}
B
Benjamin Pasero 已提交
1241

1242 1243
			return this.backupFileService.hasBackups().then(hasBackups => {
				if (hasBackups) {
B
Benjamin Pasero 已提交
1244
					return []; // do not open any empty untitled file if we have backups to restore
1245
				}
B
Benjamin Pasero 已提交
1246

B
Benjamin Pasero 已提交
1247
				return [<IUntitledResourceInput>{}];
1248
			});
1249
		}
1250

B
Benjamin Pasero 已提交
1251
		return [];
B
Benjamin Pasero 已提交
1252
	}
1253

1254
	private toInputs(paths: IPath[], isNew: boolean): Array<IResourceInput | IUntitledResourceInput> {
B
Benjamin Pasero 已提交
1255 1256
		if (!paths || !paths.length) {
			return [];
1257
		}
I
isidor 已提交
1258

B
Benjamin Pasero 已提交
1259
		return paths.map(p => {
1260
			const resource = p.fileUri;
1261 1262 1263 1264
			let input: IResourceInput | IUntitledResourceInput;
			if (isNew) {
				input = { filePath: resource.fsPath, options: { pinned: true } } as IUntitledResourceInput;
			} else {
B
Benjamin Pasero 已提交
1265
				input = { resource, options: { pinned: true }, forceFile: true } as IResourceInput;
1266
			}
E
Erich Gamma 已提交
1267

1268
			if (!isNew && p.lineNumber) {
B
Benjamin Pasero 已提交
1269 1270 1271 1272 1273
				input.options.selection = {
					startLineNumber: p.lineNumber,
					startColumn: p.columnNumber
				};
			}
1274

B
Benjamin Pasero 已提交
1275 1276
			return input;
		});
1277 1278
	}

1279
	private openUntitledFile() {
1280
		const startupEditor = this.configurationService.inspect('workbench.startupEditor');
B
Benjamin Pasero 已提交
1281 1282

		// Fallback to previous workbench.welcome.enabled setting in case startupEditor is not defined
1283
		if (!startupEditor.user && !startupEditor.workspace) {
1284 1285 1286
			const welcomeEnabledValue = this.configurationService.getValue('workbench.welcome.enabled');
			if (typeof welcomeEnabledValue === 'boolean') {
				return !welcomeEnabledValue;
1287
			}
1288
		}
E
Erich Gamma 已提交
1289

1290
		return startupEditor.value === 'newUntitledFile';
1291
	}
E
Erich Gamma 已提交
1292 1293

	private initSettings(): void {
1294

S
SteVen Batten 已提交
1295 1296 1297
		// Editor visiblity
		this.editorHidden = false;

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

I
isidor 已提交
1301
		// Panel part visibility
1302
		const panelRegistry = Registry.as<PanelRegistry>(PanelExtensions.Panels);
1303
		this.panelHidden = this.storageService.getBoolean(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE, true);
1304 1305
		if (!panelRegistry.getDefaultPanelId()) {
			this.panelHidden = true; // we hide panel part if there is no default panel
1306 1307
		}

E
Erich Gamma 已提交
1308
		// Sidebar position
1309
		const sideBarPosition = this.configurationService.getValue<string>(Workbench.sidebarPositionConfigurationKey);
1310
		this.sideBarPosition = (sideBarPosition === 'right') ? Position.RIGHT : Position.LEFT;
1311

I
isidor 已提交
1312
		// Panel position
1313
		this.setPanelPositionFromStorageOrConfig();
1314

1315
		// Menubar visibility
1316
		const menuBarVisibility = this.configurationService.getValue<MenuBarVisibility>(Workbench.menubarVisibilityConfigurationKey);
S
SteVen Batten 已提交
1317
		this.setMenubarVisibility(menuBarVisibility, true);
1318

B
Benjamin Pasero 已提交
1319
		// Statusbar visibility
1320
		const statusBarVisible = this.configurationService.getValue<string>(Workbench.statusbarVisibleConfigurationKey);
1321
		this.statusBarHidden = !statusBarVisible;
1322

S
Sanders Lauture 已提交
1323
		// Activity bar visibility
1324
		const activityBarVisible = this.configurationService.getValue<string>(Workbench.activityBarVisibleConfigurationKey);
S
Sanders Lauture 已提交
1325
		this.activityBarHidden = !activityBarVisible;
1326

1327
		// Font aliasing
1328
		this.fontAliasing = this.configurationService.getValue<FontAliasingOption>(Workbench.fontAliasingConfigurationKey);
1329

I
isidor 已提交
1330 1331
		// Zen mode
		this.zenMode = {
I
isidor 已提交
1332
			active: false,
1333
			transitionedToFullScreen: false,
1334
			transitionedToCenteredEditorLayout: false,
1335
			wasSideBarVisible: false,
1336 1337
			wasPanelVisible: false,
			transitionDisposeables: []
I
isidor 已提交
1338
		};
E
Erich Gamma 已提交
1339 1340
	}

1341 1342
	private setPanelPositionFromStorageOrConfig() {
		const defaultPanelPosition = this.configurationService.getValue<string>(Workbench.defaultPanelPositionStorageKey);
1343
		const panelPosition = this.storageService.get(Workbench.panelPositionStorageKey, StorageScope.WORKSPACE, defaultPanelPosition);
1344

1345 1346
		this.panelPosition = (panelPosition === 'right') ? Position.RIGHT : Position.BOTTOM;
	}
1347

B
Benjamin Pasero 已提交
1348 1349
	private useCustomTitleBarStyle(): boolean {
		return getTitleBarStyle(this.configurationService, this.environmentService) === 'custom';
B
Benjamin Pasero 已提交
1350 1351
	}

1352
	private saveLastPanelDimension(): void {
S
SteVen Batten 已提交
1353
		if (!(this.workbenchGrid instanceof Grid)) {
1354 1355 1356 1357
			return;
		}

		if (this.panelPosition === Position.BOTTOM) {
S
SteVen Batten 已提交
1358
			this.uiState.lastPanelHeight = this.workbenchGrid.getViewSize(this.panelPartView);
1359
		} else {
S
SteVen Batten 已提交
1360
			this.uiState.lastPanelWidth = this.workbenchGrid.getViewSize(this.panelPartView);
1361 1362 1363 1364 1365 1366 1367
		}
	}

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

1368 1369
	private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.statusBarHidden = hidden;
B
Benjamin Pasero 已提交
1370

1371 1372
		// Adjust CSS
		if (hidden) {
1373
			addClass(this.workbench, 'nostatusbar');
E
Erich Gamma 已提交
1374
		} else {
1375
			removeClass(this.workbench, 'nostatusbar');
E
Erich Gamma 已提交
1376 1377
		}

1378 1379
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1380
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1381
				this.layout();
1382 1383 1384
			} else {
				this.workbenchGrid.layout();
			}
1385 1386 1387
		}
	}

1388
	private setFontAliasing(aliasing: FontAliasingOption) {
1389
		this.fontAliasing = aliasing;
S
Sanders Lauture 已提交
1390

B
Benjamin Pasero 已提交
1391 1392 1393 1394 1395
		// Remove all
		document.body.classList.remove(...fontAliasingValues.map(value => `monaco-font-aliasing-${value}`));

		// Add specific
		if (fontAliasingValues.some(option => option === aliasing)) {
1396
			document.body.classList.add(`monaco-font-aliasing-${aliasing}`);
S
Sanders Lauture 已提交
1397
		}
1398 1399
	}

E
Erich Gamma 已提交
1400
	private createWorkbenchLayout(): void {
1401
		if (this.configurationService.getValue('workbench.useExperimentalGridLayout')) {
1402

S
SteVen Batten 已提交
1403 1404 1405 1406 1407 1408 1409 1410 1411
			// 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 });
1412

1413
			this.workbench.prepend(this.workbenchGrid.element);
1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
		} 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 已提交
1433 1434 1435 1436 1437 1438
	}

	private renderWorkbench(): void {

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

1442
		if (this.panelHidden) {
1443
			addClass(this.workbench, 'nopanel');
1444
		}
B
Benjamin Pasero 已提交
1445

1446
		if (this.statusBarHidden) {
1447
			addClass(this.workbench, 'nostatusbar');
1448
		}
E
Erich Gamma 已提交
1449

B
Benjamin Pasero 已提交
1450
		// Apply font aliasing
1451 1452
		this.setFontAliasing(this.fontAliasing);

1453
		// Apply fullscreen state
1454 1455
		if (isFullscreen()) {
			addClass(this.workbench, 'fullscreen');
B
Benjamin Pasero 已提交
1456 1457
		}

E
Erich Gamma 已提交
1458
		// Create Parts
B
Benjamin Pasero 已提交
1459
		this.createTitlebarPart();
E
Erich Gamma 已提交
1460 1461 1462
		this.createActivityBarPart();
		this.createSidebarPart();
		this.createEditorPart();
1463
		this.createPanelPart();
E
Erich Gamma 已提交
1464 1465
		this.createStatusbarPart();

1466 1467
		// Notification Handlers
		this.createNotificationsHandlers();
1468

1469 1470

		// Menubar visibility changes
B
Benjamin Pasero 已提交
1471
		if ((isWindows || isLinux) && this.useCustomTitleBarStyle()) {
1472 1473 1474
			this.titlebarPart.onMenubarVisibilityChange()(e => this.onMenubarToggled(e));
		}

E
Erich Gamma 已提交
1475
		// Add Workbench to DOM
B
Benjamin Pasero 已提交
1476
		this.container.appendChild(this.workbench);
E
Erich Gamma 已提交
1477 1478
	}

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

B
Benjamin Pasero 已提交
1482
		this.titlebarPart.create(titlebarContainer);
B
Benjamin Pasero 已提交
1483 1484
	}

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

B
Benjamin Pasero 已提交
1488
		this.activitybarPart.create(activitybarPartContainer);
E
Erich Gamma 已提交
1489 1490 1491
	}

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

B
Benjamin Pasero 已提交
1494
		this.sidebarPart.create(sidebarPartContainer);
E
Erich Gamma 已提交
1495 1496
	}

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

B
Benjamin Pasero 已提交
1500
		this.panelPart.create(panelPartContainer);
I
isidor 已提交
1501 1502
	}

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

B
Benjamin Pasero 已提交
1506
		this.editorPart.create(editorContainer);
E
Erich Gamma 已提交
1507 1508 1509
	}

	private createStatusbarPart(): void {
B
Benjamin Pasero 已提交
1510 1511 1512 1513 1514 1515 1516
		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');
1517
		classes.forEach(clazz => addClass(part, clazz));
B
Benjamin Pasero 已提交
1518 1519 1520
		part.id = id;
		part.setAttribute('role', role);

1521 1522 1523 1524 1525
		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 已提交
1526

B
Benjamin Pasero 已提交
1527
		return part;
E
Erich Gamma 已提交
1528 1529
	}

1530 1531
	private createNotificationsHandlers(): void {

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

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

1538
		// Notifications Alerts
1539
		this._register(this.instantiationService.createInstance(NotificationsAlerts, this.notificationService.model));
1540 1541 1542 1543

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

1544
		// Eventing
1545
		this._register(this.notificationsCenter.onDidChangeVisibility(() => {
1546 1547 1548 1549 1550 1551 1552 1553

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

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

1554
		// Register Commands
1555
		registerNotificationCommands(this.notificationsCenter, this.notificationsToasts);
1556 1557
	}

1558
	private saveState(e: IWillSaveStateEvent): void {
1559
		if (this.zenMode.active) {
B
Benjamin Pasero 已提交
1560
			this.storageService.store(Workbench.zenModeActiveStorageKey, true, StorageScope.WORKSPACE);
1561
		} else {
B
Benjamin Pasero 已提交
1562
			this.storageService.remove(Workbench.zenModeActiveStorageKey, StorageScope.WORKSPACE);
1563
		}
1564 1565 1566 1567 1568 1569 1570 1571

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

1574
	dispose(): void {
1575
		super.dispose();
1576 1577 1578 1579 1580 1581

		this.workbenchShutdown = true;
	}

	//#region IPartService

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

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

B
Benjamin Pasero 已提交
1587 1588
	isRestored(): boolean {
		return !!(this.workbenchRestored && this.workbenchStarted);
1589
	}
1590

1591 1592 1593 1594 1595
	hasFocus(part: Parts): boolean {
		const activeElement = document.activeElement;
		if (!activeElement) {
			return false;
		}
1596

1597
		const container = this.getContainer(part);
1598
		return isAncestor(activeElement, container);
1599
	}
1600

1601
	getContainer(part: Parts): HTMLElement | null {
1602 1603
		switch (part) {
			case Parts.TITLEBAR_PART:
1604
				return this.titlebarPart.getContainer();
1605
			case Parts.ACTIVITYBAR_PART:
1606
				return this.activitybarPart.getContainer();
1607
			case Parts.SIDEBAR_PART:
1608
				return this.sidebarPart.getContainer();
1609
			case Parts.PANEL_PART:
1610
				return this.panelPart.getContainer();
1611
			case Parts.EDITOR_PART:
1612
				return this.editorPart.getContainer();
1613
			case Parts.STATUSBAR_PART:
1614
				return this.statusbarPart.getContainer();
1615
		}
1616

1617
		return null;
1618
	}
1619

1620 1621 1622
	isVisible(part: Parts): boolean {
		switch (part) {
			case Parts.TITLEBAR_PART:
B
Benjamin Pasero 已提交
1623
				if (!this.useCustomTitleBarStyle()) {
1624
					return false;
1625
				} else if (!isFullscreen()) {
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
					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;
1636 1637 1638 1639 1640 1641 1642 1643
			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;
1644 1645
			case Parts.EDITOR_PART:
				return this.workbenchGrid instanceof Grid ? !this.editorHidden : true;
E
Erich Gamma 已提交
1646
		}
1647

1648
		return true; // any other part cannot be hidden
E
Erich Gamma 已提交
1649 1650
	}

1651 1652 1653
	getTitleBarOffset(): number {
		let offset = 0;
		if (this.isVisible(Parts.TITLEBAR_PART)) {
S
SteVen Batten 已提交
1654
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1655
				offset = this.titlebarPart.maximumHeight;
S
SteVen Batten 已提交
1656 1657 1658
			} else {
				offset = this.workbenchGrid.partLayoutInfo.titlebar.height;

B
Benjamin Pasero 已提交
1659 1660 1661
				if (isMacintosh || this.menubarVisibility === 'hidden') {
					offset /= getZoomFactor();
				}
1662
			}
E
Erich Gamma 已提交
1663
		}
1664 1665

		return offset;
E
Erich Gamma 已提交
1666
	}
1667

1668 1669
	getWorkbenchElement(): HTMLElement {
		return this.workbench;
1670
	}
1671

I
isidor 已提交
1672
	toggleZenMode(skipLayout?: boolean, restoring = false): void {
I
isidor 已提交
1673
		this.zenMode.active = !this.zenMode.active;
1674
		this.zenMode.transitionDisposeables = dispose(this.zenMode.transitionDisposeables);
1675

1676 1677
		// 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)
1678
		let toggleFullScreen = false;
I
isidor 已提交
1679 1680 1681 1682 1683 1684 1685 1686
		const setLineNumbers = (lineNumbers: any) => {
			this.editorService.visibleControls.forEach(editor => {
				const control = <IEditor>editor.getControl();
				if (control) {
					control.updateOptions({ lineNumbers });
				}
			});
		};
1687 1688

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

1692
			toggleFullScreen = !isFullscreen() && config.fullScreen;
I
isidor 已提交
1693
			this.zenMode.transitionedToFullScreen = restoring ? config.fullScreen : toggleFullScreen;
1694
			this.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout;
1695 1696
			this.zenMode.wasSideBarVisible = this.isVisible(Parts.SIDEBAR_PART);
			this.zenMode.wasPanelVisible = this.isVisible(Parts.PANEL_PART);
1697

1698 1699
			this.setPanelHidden(true, true);
			this.setSideBarHidden(true, true);
I
isidor 已提交
1700

1701 1702 1703
			if (config.hideActivityBar) {
				this.setActivityBarHidden(true, true);
			}
1704

I
isidor 已提交
1705
			if (config.hideStatusBar) {
I
isidor 已提交
1706 1707
				this.setStatusBarHidden(true, true);
			}
1708

I
isidor 已提交
1709 1710 1711 1712 1713
			if (config.hideLineNumbers) {
				setLineNumbers('off');
				this.zenMode.transitionDisposeables.push(this.editorService.onDidVisibleEditorsChange(() => setLineNumbers('off')));
			}

1714 1715
			if (config.hideTabs && this.editorPart.partOptions.showTabs) {
				this.zenMode.transitionDisposeables.push(this.editorPart.enforcePartOptions({ showTabs: false }));
I
isidor 已提交
1716
			}
1717 1718 1719 1720

			if (config.centerLayout) {
				this.centerEditorLayout(true, true);
			}
1721 1722 1723 1724
		}

		// Zen Mode Inactive
		else {
1725
			if (this.zenMode.wasPanelVisible) {
1726
				this.setPanelHidden(false, true);
1727
			}
1728

1729
			if (this.zenMode.wasSideBarVisible) {
1730
				this.setSideBarHidden(false, true);
1731
			}
1732

1733 1734 1735
			if (this.zenMode.transitionedToCenteredEditorLayout) {
				this.centerEditorLayout(false, true);
			}
I
isidor 已提交
1736
			setLineNumbers(this.configurationService.getValue('editor.lineNumbers'));
1737

1738 1739
			// Status bar and activity bar visibility come from settings -> update their visibility.
			this.onDidUpdateConfiguration(true);
1740

B
Benjamin Pasero 已提交
1741
			this.editorGroupService.activeGroup.focus();
1742

1743
			toggleFullScreen = this.zenMode.transitionedToFullScreen && isFullscreen();
I
isidor 已提交
1744
		}
1745

1746
		this.inZenMode.set(this.zenMode.active);
I
isidor 已提交
1747

I
isidor 已提交
1748
		if (!skipLayout) {
1749
			this.layout();
I
isidor 已提交
1750
		}
1751

1752
		if (toggleFullScreen) {
1753
			this.windowService.toggleFullScreen();
1754
		}
I
isidor 已提交
1755 1756
	}

S
SteVen Batten 已提交
1757
	private updateGrid(): void {
S
SteVen Batten 已提交
1758
		if (!(this.workbenchGrid instanceof Grid)) {
1759 1760 1761
			return;
		}

S
SteVen Batten 已提交
1762 1763 1764 1765 1766
		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);
1767

S
SteVen Batten 已提交
1768 1769 1770
		// Add parts to grid
		if (!statusBarInGrid) {
			this.workbenchGrid.addView(this.statusbarPartView, Sizing.Split, this.editorPartView, Direction.Down);
S
SteVen Batten 已提交
1771 1772 1773
			statusBarInGrid = true;
		}

1774
		if (!titlebarInGrid && this.useCustomTitleBarStyle()) {
S
SteVen Batten 已提交
1775 1776 1777
			this.workbenchGrid.addView(this.titlebarPartView, Sizing.Split, this.editorPartView, Direction.Up);
			titlebarInGrid = true;
		}
S
SteVen Batten 已提交
1778

S
SteVen Batten 已提交
1779 1780 1781 1782
		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 已提交
1783

S
SteVen Batten 已提交
1784 1785 1786 1787
		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 已提交
1788

S
SteVen Batten 已提交
1789 1790 1791
		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 已提交
1792 1793
		}

S
SteVen Batten 已提交
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
		// 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 已提交
1819
		// Show visible parts
S
SteVen Batten 已提交
1820 1821 1822 1823
		if (!this.editorHidden) {
			this.editorPartView.show();
		}

S
SteVen Batten 已提交
1824 1825 1826
		if (!this.statusBarHidden) {
			this.statusbarPartView.show();
		}
S
SteVen Batten 已提交
1827

S
SteVen Batten 已提交
1828 1829
		if (this.isVisible(Parts.TITLEBAR_PART)) {
			this.titlebarPartView.show();
S
SteVen Batten 已提交
1830 1831
		}

S
SteVen Batten 已提交
1832 1833 1834
		if (!this.activityBarHidden) {
			this.activitybarPartView.show();
		}
S
SteVen Batten 已提交
1835

S
SteVen Batten 已提交
1836 1837
		if (!this.sideBarHidden) {
			this.sidebarPartView.show();
S
SteVen Batten 已提交
1838 1839
		}

S
SteVen Batten 已提交
1840 1841
		if (!this.panelHidden) {
			this.panelPartView.show();
S
SteVen Batten 已提交
1842 1843 1844
		}
	}

1845
	private layout(options?: ILayoutOptions): void {
S
SteVen Batten 已提交
1846 1847 1848
		this.contextViewService.layout();

		if (this.workbenchStarted && !this.workbenchShutdown) {
S
SteVen Batten 已提交
1849
			if (this.workbenchGrid instanceof Grid) {
1850 1851 1852
				const dimensions = getClientArea(this.container);
				position(this.workbench, 0, 0, 0, 0, 'relative');
				size(this.workbench, dimensions.width, dimensions.height);
S
SteVen Batten 已提交
1853

S
SteVen Batten 已提交
1854
				// Layout the grid
S
SteVen Batten 已提交
1855
				this.workbenchGrid.layout(dimensions.width, dimensions.height);
S
SteVen Batten 已提交
1856 1857 1858 1859 1860 1861 1862 1863

				// 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
1864
				this.updateGrid();
S
SteVen Batten 已提交
1865 1866
			} else {
				this.workbenchGrid.layout(options);
1867
			}
1868 1869 1870
		}
	}

1871
	isEditorLayoutCentered(): boolean {
1872
		return this.shouldCenterLayout;
S
SrTobi 已提交
1873 1874
	}

1875
	centerEditorLayout(active: boolean, skipLayout?: boolean): void {
B
Benjamin Pasero 已提交
1876
		this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, active, StorageScope.WORKSPACE);
1877 1878
		this.shouldCenterLayout = active;
		let smartActive = active;
1879
		if (this.editorPart.groups.length > 1 && this.configurationService.getValue('workbench.editor.centeredLayoutAutoResize')) {
B
Benjamin Pasero 已提交
1880
			smartActive = false; // Respect the auto resize setting - do not go into centered layout if there is more than 1 group.
1881
		}
B
Benjamin Pasero 已提交
1882

1883
		// Enter Centered Editor Layout
1884 1885
		if (this.editorPart.isLayoutCentered() !== smartActive) {
			this.editorPart.centerLayout(smartActive);
1886

1887 1888 1889
			if (!skipLayout) {
				this.layout();
			}
1890
		}
S
SrTobi 已提交
1891 1892
	}

1893
	resizePart(part: Parts, sizeChange: number): void {
S
SteVen Batten 已提交
1894
		let view: View;
1895 1896
		switch (part) {
			case Parts.SIDEBAR_PART:
S
SteVen Batten 已提交
1897
				view = this.sidebarPartView;
1898
			case Parts.PANEL_PART:
S
SteVen Batten 已提交
1899
				view = this.panelPartView;
1900
			case Parts.EDITOR_PART:
S
SteVen Batten 已提交
1901 1902
				view = this.editorPartView;
				if (this.workbenchGrid instanceof Grid) {
1903 1904 1905 1906
					this.workbenchGrid.resizeView(view, this.workbenchGrid.getViewSize(view) + sizeChange);
				} else {
					this.workbenchGrid.resizePart(part, sizeChange);
				}
1907 1908
				break;
			default:
B
Benjamin Pasero 已提交
1909
				return; // Cannot resize other parts
1910 1911 1912
		}
	}

1913 1914
	setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
		this.activityBarHidden = hidden;
1915

1916 1917
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1918
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1919
				this.layout();
1920 1921 1922
			} else {
				this.workbenchGrid.layout();
			}
1923
		}
1924
	}
1925

S
SteVen Batten 已提交
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942
	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();
		}
	}

1943
	setSideBarHidden(hidden: boolean, skipLayout?: boolean): void {
1944 1945 1946 1947 1948
		this.sideBarHidden = hidden;
		this.sideBarVisibleContext.set(!hidden);

		// Adjust CSS
		if (hidden) {
1949
			addClass(this.workbench, 'nosidebar');
1950
		} else {
1951
			removeClass(this.workbench, 'nosidebar');
1952 1953
		}

1954 1955
		// If sidebar becomes hidden, also hide the current active Viewlet if any
		if (hidden && this.sidebarPart.getActiveViewlet()) {
1956 1957 1958 1959 1960 1961 1962 1963 1964
			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();
			}
1965 1966 1967 1968 1969 1970
		}

		// 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 已提交
1971
				const viewlet = this.sidebarPart.openViewlet(viewletToOpen, true);
1972
				if (!viewlet) {
I
isidor 已提交
1973
					this.sidebarPart.openViewlet(this.sidebarPart.getDefaultViewletId(), true);
1974
				}
1975
			}
1976 1977
		}

1978 1979 1980 1981 1982 1983 1984
		// 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);
		}
1985

1986 1987
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
1988
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
1989
				this.layout();
1990 1991 1992
			} else {
				this.workbenchGrid.layout();
			}
1993
		}
1994
	}
1995

1996
	setPanelHidden(hidden: boolean, skipLayout?: boolean): void {
1997 1998 1999 2000
		this.panelHidden = hidden;

		// Adjust CSS
		if (hidden) {
2001
			addClass(this.workbench, 'nopanel');
2002
		} else {
2003
			removeClass(this.workbench, 'nopanel');
2004 2005 2006 2007
		}

		// If panel part becomes hidden, also hide the current active panel if any
		if (hidden && this.panelPart.getActivePanel()) {
2008 2009
			this.panelPart.hideActivePanel();
			this.editorGroupService.activeGroup.focus(); // Pass focus to editor group if panel part is now hidden
2010 2011 2012 2013 2014 2015
		}

		// 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) {
2016
				this.panelPart.openPanel(panelToOpen, true);
2017 2018 2019
			}
		}

2020 2021 2022 2023 2024 2025
		// Remember in settings
		if (!hidden) {
			this.storageService.store(Workbench.panelHiddenStorageKey, 'false', StorageScope.WORKSPACE);
		} else {
			this.storageService.remove(Workbench.panelHiddenStorageKey, StorageScope.WORKSPACE);
		}
2026

S
SteVen Batten 已提交
2027 2028 2029 2030 2031
		// The editor and panel cannot be hiddne at the same time
		if (hidden && this.editorHidden) {
			this.setEditorHidden(false, true);
		}

2032 2033
		// Layout
		if (!skipLayout) {
S
SteVen Batten 已提交
2034
			if (this.workbenchGrid instanceof Grid) {
S
SteVen Batten 已提交
2035
				this.layout();
2036 2037 2038
			} else {
				this.workbenchGrid.layout();
			}
2039
		}
2040 2041 2042
	}

	toggleMaximizedPanel(): void {
S
SteVen Batten 已提交
2043 2044
		if (this.workbenchGrid instanceof Grid) {
			this.workbenchGrid.maximizeViewSize(this.panelPartView);
2045 2046 2047
		} else {
			this.workbenchGrid.layout({ toggleMaximizedPanel: true, source: Parts.PANEL_PART });
		}
2048 2049 2050
	}

	isPanelMaximized(): boolean {
S
SteVen Batten 已提交
2051
		if (this.workbenchGrid instanceof Grid) {
2052
			try {
S
SteVen Batten 已提交
2053
				return this.workbenchGrid.getViewSize2(this.panelPartView).height === this.panelPart.maximumHeight;
2054 2055 2056 2057 2058 2059
			} catch (e) {
				return false;
			}
		} else {
			return this.workbenchGrid.isPanelMaximized();
		}
2060 2061 2062 2063 2064 2065 2066
	}

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

	setSideBarPosition(position: Position): void {
2067 2068
		const wasHidden = this.sideBarHidden;

2069
		if (this.sideBarHidden) {
2070
			this.setSideBarHidden(false, true /* Skip Layout */);
2071 2072 2073 2074 2075 2076 2077
		}

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

		// Adjust CSS
2078 2079 2080 2081
		removeClass(this.activitybarPart.getContainer(), oldPositionValue);
		removeClass(this.sidebarPart.getContainer(), oldPositionValue);
		addClass(this.activitybarPart.getContainer(), newPositionValue);
		addClass(this.sidebarPart.getContainer(), newPositionValue);
2082 2083 2084 2085 2086 2087

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

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

S
SteVen Batten 已提交
2090
			if (!wasHidden) {
S
SteVen Batten 已提交
2091
				this.uiState.lastSidebarDimension = this.workbenchGrid.getViewSize(this.sidebarPartView);
2092 2093
			}

S
SteVen Batten 已提交
2094 2095
			this.workbenchGrid.removeView(this.sidebarPartView);
			this.workbenchGrid.removeView(this.activitybarPartView);
S
SteVen Batten 已提交
2096 2097 2098

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

S
SteVen Batten 已提交
2101
			this.layout();
2102 2103 2104
		} else {
			this.workbenchGrid.layout();
		}
2105 2106
	}

S
SteVen Batten 已提交
2107
	setMenubarVisibility(visibility: MenuBarVisibility, skipLayout: boolean): void {
S
SteVen Batten 已提交
2108 2109
		if (this.menubarVisibility !== visibility) {
			this.menubarVisibility = visibility;
2110

2111
			// Layout
S
SteVen Batten 已提交
2112
			if (!skipLayout) {
S
SteVen Batten 已提交
2113
				if (this.workbenchGrid instanceof Grid) {
2114
					const dimensions = getClientArea(this.container);
2115 2116 2117 2118
					this.workbenchGrid.layout(dimensions.width, dimensions.height);
				} else {
					this.workbenchGrid.layout();
				}
S
SteVen Batten 已提交
2119
			}
2120 2121 2122
		}
	}

S
SteVen Batten 已提交
2123 2124 2125 2126
	getMenubarVisibility(): MenuBarVisibility {
		return this.menubarVisibility;
	}

2127 2128 2129 2130
	getPanelPosition(): Position {
		return this.panelPosition;
	}

2131
	setPanelPosition(position: Position): void {
2132 2133
		const wasHidden = this.panelHidden;

2134 2135
		if (this.panelHidden) {
			this.setPanelHidden(false, true /* Skip Layout */);
2136 2137
		} else {
			this.saveLastPanelDimension();
2138
		}
2139

2140 2141 2142 2143
		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);
2144

2145
		// Adjust CSS
2146 2147
		removeClass(this.panelPart.getContainer(), oldPositionValue);
		addClass(this.panelPart.getContainer(), newPositionValue);
2148

2149 2150 2151 2152
		// Update Styles
		this.panelPart.updateStyles();

		// Layout
S
SteVen Batten 已提交
2153 2154 2155
		if (this.workbenchGrid instanceof Grid) {
			if (!wasHidden) {
				this.saveLastPanelDimension();
2156
			}
2157

2158
			this.workbenchGrid.removeView(this.panelPartView);
S
SteVen Batten 已提交
2159
			this.layout();
2160 2161 2162 2163
		} else {
			this.workbenchGrid.layout();
		}
	}
2164 2165

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