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

'use strict';

8
import nls = require('vs/nls');
E
Erich Gamma 已提交
9 10 11
import {TPromise} from 'vs/base/common/winjs.base';
import errors = require('vs/base/common/errors');
import arrays = require('vs/base/common/arrays');
12
import Severity from 'vs/base/common/severity';
13
import {OpenGlobalSettingsAction} from 'vs/workbench/browser/actions/openSettings';
E
Erich Gamma 已提交
14 15
import {IPartService} from 'vs/workbench/services/part/common/partService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
16
import {IMessageService, CloseAction} from 'vs/platform/message/common/message';
E
Erich Gamma 已提交
17 18 19 20 21
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {IWorkspaceContextService}from 'vs/workbench/services/workspace/common/contextService';
import {IWindowService}from 'vs/workbench/services/window/electron-browser/windowService';
B
Benjamin Pasero 已提交
22
import {IWindowConfiguration} from 'vs/workbench/electron-browser/window';
B
Benjamin Pasero 已提交
23
import {IConfigurationService, IConfigurationServiceEvent, ConfigurationServiceEventTypes} from 'vs/platform/configuration/common/configuration';
E
Erich Gamma 已提交
24 25 26

import win = require('vs/workbench/electron-browser/window');

B
Benjamin Pasero 已提交
27
import {ipcRenderer as ipc, webFrame, remote} from 'electron';
E
Erich Gamma 已提交
28 29 30 31 32 33 34 35 36

export class ElectronIntegration {

	constructor(
		@IInstantiationService private instantiationService: IInstantiationService,
		@IWindowService private windowService: IWindowService,
		@IPartService private partService: IPartService,
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
		@ITelemetryService private telemetryService: ITelemetryService,
B
Benjamin Pasero 已提交
37
		@IConfigurationService private configurationService: IConfigurationService,
E
Erich Gamma 已提交
38
		@IKeybindingService private keybindingService: IKeybindingService,
39 40
		@IStorageService private storageService: IStorageService,
		@IMessageService private messageService: IMessageService
E
Erich Gamma 已提交
41 42 43 44 45 46
	) {
	}

	public integrate(shellContainer: HTMLElement): void {

		// Register the active window
B
Benjamin Pasero 已提交
47
		let activeWindow = this.instantiationService.createInstance(win.ElectronWindow, remote.getCurrentWindow(), shellContainer);
E
Erich Gamma 已提交
48 49 50
		this.windowService.registerWindow(activeWindow);

		// Support runAction event
51
		ipc.on('vscode:runAction', (event, actionId: string) => {
52
			this.keybindingService.executeCommand(actionId, { from: 'menu' }).done(undefined, err => this.messageService.show(Severity.Error, err));
E
Erich Gamma 已提交
53 54 55
		});

		// Support options change
56
		ipc.on('vscode:optionsChange', (event, options: string) => {
E
Erich Gamma 已提交
57 58 59 60 61 62 63 64 65 66
			let optionsData = JSON.parse(options);
			for (let key in optionsData) {
				if (optionsData.hasOwnProperty(key)) {
					let value = optionsData[key];
					this.contextService.updateOptions(key, value);
				}
			}
		});

		// Support resolve keybindings event
67
		ipc.on('vscode:resolveKeybindings', (event, rawActionIds: string) => {
E
Erich Gamma 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
			let actionIds: string[] = [];
			try {
				actionIds = JSON.parse(rawActionIds);
			} catch (error) {
				// should not happen
			}

			// Resolve keys using the keybinding service and send back to browser process
			this.resolveKeybindings(actionIds).done((keybindings) => {
				if (keybindings.length) {
					ipc.send('vscode:keybindingsResolved', JSON.stringify(keybindings));
				}
			}, () => errors.onUnexpectedError);
		});

83
		ipc.on('vscode:telemetry', (event, { eventName, data }) => {
E
Erich Gamma 已提交
84 85 86
			this.telemetryService.publicLog(eventName, data);
		});

87
		ipc.on('vscode:reportError', (event, error) => {
E
Erich Gamma 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100
			if (error) {
				let errorParsed = JSON.parse(error);
				errorParsed.mainProcess = true;
				errors.onUnexpectedError(errorParsed);
			}
		});

		// Emit event when vscode has loaded
		this.partService.joinCreation().then(() => {
			ipc.send('vscode:workbenchLoaded', this.windowService.getWindowId());
		});

		// Theme changes
101
		ipc.on('vscode:changeTheme', (event, theme: string) => {
E
Erich Gamma 已提交
102 103
			this.storageService.store('workbench.theme', theme, StorageScope.GLOBAL);
		});
B
Benjamin Pasero 已提交
104 105

		// Configuration changes
106
		let previousConfiguredZoomLevel: number;
B
Benjamin Pasero 已提交
107
		this.configurationService.addListener(ConfigurationServiceEventTypes.UPDATED, (e: IConfigurationServiceEvent) => {
B
Benjamin Pasero 已提交
108 109 110 111 112
			let windowConfig: IWindowConfiguration = e.config;

			let newZoomLevel = 0;
			if (windowConfig.window && typeof windowConfig.window.zoomLevel === 'number') {
				newZoomLevel = windowConfig.window.zoomLevel;
113 114 115 116 117 118 119

				// Leave early if the configured zoom level did not change (https://github.com/Microsoft/vscode/issues/1536)
				if (previousConfiguredZoomLevel === newZoomLevel) {
					return;
				}

				previousConfiguredZoomLevel = newZoomLevel;
B
Benjamin Pasero 已提交
120 121 122 123 124
			}

			if (webFrame.getZoomLevel() !== newZoomLevel) {
				webFrame.setZoomLevel(newZoomLevel);
			}
B
Benjamin Pasero 已提交
125
		});
126 127 128 129 130

		// Auto Save Info (TODO@Ben remove me in a couple of versions)
		ipc.on('vscode:showAutoSaveInfo', () => {
			this.messageService.show(
				Severity.Info, {
131
					message: nls.localize('autoSaveInfo', "The enabled **File | Auto Save** menu option has become a setting **files.autoSave** with the value **afterDelay**."),
132 133 134 135
					actions: [
						CloseAction,
						this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
					]
136
				});
137
		});
138 139 140 141

		ipc.on('vscode:showAutoSaveError', () => {
			this.messageService.show(
				Severity.Warning, {
142
					message: nls.localize('autoSaveError', "Unable to write to settings. Please add **files.autoSave: \"afterDelay\"** to settings.json."),
143 144 145 146 147 148 149
					actions: [
						CloseAction,
						this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
					]
				});
		});

E
Erich Gamma 已提交
150 151 152 153 154 155
	}

	private resolveKeybindings(actionIds: string[]): TPromise<{ id: string; binding: number; }[]> {
		return this.partService.joinCreation().then(() => {
			return arrays.coalesce(actionIds.map((id) => {
				let bindings = this.keybindingService.lookupKeybindings(id);
156 157 158 159 160 161 162 163 164 165 166

				// return the first binding that can be represented by electron
				for (let i = 0; i < bindings.length; i++) {
					let binding = bindings[i];
					let electronAccelerator = this.keybindingService.getElectronAcceleratorFor(binding);
					if (electronAccelerator) {
						return {
							id: id,
							binding: binding.value
						};
					}
E
Erich Gamma 已提交
167 168 169 170 171 172 173
				}

				return null;
			}));
		});
	}
}