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

'use strict';

import 'vs/css!./media/shell';

10
import * as nls from 'vs/nls';
J
Johannes Rieken 已提交
11
import { TPromise } from 'vs/base/common/winjs.base';
J
Joao Moreno 已提交
12
import * as platform from 'vs/base/common/platform';
J
Johannes Rieken 已提交
13
import { Dimension, Builder, $ } from 'vs/base/browser/builder';
E
Erich Gamma 已提交
14
import dom = require('vs/base/browser/dom');
15
import aria = require('vs/base/browser/ui/aria/aria');
J
Johannes Rieken 已提交
16
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
17
import errors = require('vs/base/common/errors');
J
Johannes Rieken 已提交
18
import { toErrorMessage } from 'vs/base/common/errorMessage';
19
import product from 'vs/platform/node/product';
20
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
21
import pkg from 'vs/platform/node/package';
J
Johannes Rieken 已提交
22
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
23
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
24
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
25 26
import { NullTelemetryService, configurationTelemetry, lifecycleTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { loadExperiments } from 'vs/platform/telemetry/common/experiments';
J
Johannes Rieken 已提交
27 28 29
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { IdleMonitor, UserStatus } from 'vs/platform/telemetry/browser/idleMonitor';
J
Joao Moreno 已提交
30
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
31
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
C
Christof Marti 已提交
32 33
import { resolveWorkbenchCommonProperties, getOrCreateMachineId } from 'vs/platform/telemetry/node/workbenchCommonProperties';
import { machineIdIpcChannel } from 'vs/platform/telemetry/node/commonProperties';
J
Johannes Rieken 已提交
34
import { WorkspaceStats } from 'vs/workbench/services/telemetry/common/workspaceStats';
35
import { IWindowsService, IWindowService, IWindowConfiguration } from 'vs/platform/windows/common/windows';
J
Joao Moreno 已提交
36
import { WindowService } from 'vs/platform/windows/electron-browser/windowService';
J
Johannes Rieken 已提交
37
import { MessageService } from 'vs/workbench/services/message/electron-browser/messageService';
J
Joao Moreno 已提交
38
import { IRequestService } from 'vs/platform/request/node/request';
39
import { RequestService } from 'vs/platform/request/electron-browser/requestService';
J
Johannes Rieken 已提交
40 41 42 43 44 45 46 47 48 49 50 51
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { LifecycleService } from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService';
import { MarkerService } from 'vs/platform/markers/common/markerService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServiceImpl';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
import { IntegrityServiceImpl } from 'vs/platform/integrity/node/integrityServiceImpl';
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
import { EditorWorkerServiceImpl } from 'vs/editor/common/services/editorWorkerServiceImpl';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
52
import { ExtensionService } from "vs/workbench/services/extensions/electron-browser/extensionService";
J
Johannes Rieken 已提交
53
import { IStorageService } from 'vs/platform/storage/common/storage';
J
Joao Moreno 已提交
54
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Johannes Rieken 已提交
55 56 57
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
58
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
J
Johannes Rieken 已提交
59 60
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
B
Benjamin Pasero 已提交
61
import { IMessageService, IChoiceService, Severity } from 'vs/platform/message/common/message';
J
Johannes Rieken 已提交
62 63 64 65
import { ChoiceChannel } from 'vs/platform/message/common/messageIpc';
import { ISearchService } from 'vs/platform/search/common/search';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
66
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
67
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
68
import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/workbenchModeService';
J
Johannes Rieken 已提交
69 70
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
71 72
import { ICrashReporterService, NullCrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
import { CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
73
import { NodeCachedDataManager } from 'vs/workbench/electron-browser/nodeCachedDataManager';
J
Johannes Rieken 已提交
74 75 76
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
77 78
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
B
Benjamin Pasero 已提交
79
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
C
Christof Marti 已提交
80
import { remote, ipcRenderer as ipc } from 'electron';
81
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
82 83
import { restoreFontInfo, readFontInfo, saveFontInfo } from 'vs/editor/browser/config/configuration';
import * as browser from 'vs/base/browser/browser';
84
import 'vs/platform/opener/browser/opener.contribution';
85 86
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
87 88
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { TextResourceConfigurationService } from 'vs/editor/common/services/resourceConfigurationImpl';
89
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
90
import { foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
91 92
import { TextMateService } from 'vs/workbench/services/textMate/electron-browser/TMSyntax';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
93
import { IBroadcastService, BroadcastService } from "vs/platform/broadcast/electron-browser/broadcastService";
94

95 96 97 98 99 100
/**
 * Services that we require for the Shell
 */
export interface ICoreServices {
	contextService: IWorkspaceContextService;
	configurationService: IConfigurationService;
101
	environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
102
	timerService: ITimerService;
103
	storageService: IStorageService;
104 105
}

106 107
const currentWindow = remote.getCurrentWindow();

E
Erich Gamma 已提交
108
/**
B
Benjamin Pasero 已提交
109
 * The workbench shell contains the workbench with a rich header containing navigation and the activity bar.
E
Erich Gamma 已提交
110 111 112
 * With the Shell being the top level element in the page, it is also responsible for driving the layouting.
 */
export class WorkbenchShell {
B
Benjamin Pasero 已提交
113
	private storageService: IStorageService;
114
	private messageService: MessageService;
J
Johannes Rieken 已提交
115
	private environmentService: IEnvironmentService;
B
Benjamin Pasero 已提交
116
	private contextViewService: ContextViewService;
117 118
	private configurationService: IConfigurationService;
	private contextService: IWorkspaceContextService;
119
	private telemetryService: ITelemetryService;
120
	private extensionService: ExtensionService;
121
	private broadcastService: IBroadcastService;
B
Benjamin Pasero 已提交
122
	private timerService: ITimerService;
B
Benjamin Pasero 已提交
123
	private themeService: WorkbenchThemeService;
124
	private lifecycleService: LifecycleService;
125 126
	private mainProcessServices: ServiceCollection;

E
Erich Gamma 已提交
127
	private container: HTMLElement;
128
	private toUnbind: IDisposable[];
E
Erich Gamma 已提交
129 130 131 132 133
	private previousErrorValue: string;
	private previousErrorTime: number;
	private content: HTMLElement;
	private contentsContainer: Builder;

134
	private configuration: IWindowConfiguration;
E
Erich Gamma 已提交
135 136
	private workbench: Workbench;

B
Benjamin Pasero 已提交
137
	constructor(container: HTMLElement, coreServices: ICoreServices, mainProcessServices: ServiceCollection, configuration: IWindowConfiguration) {
E
Erich Gamma 已提交
138 139
		this.container = container;

140
		this.configuration = configuration;
141

B
Benjamin Pasero 已提交
142 143 144 145 146
		this.contextService = coreServices.contextService;
		this.configurationService = coreServices.configurationService;
		this.environmentService = coreServices.environmentService;
		this.timerService = coreServices.timerService;
		this.storageService = coreServices.storageService;
E
Erich Gamma 已提交
147

148 149
		this.mainProcessServices = mainProcessServices;

E
Erich Gamma 已提交
150 151 152 153 154 155
		this.toUnbind = [];
		this.previousErrorTime = 0;
	}

	private createContents(parent: Builder): Builder {

156
		// ARIA
B
Benjamin Pasero 已提交
157
		aria.setARIAContainer(document.body);
158

E
Erich Gamma 已提交
159
		// Workbench Container
160
		const workbenchContainer = $(parent).div();
E
Erich Gamma 已提交
161 162

		// Instantiation service with services
163
		const [instantiationService, serviceCollection] = this.initServiceCollection(parent.getHTMLElement());
E
Erich Gamma 已提交
164 165

		// Workbench
B
Benjamin Pasero 已提交
166
		this.workbench = instantiationService.createInstance(Workbench, parent.getHTMLElement(), workbenchContainer.getHTMLElement(), this.configuration, serviceCollection);
E
Erich Gamma 已提交
167
		this.workbench.startup({
168
			onWorkbenchStarted: (info: IWorkbenchStartedInfo) => {
169 170

				// run workbench started logic
B
Benjamin Pasero 已提交
171
				this.onWorkbenchStarted(info);
172 173 174

				// start cached data manager
				instantiationService.createInstance(NodeCachedDataManager);
175 176 177 178

				// Set lifecycle phase to `Runnning` so that other contributions
				// can now do something
				this.lifecycleService.phase = LifecyclePhase.Running;
E
Erich Gamma 已提交
179 180 181
			}
		});

182
		// Window
183
		this.workbench.getInstantiationService().createInstance(ElectronWindow, this.container);
E
Erich Gamma 已提交
184 185

		// Handle case where workbench is not starting up properly
186
		const timeoutHandle = setTimeout(() => {
E
Erich Gamma 已提交
187 188 189 190 191 192 193 194 195 196
			console.warn('Workbench did not finish loading in 10 seconds, that might be a problem that should be reported.');
		}, 10000);

		this.workbench.joinCreation().then(() => {
			clearTimeout(timeoutHandle);
		});

		return workbenchContainer;
	}

B
Benjamin Pasero 已提交
197
	private onWorkbenchStarted(info: IWorkbenchStartedInfo): void {
198 199

		// Telemetry: workspace info
B
Benjamin Pasero 已提交
200
		const { filesToOpen, filesToCreate, filesToDiff } = this.configuration;
201 202 203
		this.telemetryService.publicLog('workspaceLoad', {
			userAgent: navigator.userAgent,
			windowSize: { innerHeight: window.innerHeight, innerWidth: window.innerWidth, outerHeight: window.outerHeight, outerWidth: window.outerWidth },
B
Benjamin Pasero 已提交
204
			emptyWorkbench: !this.contextService.hasWorkspace(),
B
Benjamin Pasero 已提交
205 206 207
			'workbench.filesToOpen': filesToOpen && filesToOpen.length || void 0,
			'workbench.filesToCreate': filesToCreate && filesToCreate.length || void 0,
			'workbench.filesToDiff': filesToDiff && filesToDiff.length || void 0,
208
			customKeybindingsCount: info.customKeybindingsCount,
B
Benjamin Pasero 已提交
209
			theme: this.themeService.getColorTheme().id,
210
			language: platform.language,
211
			experiments: loadExperiments(),
212 213
			pinnedViewlets: info.pinnedViewlets,
			restoredViewlet: info.restoredViewlet,
214 215
			restoredEditors: info.restoredEditors.length,
			startupKind: this.lifecycleService.startupKind
216 217
		});

B
Benjamin Pasero 已提交
218
		// Telemetry: startup metrics
219
		this.timerService.workbenchStarted = Date.now();
B
Benjamin Pasero 已提交
220 221
		this.timerService.restoreEditorsDuration = info.restoreEditorsDuration;
		this.timerService.restoreViewletDuration = info.restoreViewletDuration;
222
		this.extensionService.onReady().done(() => {
B
Benjamin Pasero 已提交
223
			this.telemetryService.publicLog('startupTime', this.timerService.startupMetrics);
224
		});
B
Benjamin Pasero 已提交
225

226
		// Telemetry: workspace tags
227
		const workspaceStats: WorkspaceStats = <WorkspaceStats>this.workbench.getInstantiationService().createInstance(WorkspaceStats);
B
Benjamin Pasero 已提交
228
		workspaceStats.reportWorkspaceTags(this.configuration);
K
kieferrm 已提交
229
		workspaceStats.reportCloudStats();
J
Joao Moreno 已提交
230 231 232 233

		if ((platform.isLinux || platform.isMacintosh) && process.getuid() === 0) {
			this.messageService.show(Severity.Warning, nls.localize('runningAsRoot', "It is recommended not to run Code as 'root'."));
		}
B
Benjamin Pasero 已提交
234 235
	}

236
	private initServiceCollection(container: HTMLElement): [IInstantiationService, ServiceCollection] {
J
Johannes Rieken 已提交
237
		const disposables: IDisposable[] = [];
J
Joao Moreno 已提交
238

239 240 241
		const serviceCollection = new ServiceCollection();
		serviceCollection.set(IWorkspaceContextService, this.contextService);
		serviceCollection.set(IConfigurationService, this.configurationService);
242
		serviceCollection.set(IEnvironmentService, this.environmentService);
B
Benjamin Pasero 已提交
243
		serviceCollection.set(ITimerService, this.timerService);
244
		serviceCollection.set(IStorageService, this.storageService);
245 246 247
		this.mainProcessServices.forEach((serviceIdentifier, serviceInstance) => {
			serviceCollection.set(serviceIdentifier, serviceInstance);
		});
248

249
		const instantiationService: IInstantiationService = new InstantiationService(serviceCollection, true);
250

251 252
		this.broadcastService = new BroadcastService(currentWindow.id);
		serviceCollection.set(IBroadcastService, this.broadcastService);
253

254
		serviceCollection.set(IWindowService, new SyncDescriptor(WindowService, currentWindow.id));
J
Joao Moreno 已提交
255

256
		const sharedProcess = (<IWindowsService>serviceCollection.get(IWindowsService)).whenSharedProcessReady()
257
			.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${currentWindow.id}`));
258 259 260

		sharedProcess
			.done(client => client.registerChannel('choice', instantiationService.createInstance(ChoiceChannel)));
261

262 263 264 265
		// Warm up font cache information before building up too many dom elements
		restoreFontInfo(this.storageService);
		readFontInfo(BareFontInfo.createFromRawSettings(this.configurationService.getConfiguration('editor'), browser.getZoomLevel()));

266
		// Telemetry
C
Christof Marti 已提交
267
		this.sendMachineIdToMain(this.storageService);
268
		if (this.environmentService.isBuilt && !this.environmentService.isExtensionDevelopment && !!product.enableTelemetry) {
269
			const channel = getDelayedChannel<ITelemetryAppenderChannel>(sharedProcess.then(c => c.getChannel('telemetryAppender')));
270 271
			const commit = product.commit;
			const version = pkg.version;
272

273
			const config: ITelemetryServiceConfig = {
274
				appender: new TelemetryAppenderClient(channel),
275
				commonProperties: resolveWorkbenchCommonProperties(this.storageService, commit, version),
276
				piiPaths: [this.environmentService.appRoot, this.environmentService.extensionsPath]
277
			};
278

J
Joao Moreno 已提交
279
			const telemetryService = instantiationService.createInstance(TelemetryService, config);
280 281
			this.telemetryService = telemetryService;

J
Joao Moreno 已提交
282
			const errorTelemetry = new ErrorTelemetry(telemetryService);
283
			const idleMonitor = new IdleMonitor(2 * 60 * 1000); // 2 minutes
284

285 286 287 288
			const listener = idleMonitor.onStatusChange(status =>
				this.telemetryService.publicLog(status === UserStatus.Active
					? TelemetryService.IDLE_STOP_EVENT_NAME
					: TelemetryService.IDLE_START_EVENT_NAME
289
				));
290

J
Johannes Rieken 已提交
291
			disposables.push(telemetryService, errorTelemetry, listener, idleMonitor);
292
		} else {
293
			this.telemetryService = NullTelemetryService;
294
		}
E
Erich Gamma 已提交
295

296
		serviceCollection.set(ITelemetryService, this.telemetryService);
J
Johannes Rieken 已提交
297
		disposables.push(configurationTelemetry(this.telemetryService, this.configurationService));
E
Erich Gamma 已提交
298

299 300 301 302 303 304
		let crashReporterService = NullCrashReporterService;
		if (product.crashReporter && product.hockeyApp) {
			crashReporterService = instantiationService.createInstance(CrashReporterService);
		}
		serviceCollection.set(ICrashReporterService, crashReporterService);

305
		this.messageService = instantiationService.createInstance(MessageService, container);
306
		serviceCollection.set(IMessageService, this.messageService);
J
Joao Moreno 已提交
307
		serviceCollection.set(IChoiceService, this.messageService);
E
Erich Gamma 已提交
308

309
		const lifecycleService = instantiationService.createInstance(LifecycleService);
J
Johannes Rieken 已提交
310
		this.toUnbind.push(lifecycleService.onShutdown(reason => dispose(disposables)));
311
		this.toUnbind.push(lifecycleService.onShutdown(reason => saveFontInfo(this.storageService)));
312
		serviceCollection.set(ILifecycleService, lifecycleService);
J
Johannes Rieken 已提交
313
		disposables.push(lifecycleTelemetry(this.telemetryService, lifecycleService));
314
		this.lifecycleService = lifecycleService;
315

S
Sandeep Somavarapu 已提交
316
		const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
317
		serviceCollection.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementChannelClient, extensionManagementChannel));
S
Sandeep Somavarapu 已提交
318

319 320
		const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
		serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
J
Johannes Rieken 已提交
321
		disposables.push(extensionEnablementService);
322

323
		this.extensionService = instantiationService.createInstance(ExtensionService);
324
		serviceCollection.set(IExtensionService, this.extensionService);
325 326

		this.timerService.beforeExtensionLoad = Date.now();
327
		this.extensionService.onReady().done(() => {
328
			this.timerService.afterExtensionLoad = Date.now();
329
		});
E
Erich Gamma 已提交
330

B
Benjamin Pasero 已提交
331 332 333
		this.themeService = instantiationService.createInstance(WorkbenchThemeService, document.body);
		serviceCollection.set(IWorkbenchThemeService, this.themeService);

334
		serviceCollection.set(ICommandService, new SyncDescriptor(CommandService));
335

336 337
		this.contextViewService = instantiationService.createInstance(ContextViewService, this.container);
		serviceCollection.set(IContextViewService, this.contextViewService);
E
Erich Gamma 已提交
338

339
		serviceCollection.set(IRequestService, new SyncDescriptor(RequestService));
E
Erich Gamma 已提交
340

341
		serviceCollection.set(IMarkerService, new SyncDescriptor(MarkerService));
E
Erich Gamma 已提交
342

343
		serviceCollection.set(IModeService, new SyncDescriptor(WorkbenchModeServiceImpl));
344

345
		serviceCollection.set(IModelService, new SyncDescriptor(ModelServiceImpl));
346

347 348
		serviceCollection.set(ITextResourceConfigurationService, new SyncDescriptor(TextResourceConfigurationService));

349
		serviceCollection.set(IEditorWorkerService, new SyncDescriptor(EditorWorkerServiceImpl));
350

351
		serviceCollection.set(IUntitledEditorService, new SyncDescriptor(UntitledEditorService));
352

353
		serviceCollection.set(ITextMateService, new SyncDescriptor(TextMateService));
A
Alex Dima 已提交
354

355
		serviceCollection.set(ISearchService, new SyncDescriptor(SearchService));
356

357
		serviceCollection.set(ICodeEditorService, new SyncDescriptor(CodeEditorServiceImpl));
358

359
		serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
A
Alex Dima 已提交
360

361
		return [instantiationService, serviceCollection];
E
Erich Gamma 已提交
362 363
	}

C
Christof Marti 已提交
364 365 366 367 368 369
	private sendMachineIdToMain(storageService: IStorageService) {
		getOrCreateMachineId(storageService).then(machineId => {
			ipc.send(machineIdIpcChannel, machineId);
		}).then(null, errors.onUnexpectedError);
	}

E
Erich Gamma 已提交
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
	public open(): void {

		// Listen on unexpected errors
		errors.setUnexpectedErrorHandler((error: any) => {
			this.onUnexpectedError(error);
		});

		// Shell Class for CSS Scoping
		$(this.container).addClass('monaco-shell');

		// Controls
		this.content = $('.monaco-shell-content').appendTo(this.container).getHTMLElement();

		// Create Contents
		this.contentsContainer = this.createContents($(this.content));

		// Layout
		this.layout();

		// Listeners
		this.registerListeners();
	}

	private registerListeners(): void {

		// Resize
		$(window).on(dom.EventType.RESIZE, () => this.layout(), this.toUnbind);
	}

	public onUnexpectedError(error: any): void {
400
		const errorMsg = toErrorMessage(error, true);
E
Erich Gamma 已提交
401 402 403 404
		if (!errorMsg) {
			return;
		}

405
		const now = Date.now();
E
Erich Gamma 已提交
406 407 408 409 410 411 412 413 414 415 416
		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 to console
		console.error(errorMsg);

		// Show to user if friendly message provided
417
		if (error && error.friendlyMessage && this.messageService) {
B
Benjamin Pasero 已提交
418
			this.messageService.show(Severity.Error, error.friendlyMessage);
E
Erich Gamma 已提交
419 420 421
		}
	}

B
Benjamin Pasero 已提交
422
	private layout(): void {
423
		const clArea = $(this.container).getClientArea();
E
Erich Gamma 已提交
424

425
		const contentsSize = new Dimension(clArea.width, clArea.height);
E
Erich Gamma 已提交
426 427
		this.contentsContainer.size(contentsSize.width, contentsSize.height);

B
Benjamin Pasero 已提交
428
		this.contextViewService.layout();
E
Erich Gamma 已提交
429 430 431 432 433 434 435
		this.workbench.layout();
	}

	public joinCreation(): TPromise<boolean> {
		return this.workbench.joinCreation();
	}

B
Benjamin Pasero 已提交
436
	public dispose(): void {
E
Erich Gamma 已提交
437 438 439

		// Workbench
		if (this.workbench) {
B
Benjamin Pasero 已提交
440
			this.workbench.dispose();
E
Erich Gamma 已提交
441 442
		}

B
Benjamin Pasero 已提交
443
		this.contextViewService.dispose();
E
Erich Gamma 已提交
444 445

		// Listeners
J
Joao Moreno 已提交
446
		this.toUnbind = dispose(this.toUnbind);
E
Erich Gamma 已提交
447 448 449 450

		// Container
		$(this.container).empty();
	}
451
}
452 453

registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
B
Benjamin Pasero 已提交
454 455

	// Foreground
B
Benjamin Pasero 已提交
456
	const windowForeground = theme.getColor(foreground);
457 458 459
	if (windowForeground) {
		collector.addRule(`.monaco-shell { color: ${windowForeground}; }`);
	}
B
Benjamin Pasero 已提交
460

461 462 463 464 465 466
	// Selection
	const windowSelectionBackground = theme.getColor(selectionBackground);
	if (windowSelectionBackground) {
		collector.addRule(`.monaco-shell ::selection { background-color: ${windowSelectionBackground}; }`);
	}

467 468 469 470 471 472 473
	// Input placeholder
	const placeholderForeground = theme.getColor(inputPlaceholderForeground);
	if (placeholderForeground) {
		collector.addRule(`.monaco-shell input::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
		collector.addRule(`.monaco-shell textarea::-webkit-input-placeholder { color: ${placeholderForeground}; }`);
	}

474 475 476 477 478 479 480 481 482 483 484
	// List highlight
	const listHighlightForegroundColor = theme.getColor(listHighlightForeground);
	if (listHighlightForegroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
			.monaco-shell .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
				color: ${listHighlightForegroundColor};
			}
		`);
	}

B
Benjamin Pasero 已提交
485
	// We need to set the workbench background color so that on Windows we get subpixel-antialiasing.
486 487 488 489 490 491 492 493 494 495 496 497 498
	let workbenchBackground: string;
	switch (theme.type) {
		case 'dark':
			workbenchBackground = '#252526';
			break;
		case 'light':
			workbenchBackground = '#F3F3F3';
			break;
		default:
			workbenchBackground = '#000000';
	}
	collector.addRule(`.monaco-workbench { background-color: ${workbenchBackground}; }`);

B
Benjamin Pasero 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 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
	// Scrollbars
	const scrollbarShadowColor = theme.getColor(scrollbarShadow);
	if (scrollbarShadowColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .shadow.top {
				box-shadow: ${scrollbarShadowColor} 0 6px 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.left {
				box-shadow: ${scrollbarShadowColor} 6px 0 6px -6px inset;
			}

			.monaco-shell .monaco-scrollable-element > .shadow.top.left {
				box-shadow: ${scrollbarShadowColor} 6px 6px 6px -6px inset;
			}
		`);
	}

	const scrollbarSliderBackgroundColor = theme.getColor(scrollbarSliderBackground);
	if (scrollbarSliderBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider {
				background: ${scrollbarSliderBackgroundColor};
			}
		`);
	}

	const scrollbarSliderHoverBackgroundColor = theme.getColor(scrollbarSliderHoverBackground);
	if (scrollbarSliderHoverBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider:hover {
				background: ${scrollbarSliderHoverBackgroundColor};
			}
		`);
	}

	const scrollbarSliderActiveBackgroundColor = theme.getColor(scrollbarSliderActiveBackground);
	if (scrollbarSliderActiveBackgroundColor) {
		collector.addRule(`
			.monaco-shell .monaco-scrollable-element > .scrollbar > .slider.active {
				background: ${scrollbarSliderActiveBackgroundColor};
			}
		`);
	}

	// Focus outline
545
	const focusOutline = theme.getColor(focusBorder);
B
Benjamin Pasero 已提交
546 547 548 549 550 551 552 553
	if (focusOutline) {
		collector.addRule(`
			.monaco-shell [tabindex="0"]:focus,
			.monaco-shell .synthetic-focus,
			.monaco-shell select:focus,
			.monaco-shell .monaco-tree.focused.no-focused-item:focus:before,
			.monaco-shell input[type="button"]:focus,
			.monaco-shell input[type="text"]:focus,
B
Benjamin Pasero 已提交
554
			.monaco-shell button:focus,
B
Benjamin Pasero 已提交
555 556 557 558 559 560 561
			.monaco-shell textarea:focus,
			.monaco-shell input[type="search"]:focus,
			.monaco-shell input[type="checkbox"]:focus {
				outline-color: ${focusOutline};
			}
		`);
	}
562
});