codeEditorWidget.ts 71.1 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.
 *--------------------------------------------------------------------------------------------*/

import 'vs/css!./media/editor';
import 'vs/css!./media/tokens';
A
Alex Dima 已提交
8 9
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
A
Alex Dima 已提交
10
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
11
import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
A
Alex Dima 已提交
12
import { Color } from 'vs/base/common/color';
J
Johannes Rieken 已提交
13
import { onUnexpectedError } from 'vs/base/common/errors';
A
Alex Dima 已提交
14 15
import { Emitter, Event } from 'vs/base/common/event';
import { hash } from 'vs/base/common/hash';
A
Alex Dima 已提交
16
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
A
Alex Dima 已提交
17
import { Schemas } from 'vs/base/common/network';
J
Johannes Rieken 已提交
18
import { Configuration } from 'vs/editor/browser/config/configuration';
A
Alex Dima 已提交
19 20 21 22 23 24 25
import { CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { EditorExtensionsRegistry, IEditorContributionCtor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICommandDelegate } from 'vs/editor/browser/view/viewController';
import { IContentWidgetData, IOverlayWidgetData, View } from 'vs/editor/browser/view/viewImpl';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
A
renames  
Alex Dima 已提交
26
import { IConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, InternalEditorOptions, IComputedEditorOptions, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions';
A
Alex Dima 已提交
27
import { Cursor, CursorStateChangedEvent } from 'vs/editor/common/controller/cursor';
A
Alex Dima 已提交
28
import { CursorColumns, ICursors } from 'vs/editor/common/controller/cursorCommon';
A
Alex Dima 已提交
29
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
A
Alex Dima 已提交
30 31 32 33 34
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { InternalEditorAction } from 'vs/editor/common/editorAction';
import * as editorCommon from 'vs/editor/common/editorCommon';
A
Alex Dima 已提交
35
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
36
import { EndOfLinePreference, IIdentifiedSingleEditOperation, IModelDecoration, IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel, ICursorStateComputer } from 'vs/editor/common/model';
A
Alex Dima 已提交
37
import { ClassName } from 'vs/editor/common/model/intervalTree';
A
Alex Dima 已提交
38
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
A
Alex Dima 已提交
39
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
A
Alex Dima 已提交
40
import * as modes from 'vs/editor/common/modes';
41
import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from 'vs/editor/common/view/editorColorRegistry';
42
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
A
Alex Dima 已提交
43 44 45
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
A
Alex Dima 已提交
46
import { ICommandService } from 'vs/platform/commands/common/commands';
A
Alex Dima 已提交
47 48 49 50
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { INotificationService } from 'vs/platform/notification/common/notification';
A
Alex Dima 已提交
51
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
52
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
53
import { withNullAsUndefined } from 'vs/base/common/types';
E
Erich Gamma 已提交
54

A
Alex Dima 已提交
55 56
let EDITOR_ID = 0;

57 58
const SHOW_UNUSED_ENABLED_CLASS = 'showUnused';

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
export interface ICodeEditorWidgetOptions {
	/**
	 * Is this a simple widget (not a real code editor) ?
	 * Defaults to false.
	 */
	isSimpleWidget?: boolean;

	/**
	 * Contributions to instantiate.
	 * Defaults to EditorExtensionsRegistry.getEditorContributions().
	 */
	contributions?: IEditorContributionCtor[];

	/**
	 * Telemetry data associated with this CodeEditorWidget.
	 * Defaults to null.
	 */
	telemetryData?: object;
}

A
Alex Dima 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
class ModelData {
	public readonly model: ITextModel;
	public readonly viewModel: ViewModel;
	public readonly cursor: Cursor;
	public readonly view: View;
	public readonly hasRealView: boolean;
	public readonly listenersToRemove: IDisposable[];

	constructor(model: ITextModel, viewModel: ViewModel, cursor: Cursor, view: View, hasRealView: boolean, listenersToRemove: IDisposable[]) {
		this.model = model;
		this.viewModel = viewModel;
		this.cursor = cursor;
		this.view = view;
		this.hasRealView = hasRealView;
		this.listenersToRemove = listenersToRemove;
	}

	public dispose(): void {
		dispose(this.listenersToRemove);
		this.model.onBeforeDetached();
		if (this.hasRealView) {
			this.view.dispose();
		}
		this.cursor.dispose();
		this.viewModel.dispose();
	}
}

A
Alex Dima 已提交
107
export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeEditor {
A
Alex Dima 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

	//#region Eventing
	private readonly _onDidDispose: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidDispose: Event<void> = this._onDidDispose.event;

	private readonly _onDidChangeModelContent: Emitter<IModelContentChangedEvent> = this._register(new Emitter<IModelContentChangedEvent>());
	public readonly onDidChangeModelContent: Event<IModelContentChangedEvent> = this._onDidChangeModelContent.event;

	private readonly _onDidChangeModelLanguage: Emitter<IModelLanguageChangedEvent> = this._register(new Emitter<IModelLanguageChangedEvent>());
	public readonly onDidChangeModelLanguage: Event<IModelLanguageChangedEvent> = this._onDidChangeModelLanguage.event;

	private readonly _onDidChangeModelLanguageConfiguration: Emitter<IModelLanguageConfigurationChangedEvent> = this._register(new Emitter<IModelLanguageConfigurationChangedEvent>());
	public readonly onDidChangeModelLanguageConfiguration: Event<IModelLanguageConfigurationChangedEvent> = this._onDidChangeModelLanguageConfiguration.event;

	private readonly _onDidChangeModelOptions: Emitter<IModelOptionsChangedEvent> = this._register(new Emitter<IModelOptionsChangedEvent>());
	public readonly onDidChangeModelOptions: Event<IModelOptionsChangedEvent> = this._onDidChangeModelOptions.event;

	private readonly _onDidChangeModelDecorations: Emitter<IModelDecorationsChangedEvent> = this._register(new Emitter<IModelDecorationsChangedEvent>());
	public readonly onDidChangeModelDecorations: Event<IModelDecorationsChangedEvent> = this._onDidChangeModelDecorations.event;

128 129
	private readonly _onDidChangeConfiguration: Emitter<IConfigurationChangedEvent> = this._register(new Emitter<IConfigurationChangedEvent>());
	public readonly onDidChangeConfiguration: Event<IConfigurationChangedEvent> = this._onDidChangeConfiguration.event;
A
Alex Dima 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142

	protected readonly _onDidChangeModel: Emitter<editorCommon.IModelChangedEvent> = this._register(new Emitter<editorCommon.IModelChangedEvent>());
	public readonly onDidChangeModel: Event<editorCommon.IModelChangedEvent> = this._onDidChangeModel.event;

	private readonly _onDidChangeCursorPosition: Emitter<ICursorPositionChangedEvent> = this._register(new Emitter<ICursorPositionChangedEvent>());
	public readonly onDidChangeCursorPosition: Event<ICursorPositionChangedEvent> = this._onDidChangeCursorPosition.event;

	private readonly _onDidChangeCursorSelection: Emitter<ICursorSelectionChangedEvent> = this._register(new Emitter<ICursorSelectionChangedEvent>());
	public readonly onDidChangeCursorSelection: Event<ICursorSelectionChangedEvent> = this._onDidChangeCursorSelection.event;

	private readonly _onDidAttemptReadOnlyEdit: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidAttemptReadOnlyEdit: Event<void> = this._onDidAttemptReadOnlyEdit.event;

143 144
	private readonly _onDidLayoutChange: Emitter<EditorLayoutInfo> = this._register(new Emitter<EditorLayoutInfo>());
	public readonly onDidLayoutChange: Event<EditorLayoutInfo> = this._onDidLayoutChange.event;
A
Alex Dima 已提交
145

146
	private readonly _editorTextFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter());
A
Alex Dima 已提交
147 148 149
	public readonly onDidFocusEditorText: Event<void> = this._editorTextFocus.onDidChangeToTrue;
	public readonly onDidBlurEditorText: Event<void> = this._editorTextFocus.onDidChangeToFalse;

150
	private readonly _editorWidgetFocus: BooleanEventEmitter = this._register(new BooleanEventEmitter());
A
Alex Dima 已提交
151 152
	public readonly onDidFocusEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToTrue;
	public readonly onDidBlurEditorWidget: Event<void> = this._editorWidgetFocus.onDidChangeToFalse;
A
Alex Dima 已提交
153 154 155 156 157 158 159

	private readonly _onWillType: Emitter<string> = this._register(new Emitter<string>());
	public readonly onWillType = this._onWillType.event;

	private readonly _onDidType: Emitter<string> = this._register(new Emitter<string>());
	public readonly onDidType = this._onDidType.event;

J
Johannes Rieken 已提交
160 161 162 163 164 165
	private readonly _onCompositionStart: Emitter<void> = this._register(new Emitter<void>());
	public readonly onCompositionStart = this._onCompositionStart.event;

	private readonly _onCompositionEnd: Emitter<void> = this._register(new Emitter<void>());
	public readonly onCompositionEnd = this._onCompositionEnd.event;

A
Alex Dima 已提交
166 167
	private readonly _onDidPaste: Emitter<Range> = this._register(new Emitter<Range>());
	public readonly onDidPaste = this._onDidPaste.event;
E
Erich Gamma 已提交
168

A
Alex Dima 已提交
169 170 171 172 173 174 175 176 177
	private readonly _onMouseUp: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseUp: Event<editorBrowser.IEditorMouseEvent> = this._onMouseUp.event;

	private readonly _onMouseDown: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseDown: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDown.event;

	private readonly _onMouseDrag: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseDrag: Event<editorBrowser.IEditorMouseEvent> = this._onMouseDrag.event;

A
Alex Dima 已提交
178 179
	private readonly _onMouseDrop: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseDrop: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseDrop.event;
A
Alex Dima 已提交
180 181 182 183 184 185 186

	private readonly _onContextMenu: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onContextMenu: Event<editorBrowser.IEditorMouseEvent> = this._onContextMenu.event;

	private readonly _onMouseMove: Emitter<editorBrowser.IEditorMouseEvent> = this._register(new Emitter<editorBrowser.IEditorMouseEvent>());
	public readonly onMouseMove: Event<editorBrowser.IEditorMouseEvent> = this._onMouseMove.event;

A
Alex Dima 已提交
187 188
	private readonly _onMouseLeave: Emitter<editorBrowser.IPartialEditorMouseEvent> = this._register(new Emitter<editorBrowser.IPartialEditorMouseEvent>());
	public readonly onMouseLeave: Event<editorBrowser.IPartialEditorMouseEvent> = this._onMouseLeave.event;
A
Alex Dima 已提交
189

190 191 192
	private readonly _onMouseWheel: Emitter<IMouseWheelEvent> = this._register(new Emitter<IMouseWheelEvent>());
	public readonly onMouseWheel: Event<IMouseWheelEvent> = this._onMouseWheel.event;

A
Alex Dima 已提交
193 194 195 196 197 198 199 200 201 202 203
	private readonly _onKeyUp: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
	public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;

	private readonly _onKeyDown: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
	public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;

	private readonly _onDidScrollChange: Emitter<editorCommon.IScrollEvent> = this._register(new Emitter<editorCommon.IScrollEvent>());
	public readonly onDidScrollChange: Event<editorCommon.IScrollEvent> = this._onDidScrollChange.event;

	private readonly _onDidChangeViewZones: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeViewZones: Event<void> = this._onDidChangeViewZones.event;
A
Alex Dima 已提交
204
	//#endregion
A
Alex Dima 已提交
205

A
Alex Dima 已提交
206
	public readonly isSimpleWidget: boolean;
M
Matt Bierner 已提交
207
	private readonly _telemetryData?: object;
208

A
Alex Dima 已提交
209 210
	private readonly _domElement: HTMLElement;
	private readonly _id: number;
A
Alex Dima 已提交
211 212
	private readonly _configuration: editorCommon.IConfiguration;

A
Alex Dima 已提交
213 214
	protected readonly _contributions: { [key: string]: editorCommon.IEditorContribution; };
	protected readonly _actions: { [key: string]: editorCommon.IEditorAction; };
A
Alex Dima 已提交
215 216

	// --- Members logically associated to a model
A
Alex Dima 已提交
217
	protected _modelData: ModelData | null;
E
Erich Gamma 已提交
218

A
Alex Dima 已提交
219 220 221 222 223 224 225
	protected readonly _instantiationService: IInstantiationService;
	protected readonly _contextKeyService: IContextKeyService;
	private readonly _notificationService: INotificationService;
	private readonly _codeEditorService: ICodeEditorService;
	private readonly _commandService: ICommandService;
	private readonly _themeService: IThemeService;

A
Alex Dima 已提交
226
	private readonly _focusTracker: CodeEditorWidgetFocusTracker;
227

A
Alex Dima 已提交
228 229
	private readonly _contentWidgets: { [key: string]: IContentWidgetData; };
	private readonly _overlayWidgets: { [key: string]: IOverlayWidgetData; };
E
Erich Gamma 已提交
230

A
Alex Dima 已提交
231 232 233 234 235
	/**
	 * map from "parent" decoration type to live decoration ids.
	 */
	private _decorationTypeKeysToIds: { [decorationTypeKey: string]: string[] };
	private _decorationTypeSubtypes: { [decorationTypeKey: string]: { [subtype: string]: boolean } };
E
Erich Gamma 已提交
236 237

	constructor(
J
Johannes Rieken 已提交
238
		domElement: HTMLElement,
239
		options: IEditorOptions,
240
		codeEditorWidgetOptions: ICodeEditorWidgetOptions,
E
Erich Gamma 已提交
241 242
		@IInstantiationService instantiationService: IInstantiationService,
		@ICodeEditorService codeEditorService: ICodeEditorService,
243
		@ICommandService commandService: ICommandService,
244
		@IContextKeyService contextKeyService: IContextKeyService,
245
		@IThemeService themeService: IThemeService,
246 247
		@INotificationService notificationService: INotificationService,
		@IAccessibilityService accessibilityService: IAccessibilityService
E
Erich Gamma 已提交
248
	) {
A
Alex Dima 已提交
249
		super();
A
Alex Dima 已提交
250 251
		this._domElement = domElement;
		this._id = (++EDITOR_ID);
A
Alex Dima 已提交
252 253
		this._decorationTypeKeysToIds = {};
		this._decorationTypeSubtypes = {};
254
		this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false;
M
Matt Bierner 已提交
255
		this._telemetryData = codeEditorWidgetOptions.telemetryData;
A
Alex Dima 已提交
256 257

		options = options || {};
258
		this._configuration = this._register(this._createConfiguration(options, accessibilityService));
A
Alex Dima 已提交
259 260 261
		this._register(this._configuration.onDidChange((e) => {
			this._onDidChangeConfiguration.fire(e);

A
Alex Dima 已提交
262
			const options = this._configuration.options;
A
renames  
Alex Dima 已提交
263 264
			if (e.hasChanged(EditorOption.layoutInfo)) {
				const layoutInfo = options.get(EditorOption.layoutInfo);
A
Alex Dima 已提交
265
				this._onDidLayoutChange.fire(layoutInfo);
A
Alex Dima 已提交
266
			}
A
Alex Dima 已提交
267
			if (options.get(EditorOption.showUnused)) {
A
Alex Dima 已提交
268
				this._domElement.classList.add(SHOW_UNUSED_ENABLED_CLASS);
269
			} else {
A
Alex Dima 已提交
270
				this._domElement.classList.remove(SHOW_UNUSED_ENABLED_CLASS);
271
			}
A
Alex Dima 已提交
272 273
		}));

A
Alex Dima 已提交
274
		this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));
A
Alex Dima 已提交
275
		this._notificationService = notificationService;
276
		this._codeEditorService = codeEditorService;
277
		this._commandService = commandService;
278
		this._themeService = themeService;
A
Alex Dima 已提交
279 280 281 282 283
		this._register(new EditorContextKeysManager(this, this._contextKeyService));
		this._register(new EditorModeContext(this, this._contextKeyService));

		this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));

A
Alex Dima 已提交
284
		this._modelData = null;
A
Alex Dima 已提交
285 286 287

		this._contributions = {};
		this._actions = {};
E
Erich Gamma 已提交
288

289
		this._focusTracker = new CodeEditorWidgetFocusTracker(domElement);
A
Alex Dima 已提交
290
		this._focusTracker.onChange(() => {
A
Alex Dima 已提交
291
			this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());
E
Erich Gamma 已提交
292 293
		});

A
Alex Dima 已提交
294 295
		this._contentWidgets = {};
		this._overlayWidgets = {};
E
Erich Gamma 已提交
296

A
Alex Dima 已提交
297 298 299 300
		let contributions: IEditorContributionCtor[];
		if (Array.isArray(codeEditorWidgetOptions.contributions)) {
			contributions = codeEditorWidgetOptions.contributions;
		} else {
301 302
			contributions = EditorExtensionsRegistry.getEditorContributions();
		}
303
		for (let i = 0, len = contributions.length; i < len; i++) {
M
Matt Bierner 已提交
304
			const ctor = contributions[i];
E
Erich Gamma 已提交
305
			try {
M
Matt Bierner 已提交
306
				const contribution = this._instantiationService.createInstance(ctor, this);
A
Alex Dima 已提交
307
				this._contributions[contribution.getId()] = contribution;
E
Erich Gamma 已提交
308
			} catch (err) {
309
				onUnexpectedError(err);
E
Erich Gamma 已提交
310 311
			}
		}
312

313
		EditorExtensionsRegistry.getEditorActions().forEach((action) => {
314 315 316 317
			const internalAction = new InternalEditorAction(
				action.id,
				action.label,
				action.alias,
318
				withNullAsUndefined(action.precondition),
319
				(): Promise<void> => {
320
					return this._instantiationService.invokeFunction((accessor) => {
321
						return Promise.resolve(action.runEditorCommand(accessor, this, null));
322 323 324 325
					});
				},
				this._contextKeyService
			);
A
Alex Dima 已提交
326
			this._actions[internalAction.id] = internalAction;
327
		});
328 329

		this._codeEditorService.addCodeEditor(this);
E
Erich Gamma 已提交
330 331
	}

332
	protected _createConfiguration(options: IEditorOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration {
A
Alex Dima 已提交
333
		return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService);
A
Alex Dima 已提交
334 335 336
	}

	public getId(): string {
A
Alex Dima 已提交
337
		return this.getEditorType() + ':' + this._id;
A
Alex Dima 已提交
338 339 340 341
	}

	public getEditorType(): string {
		return editorCommon.EditorType.ICodeEditor;
E
Erich Gamma 已提交
342 343 344
	}

	public dispose(): void {
345 346
		this._codeEditorService.removeCodeEditor(this);

347
		this._focusTracker.dispose();
A
Alex Dima 已提交
348

M
Matt Bierner 已提交
349
		const keys = Object.keys(this._contributions);
A
Alex Dima 已提交
350
		for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
351
			const contributionId = keys[i];
A
Alex Dima 已提交
352 353 354 355 356 357 358 359
			this._contributions[contributionId].dispose();
		}

		this._removeDecorationTypes();
		this._postDetachModelCleanup(this._detachModel());

		this._onDidDispose.fire();

E
Erich Gamma 已提交
360 361 362
		super.dispose();
	}

A
Alex Dima 已提交
363 364 365 366
	public invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T {
		return this._instantiationService.invokeFunction(fn);
	}

367
	public updateOptions(newOptions: IEditorOptions): void {
A
Alex Dima 已提交
368 369 370
		this._configuration.updateOptions(newOptions);
	}

371
	public getConfiguration(): InternalEditorOptions {
A
Alex Dima 已提交
372 373 374
		return this._configuration.editor;
	}

375
	public getOptions(): IComputedEditorOptions {
A
Alex Dima 已提交
376 377 378
		return this._configuration.options;
	}

A
renames  
Alex Dima 已提交
379
	public getOption<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T> {
380
		return this._configuration.options.get(id);
A
Alex Dima 已提交
381 382
	}

383
	public getRawConfiguration(): IEditorOptions {
A
Alex Dima 已提交
384 385 386
		return this._configuration.getRawOptions();
	}

A
Alex Dima 已提交
387 388 389
	public getValue(options: { preserveBOM: boolean; lineEnding: string; } | null = null): string {
		if (!this._modelData) {
			return '';
A
Alex Dima 已提交
390
		}
A
Alex Dima 已提交
391

M
Matt Bierner 已提交
392
		const preserveBOM: boolean = (options && options.preserveBOM) ? true : false;
A
Alex Dima 已提交
393 394 395 396 397 398 399
		let eolPreference = EndOfLinePreference.TextDefined;
		if (options && options.lineEnding && options.lineEnding === '\n') {
			eolPreference = EndOfLinePreference.LF;
		} else if (options && options.lineEnding && options.lineEnding === '\r\n') {
			eolPreference = EndOfLinePreference.CRLF;
		}
		return this._modelData.model.getValue(eolPreference, preserveBOM);
A
Alex Dima 已提交
400 401 402
	}

	public setValue(newValue: string): void {
A
Alex Dima 已提交
403 404
		if (!this._modelData) {
			return;
A
Alex Dima 已提交
405
		}
A
Alex Dima 已提交
406
		this._modelData.model.setValue(newValue);
A
Alex Dima 已提交
407 408
	}

A
Alex Dima 已提交
409 410 411 412 413
	public getModel(): ITextModel | null {
		if (!this._modelData) {
			return null;
		}
		return this._modelData.model;
A
Alex Dima 已提交
414 415
	}

A
Alex Dima 已提交
416 417
	public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | null = null): void {
		const model = <ITextModel | null>_model;
A
Alex Dima 已提交
418 419 420 421 422
		if (this._modelData === null && model === null) {
			// Current model is the new model
			return;
		}
		if (this._modelData && this._modelData.model === model) {
A
Alex Dima 已提交
423 424 425 426
			// Current model is the new model
			return;
		}

M
Matt Bierner 已提交
427
		const detachedModel = this._detachModel();
A
Alex Dima 已提交
428 429
		this._attachModel(model);

M
Matt Bierner 已提交
430
		const e: editorCommon.IModelChangedEvent = {
A
Alex Dima 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443
			oldModelUrl: detachedModel ? detachedModel.uri : null,
			newModelUrl: model ? model.uri : null
		};

		this._removeDecorationTypes();
		this._onDidChangeModel.fire(e);
		this._postDetachModelCleanup(detachedModel);
	}

	private _removeDecorationTypes(): void {
		this._decorationTypeKeysToIds = {};
		if (this._decorationTypeSubtypes) {
			for (let decorationType in this._decorationTypeSubtypes) {
M
Matt Bierner 已提交
444
				const subTypes = this._decorationTypeSubtypes[decorationType];
A
Alex Dima 已提交
445 446 447 448 449 450 451 452 453
				for (let subType in subTypes) {
					this._removeDecorationType(decorationType + '-' + subType);
				}
			}
			this._decorationTypeSubtypes = {};
		}
	}

	public getVisibleRanges(): Range[] {
A
Alex Dima 已提交
454
		if (!this._modelData) {
A
Alex Dima 已提交
455 456
			return [];
		}
A
Alex Dima 已提交
457
		return this._modelData.viewModel.getVisibleRanges();
A
Alex Dima 已提交
458 459 460
	}

	public getWhitespaces(): IEditorWhitespace[] {
A
Alex Dima 已提交
461
		if (!this._modelData) {
A
Alex Dima 已提交
462 463
			return [];
		}
A
Alex Dima 已提交
464
		return this._modelData.viewModel.viewLayout.getWhitespaces();
A
Alex Dima 已提交
465 466
	}

A
Alex Dima 已提交
467
	private static _getVerticalOffsetForPosition(modelData: ModelData, modelLineNumber: number, modelColumn: number): number {
M
Matt Bierner 已提交
468
		const modelPosition = modelData.model.validatePosition({
A
Alex Dima 已提交
469 470 471
			lineNumber: modelLineNumber,
			column: modelColumn
		});
M
Matt Bierner 已提交
472
		const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
A
Alex Dima 已提交
473
		return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
A
Alex Dima 已提交
474 475 476
	}

	public getTopForLineNumber(lineNumber: number): number {
A
Alex Dima 已提交
477
		if (!this._modelData) {
A
Alex Dima 已提交
478 479
			return -1;
		}
A
Alex Dima 已提交
480
		return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, 1);
A
Alex Dima 已提交
481 482 483
	}

	public getTopForPosition(lineNumber: number, column: number): number {
A
Alex Dima 已提交
484
		if (!this._modelData) {
A
Alex Dima 已提交
485 486
			return -1;
		}
A
Alex Dima 已提交
487
		return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, column);
A
Alex Dima 已提交
488 489 490
	}

	public setHiddenAreas(ranges: IRange[]): void {
A
Alex Dima 已提交
491 492
		if (this._modelData) {
			this._modelData.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)));
A
Alex Dima 已提交
493 494 495 496
		}
	}

	public getVisibleColumnFromPosition(rawPosition: IPosition): number {
A
Alex Dima 已提交
497
		if (!this._modelData) {
A
Alex Dima 已提交
498 499 500
			return rawPosition.column;
		}

M
Matt Bierner 已提交
501 502
		const position = this._modelData.model.validatePosition(rawPosition);
		const tabSize = this._modelData.model.getOptions().tabSize;
A
Alex Dima 已提交
503

A
Alex Dima 已提交
504
		return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1;
A
Alex Dima 已提交
505 506
	}

A
Alex Dima 已提交
507 508
	public getPosition(): Position | null {
		if (!this._modelData) {
A
Alex Dima 已提交
509 510
			return null;
		}
A
Alex Dima 已提交
511
		return this._modelData.cursor.getPosition();
A
Alex Dima 已提交
512 513 514
	}

	public setPosition(position: IPosition): void {
A
Alex Dima 已提交
515
		if (!this._modelData) {
A
Alex Dima 已提交
516 517 518 519 520
			return;
		}
		if (!Position.isIPosition(position)) {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
521
		this._modelData.cursor.setSelections('api', [{
A
Alex Dima 已提交
522 523 524 525 526 527 528 529
			selectionStartLineNumber: position.lineNumber,
			selectionStartColumn: position.column,
			positionLineNumber: position.lineNumber,
			positionColumn: position.column
		}]);
	}

	private _sendRevealRange(modelRange: Range, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
A
Alex Dima 已提交
530
		if (!this._modelData) {
A
Alex Dima 已提交
531 532 533 534 535
			return;
		}
		if (!Range.isIRange(modelRange)) {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
536 537
		const validatedModelRange = this._modelData.model.validateRange(modelRange);
		const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);
A
Alex Dima 已提交
538

539
		this._modelData.cursor.emitCursorRevealRange('api', viewRange, verticalType, revealHorizontal, scrollType);
A
Alex Dima 已提交
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
	}

	public revealLine(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.Simple, scrollType);
	}

	public revealLineInCenter(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.Center, scrollType);
	}

	public revealLineInCenterIfOutsideViewport(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLine(lineNumber, VerticalRevealType.CenterIfOutsideViewport, scrollType);
	}

	private _revealLine(lineNumber: number, revealType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {
		if (typeof lineNumber !== 'number') {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(lineNumber, 1, lineNumber, 1),
			revealType,
			false,
			scrollType
		);
	}

	public revealPosition(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.Simple,
			true,
			scrollType
		);
	}

	public revealPositionInCenter(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.Center,
			true,
			scrollType
		);
	}

	public revealPositionInCenterIfOutsideViewport(position: IPosition, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealPosition(
			position,
			VerticalRevealType.CenterIfOutsideViewport,
			true,
			scrollType
		);
	}

	private _revealPosition(position: IPosition, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
		if (!Position.isIPosition(position)) {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(position.lineNumber, position.column, position.lineNumber, position.column),
			verticalType,
			revealHorizontal,
			scrollType
		);
	}

A
Alex Dima 已提交
607 608
	public getSelection(): Selection | null {
		if (!this._modelData) {
A
Alex Dima 已提交
609 610
			return null;
		}
A
Alex Dima 已提交
611
		return this._modelData.cursor.getSelection();
A
Alex Dima 已提交
612 613
	}

A
Alex Dima 已提交
614 615
	public getSelections(): Selection[] | null {
		if (!this._modelData) {
A
Alex Dima 已提交
616 617
			return null;
		}
A
Alex Dima 已提交
618
		return this._modelData.cursor.getSelections();
A
Alex Dima 已提交
619 620 621 622 623 624 625
	}

	public setSelection(range: IRange): void;
	public setSelection(editorRange: Range): void;
	public setSelection(selection: ISelection): void;
	public setSelection(editorSelection: Selection): void;
	public setSelection(something: any): void {
M
Matt Bierner 已提交
626 627
		const isSelection = Selection.isISelection(something);
		const isRange = Range.isIRange(something);
A
Alex Dima 已提交
628 629 630 631 632 633 634 635 636

		if (!isSelection && !isRange) {
			throw new Error('Invalid arguments');
		}

		if (isSelection) {
			this._setSelectionImpl(<ISelection>something);
		} else if (isRange) {
			// act as if it was an IRange
M
Matt Bierner 已提交
637
			const selection: ISelection = {
A
Alex Dima 已提交
638 639 640 641 642 643 644 645 646 647
				selectionStartLineNumber: something.startLineNumber,
				selectionStartColumn: something.startColumn,
				positionLineNumber: something.endLineNumber,
				positionColumn: something.endColumn
			};
			this._setSelectionImpl(selection);
		}
	}

	private _setSelectionImpl(sel: ISelection): void {
A
Alex Dima 已提交
648
		if (!this._modelData) {
A
Alex Dima 已提交
649 650
			return;
		}
M
Matt Bierner 已提交
651
		const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);
A
Alex Dima 已提交
652
		this._modelData.cursor.setSelections('api', [selection]);
A
Alex Dima 已提交
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
	}

	public revealLines(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.Simple,
			scrollType
		);
	}

	public revealLinesInCenter(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.Center,
			scrollType
		);
	}

	public revealLinesInCenterIfOutsideViewport(startLineNumber: number, endLineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealLines(
			startLineNumber,
			endLineNumber,
			VerticalRevealType.CenterIfOutsideViewport,
			scrollType
		);
	}

	private _revealLines(startLineNumber: number, endLineNumber: number, verticalType: VerticalRevealType, scrollType: editorCommon.ScrollType): void {
		if (typeof startLineNumber !== 'number' || typeof endLineNumber !== 'number') {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			new Range(startLineNumber, 1, endLineNumber, 1),
			verticalType,
			false,
			scrollType
		);
	}

	public revealRange(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth, revealVerticalInCenter: boolean = false, revealHorizontal: boolean = true): void {
		this._revealRange(
			range,
			revealVerticalInCenter ? VerticalRevealType.Center : VerticalRevealType.Simple,
			revealHorizontal,
			scrollType
		);
	}

	public revealRangeInCenter(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.Center,
			true,
			scrollType
		);
	}

	public revealRangeInCenterIfOutsideViewport(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.CenterIfOutsideViewport,
			true,
			scrollType
		);
	}

	public revealRangeAtTop(range: IRange, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void {
		this._revealRange(
			range,
			VerticalRevealType.Top,
			true,
			scrollType
		);
	}

	private _revealRange(range: IRange, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: editorCommon.ScrollType): void {
		if (!Range.isIRange(range)) {
			throw new Error('Invalid arguments');
		}

		this._sendRevealRange(
			Range.lift(range),
			verticalType,
			revealHorizontal,
			scrollType
		);
	}

A
Alex Dima 已提交
744
	public setSelections(ranges: ISelection[], source: string = 'api'): void {
A
Alex Dima 已提交
745
		if (!this._modelData) {
A
Alex Dima 已提交
746 747 748 749 750 751 752 753 754 755
			return;
		}
		if (!ranges || ranges.length === 0) {
			throw new Error('Invalid arguments');
		}
		for (let i = 0, len = ranges.length; i < len; i++) {
			if (!Selection.isISelection(ranges[i])) {
				throw new Error('Invalid arguments');
			}
		}
A
Alex Dima 已提交
756
		this._modelData.cursor.setSelections(source, ranges);
A
Alex Dima 已提交
757 758 759
	}

	public getScrollWidth(): number {
A
Alex Dima 已提交
760
		if (!this._modelData) {
A
Alex Dima 已提交
761 762
			return -1;
		}
A
Alex Dima 已提交
763
		return this._modelData.viewModel.viewLayout.getScrollWidth();
A
Alex Dima 已提交
764 765
	}
	public getScrollLeft(): number {
A
Alex Dima 已提交
766
		if (!this._modelData) {
A
Alex Dima 已提交
767 768
			return -1;
		}
A
Alex Dima 已提交
769
		return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();
A
Alex Dima 已提交
770 771 772
	}

	public getScrollHeight(): number {
A
Alex Dima 已提交
773
		if (!this._modelData) {
A
Alex Dima 已提交
774 775
			return -1;
		}
A
Alex Dima 已提交
776
		return this._modelData.viewModel.viewLayout.getScrollHeight();
A
Alex Dima 已提交
777 778
	}
	public getScrollTop(): number {
A
Alex Dima 已提交
779
		if (!this._modelData) {
A
Alex Dima 已提交
780 781
			return -1;
		}
A
Alex Dima 已提交
782
		return this._modelData.viewModel.viewLayout.getCurrentScrollTop();
A
Alex Dima 已提交
783 784 785
	}

	public setScrollLeft(newScrollLeft: number): void {
A
Alex Dima 已提交
786
		if (!this._modelData) {
A
Alex Dima 已提交
787 788 789 790 791
			return;
		}
		if (typeof newScrollLeft !== 'number') {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
792
		this._modelData.viewModel.viewLayout.setScrollPositionNow({
A
Alex Dima 已提交
793 794 795 796
			scrollLeft: newScrollLeft
		});
	}
	public setScrollTop(newScrollTop: number): void {
A
Alex Dima 已提交
797
		if (!this._modelData) {
A
Alex Dima 已提交
798 799 800 801 802
			return;
		}
		if (typeof newScrollTop !== 'number') {
			throw new Error('Invalid arguments');
		}
A
Alex Dima 已提交
803
		this._modelData.viewModel.viewLayout.setScrollPositionNow({
A
Alex Dima 已提交
804 805 806 807
			scrollTop: newScrollTop
		});
	}
	public setScrollPosition(position: editorCommon.INewScrollPosition): void {
A
Alex Dima 已提交
808
		if (!this._modelData) {
A
Alex Dima 已提交
809 810
			return;
		}
A
Alex Dima 已提交
811
		this._modelData.viewModel.viewLayout.setScrollPositionNow(position);
A
Alex Dima 已提交
812 813
	}

A
Alex Dima 已提交
814 815
	public saveViewState(): editorCommon.ICodeEditorViewState | null {
		if (!this._modelData) {
A
Alex Dima 已提交
816 817 818 819 820
			return null;
		}
		const contributionsState: { [key: string]: any } = {};

		const keys = Object.keys(this._contributions);
821
		for (const id of keys) {
A
Alex Dima 已提交
822 823 824 825 826 827
			const contribution = this._contributions[id];
			if (typeof contribution.saveViewState === 'function') {
				contributionsState[id] = contribution.saveViewState();
			}
		}

A
Alex Dima 已提交
828 829
		const cursorState = this._modelData.cursor.saveState();
		const viewState = this._modelData.viewModel.saveState();
A
Alex Dima 已提交
830 831 832 833 834 835 836
		return {
			cursorState: cursorState,
			viewState: viewState,
			contributionsState: contributionsState
		};
	}

M
Matt Bierner 已提交
837
	public restoreViewState(s: editorCommon.IEditorViewState | null): void {
A
Alex Dima 已提交
838
		if (!this._modelData || !this._modelData.hasRealView) {
A
Alex Dima 已提交
839 840
			return;
		}
M
Matt Bierner 已提交
841 842
		const codeEditorState = s as editorCommon.ICodeEditorViewState | null;
		if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) {
M
Matt Bierner 已提交
843
			const cursorState = <any>codeEditorState.cursorState;
A
Alex Dima 已提交
844
			if (Array.isArray(cursorState)) {
A
Alex Dima 已提交
845
				this._modelData.cursor.restoreState(<editorCommon.ICursorState[]>cursorState);
A
Alex Dima 已提交
846 847
			} else {
				// Backwards compatibility
A
Alex Dima 已提交
848
				this._modelData.cursor.restoreState([<editorCommon.ICursorState>cursorState]);
A
Alex Dima 已提交
849 850
			}

M
Matt Bierner 已提交
851 852
			const contributionsState = codeEditorState.contributionsState || {};
			const keys = Object.keys(this._contributions);
A
Alex Dima 已提交
853
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
854 855
				const id = keys[i];
				const contribution = this._contributions[id];
A
Alex Dima 已提交
856 857 858 859 860
				if (typeof contribution.restoreViewState === 'function') {
					contribution.restoreViewState(contributionsState[id]);
				}
			}

M
Matt Bierner 已提交
861
			const reducedState = this._modelData.viewModel.reduceRestoreState(codeEditorState.viewState);
A
Alex Dima 已提交
862
			this._modelData.view.restoreState(reducedState);
A
Alex Dima 已提交
863 864 865 866 867 868 869 870 871 872 873 874 875 876
		}
	}

	public onVisible(): void {
	}

	public onHide(): void {
	}

	public getContribution<T extends editorCommon.IEditorContribution>(id: string): T {
		return <T>(this._contributions[id] || null);
	}

	public getActions(): editorCommon.IEditorAction[] {
M
Matt Bierner 已提交
877
		const result: editorCommon.IEditorAction[] = [];
A
Alex Dima 已提交
878

M
Matt Bierner 已提交
879
		const keys = Object.keys(this._actions);
A
Alex Dima 已提交
880
		for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
881
			const id = keys[i];
A
Alex Dima 已提交
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
			result.push(this._actions[id]);
		}

		return result;
	}

	public getSupportedActions(): editorCommon.IEditorAction[] {
		let result = this.getActions();

		result = result.filter(action => action.isSupported());

		return result;
	}

	public getAction(id: string): editorCommon.IEditorAction {
		return this._actions[id] || null;
	}

	public trigger(source: string, handlerId: string, payload: any): void {
		payload = payload || {};

		// Special case for typing
		if (handlerId === editorCommon.Handler.Type) {
A
Alex Dima 已提交
905
			if (!this._modelData || typeof payload.text !== 'string' || payload.text.length === 0) {
A
Alex Dima 已提交
906 907 908 909 910 911
				// nothing to do
				return;
			}
			if (source === 'keyboard') {
				this._onWillType.fire(payload.text);
			}
A
Alex Dima 已提交
912
			this._modelData.cursor.trigger(source, handlerId, payload);
A
Alex Dima 已提交
913 914 915 916 917 918 919 920
			if (source === 'keyboard') {
				this._onDidType.fire(payload.text);
			}
			return;
		}

		// Special case for pasting
		if (handlerId === editorCommon.Handler.Paste) {
A
Alex Dima 已提交
921
			if (!this._modelData || typeof payload.text !== 'string' || payload.text.length === 0) {
A
Alex Dima 已提交
922 923 924
				// nothing to do
				return;
			}
A
Alex Dima 已提交
925 926 927
			const startPosition = this._modelData.cursor.getSelection().getStartPosition();
			this._modelData.cursor.trigger(source, handlerId, payload);
			const endPosition = this._modelData.cursor.getSelection().getStartPosition();
A
Alex Dima 已提交
928 929 930 931 932 933 934 935
			if (source === 'keyboard') {
				this._onDidPaste.fire(
					new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column)
				);
			}
			return;
		}

J
Johannes Rieken 已提交
936 937 938 939 940 941 942
		if (handlerId === editorCommon.Handler.CompositionStart) {
			this._onCompositionStart.fire();
		}
		if (handlerId === editorCommon.Handler.CompositionEnd) {
			this._onCompositionEnd.fire();
		}

A
Alex Dima 已提交
943 944
		const action = this.getAction(handlerId);
		if (action) {
R
Rob Lourens 已提交
945
			Promise.resolve(action.run()).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
946 947 948
			return;
		}

A
Alex Dima 已提交
949
		if (!this._modelData) {
A
Alex Dima 已提交
950 951 952 953 954 955 956
			return;
		}

		if (this._triggerEditorCommand(source, handlerId, payload)) {
			return;
		}

A
Alex Dima 已提交
957
		this._modelData.cursor.trigger(source, handlerId, payload);
A
Alex Dima 已提交
958 959 960 961 962 963 964
	}

	private _triggerEditorCommand(source: string, handlerId: string, payload: any): boolean {
		const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
		if (command) {
			payload = payload || {};
			payload.source = source;
A
Alex Dima 已提交
965
			this._instantiationService.invokeFunction((accessor) => {
R
Rob Lourens 已提交
966
				Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);
A
Alex Dima 已提交
967
			});
A
Alex Dima 已提交
968 969 970 971 972 973
			return true;
		}

		return false;
	}

A
Alex Dima 已提交
974 975 976 977 978
	public _getCursors(): ICursors | null {
		if (!this._modelData) {
			return null;
		}
		return this._modelData.cursor;
A
Alex Dima 已提交
979 980 981
	}

	public pushUndoStop(): boolean {
A
Alex Dima 已提交
982
		if (!this._modelData) {
A
Alex Dima 已提交
983 984
			return false;
		}
A
renames  
Alex Dima 已提交
985
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
986 987 988
			// read only editor => sorry!
			return false;
		}
A
Alex Dima 已提交
989
		this._modelData.model.pushStackElement();
A
Alex Dima 已提交
990 991 992
		return true;
	}

993
	public executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: ICursorStateComputer | Selection[]): boolean {
A
Alex Dima 已提交
994
		if (!this._modelData) {
A
Alex Dima 已提交
995 996
			return false;
		}
A
renames  
Alex Dima 已提交
997
		if (this._configuration.options.get(EditorOption.readOnly)) {
A
Alex Dima 已提交
998 999 1000 1001
			// read only editor => sorry!
			return false;
		}

1002 1003 1004 1005 1006 1007 1008
		let cursorStateComputer: ICursorStateComputer;
		if (!endCursorState) {
			cursorStateComputer = () => null;
		} else if (Array.isArray(endCursorState)) {
			cursorStateComputer = () => endCursorState;
		} else {
			cursorStateComputer = endCursorState;
A
Alex Dima 已提交
1009 1010
		}

1011
		this._modelData.cursor.executeEdits(source, edits, cursorStateComputer);
A
Alex Dima 已提交
1012 1013 1014 1015
		return true;
	}

	public executeCommand(source: string, command: editorCommon.ICommand): void {
A
Alex Dima 已提交
1016
		if (!this._modelData) {
A
Alex Dima 已提交
1017 1018
			return;
		}
A
Alex Dima 已提交
1019
		this._modelData.cursor.trigger(source, editorCommon.Handler.ExecuteCommand, command);
A
Alex Dima 已提交
1020 1021 1022
	}

	public executeCommands(source: string, commands: editorCommon.ICommand[]): void {
A
Alex Dima 已提交
1023
		if (!this._modelData) {
A
Alex Dima 已提交
1024 1025
			return;
		}
A
Alex Dima 已提交
1026
		this._modelData.cursor.trigger(source, editorCommon.Handler.ExecuteCommands, commands);
A
Alex Dima 已提交
1027 1028 1029
	}

	public changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any {
A
Alex Dima 已提交
1030
		if (!this._modelData) {
A
Alex Dima 已提交
1031 1032 1033
			// callback will not be called
			return null;
		}
A
Alex Dima 已提交
1034
		return this._modelData.model.changeDecorations(callback, this._id);
A
Alex Dima 已提交
1035 1036
	}

A
Alex Dima 已提交
1037 1038
	public getLineDecorations(lineNumber: number): IModelDecoration[] | null {
		if (!this._modelData) {
A
Alex Dima 已提交
1039 1040
			return null;
		}
A
renames  
Alex Dima 已提交
1041
		return this._modelData.model.getLineDecorations(lineNumber, this._id, this._configuration.options.get(EditorOption.readOnly));
A
Alex Dima 已提交
1042 1043 1044
	}

	public deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[] {
A
Alex Dima 已提交
1045
		if (!this._modelData) {
A
Alex Dima 已提交
1046 1047 1048 1049 1050 1051 1052
			return [];
		}

		if (oldDecorations.length === 0 && newDecorations.length === 0) {
			return oldDecorations;
		}

A
Alex Dima 已提交
1053
		return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);
A
Alex Dima 已提交
1054 1055 1056 1057
	}

	public setDecorations(decorationTypeKey: string, decorationOptions: editorCommon.IDecorationOptions[]): void {

M
Matt Bierner 已提交
1058 1059
		const newDecorationsSubTypes: { [key: string]: boolean } = {};
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1060 1061
		this._decorationTypeSubtypes[decorationTypeKey] = newDecorationsSubTypes;

M
Matt Bierner 已提交
1062
		const newModelDecorations: IModelDeltaDecoration[] = [];
A
Alex Dima 已提交
1063 1064 1065 1066 1067 1068

		for (let decorationOption of decorationOptions) {
			let typeKey = decorationTypeKey;
			if (decorationOption.renderOptions) {
				// identify custom reder options by a hash code over all keys and values
				// For custom render options register a decoration type if necessary
M
Matt Bierner 已提交
1069
				const subType = hash(decorationOption.renderOptions).toString(16);
A
Alex Dima 已提交
1070 1071 1072 1073 1074 1075 1076 1077 1078
				// The fact that `decorationTypeKey` appears in the typeKey has no influence
				// it is just a mechanism to get predictable and unique keys (repeatable for the same options and unique across clients)
				typeKey = decorationTypeKey + '-' + subType;
				if (!oldDecorationsSubTypes[subType] && !newDecorationsSubTypes[subType]) {
					// decoration type did not exist before, register new one
					this._registerDecorationType(typeKey, decorationOption.renderOptions, decorationTypeKey);
				}
				newDecorationsSubTypes[subType] = true;
			}
M
Matt Bierner 已提交
1079
			const opts = this._resolveDecorationOptions(typeKey, !!decorationOption.hoverMessage);
A
Alex Dima 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
			if (decorationOption.hoverMessage) {
				opts.hoverMessage = decorationOption.hoverMessage;
			}
			newModelDecorations.push({ range: decorationOption.range, options: opts });
		}

		// remove decoration sub types that are no longer used, deregister decoration type if necessary
		for (let subType in oldDecorationsSubTypes) {
			if (!newDecorationsSubTypes[subType]) {
				this._removeDecorationType(decorationTypeKey + '-' + subType);
			}
		}

		// update all decorations
M
Matt Bierner 已提交
1094
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1095 1096 1097 1098 1099 1100
		this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations);
	}

	public setDecorationsFast(decorationTypeKey: string, ranges: IRange[]): void {

		// remove decoration sub types that are no longer used, deregister decoration type if necessary
M
Matt Bierner 已提交
1101
		const oldDecorationsSubTypes = this._decorationTypeSubtypes[decorationTypeKey] || {};
A
Alex Dima 已提交
1102 1103 1104 1105 1106 1107
		for (let subType in oldDecorationsSubTypes) {
			this._removeDecorationType(decorationTypeKey + '-' + subType);
		}
		this._decorationTypeSubtypes[decorationTypeKey] = {};

		const opts = ModelDecorationOptions.createDynamic(this._resolveDecorationOptions(decorationTypeKey, false));
M
Matt Bierner 已提交
1108
		const newModelDecorations: IModelDeltaDecoration[] = new Array<IModelDeltaDecoration>(ranges.length);
A
Alex Dima 已提交
1109 1110 1111 1112 1113
		for (let i = 0, len = ranges.length; i < len; i++) {
			newModelDecorations[i] = { range: ranges[i], options: opts };
		}

		// update all decorations
M
Matt Bierner 已提交
1114
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey] || [];
A
Alex Dima 已提交
1115 1116 1117 1118 1119
		this._decorationTypeKeysToIds[decorationTypeKey] = this.deltaDecorations(oldDecorationsIds, newModelDecorations);
	}

	public removeDecorations(decorationTypeKey: string): void {
		// remove decorations for type and sub type
M
Matt Bierner 已提交
1120
		const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];
A
Alex Dima 已提交
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
		if (oldDecorationsIds) {
			this.deltaDecorations(oldDecorationsIds, []);
		}
		if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeKeysToIds[decorationTypeKey];
		}
		if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {
			delete this._decorationTypeSubtypes[decorationTypeKey];
		}
	}

1132
	public getLayoutInfo(): EditorLayoutInfo {
A
Alex Dima 已提交
1133
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1134
		const layoutInfo = options.get(EditorOption.layoutInfo);
A
Alex Dima 已提交
1135
		return layoutInfo;
A
Alex Dima 已提交
1136 1137
	}

A
Alex Dima 已提交
1138 1139 1140 1141 1142
	public createOverviewRuler(cssClassName: string): editorBrowser.IOverviewRuler | null {
		if (!this._modelData || !this._modelData.hasRealView) {
			return null;
		}
		return this._modelData.view.createOverviewRuler(cssClassName);
E
Erich Gamma 已提交
1143 1144
	}

A
Alex Dima 已提交
1145 1146
	public getDomNode(): HTMLElement | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1147 1148
			return null;
		}
A
Alex Dima 已提交
1149
		return this._modelData.view.domNode.domNode;
E
Erich Gamma 已提交
1150 1151
	}

1152
	public delegateVerticalScrollbarMouseDown(browserEvent: IMouseEvent): void {
A
Alex Dima 已提交
1153
		if (!this._modelData || !this._modelData.hasRealView) {
1154
			return;
E
Erich Gamma 已提交
1155
		}
A
Alex Dima 已提交
1156
		this._modelData.view.delegateVerticalScrollbarMouseDown(browserEvent);
E
Erich Gamma 已提交
1157 1158
	}

J
Johannes Rieken 已提交
1159
	public layout(dimension?: editorCommon.IDimension): void {
E
Erich Gamma 已提交
1160
		this._configuration.observeReferenceElement(dimension);
1161
		this.render();
E
Erich Gamma 已提交
1162 1163 1164
	}

	public focus(): void {
A
Alex Dima 已提交
1165
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1166 1167
			return;
		}
A
Alex Dima 已提交
1168
		this._modelData.view.focus();
E
Erich Gamma 已提交
1169 1170
	}

A
Alex Dima 已提交
1171
	public hasTextFocus(): boolean {
A
Alex Dima 已提交
1172 1173 1174 1175
		if (!this._modelData || !this._modelData.hasRealView) {
			return false;
		}
		return this._modelData.view.isFocused();
E
Erich Gamma 已提交
1176 1177
	}

1178
	public hasWidgetFocus(): boolean {
1179
		return this._focusTracker && this._focusTracker.hasFocus();
1180 1181
	}

A
Alex Dima 已提交
1182
	public addContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1183
		const widgetData: IContentWidgetData = {
E
Erich Gamma 已提交
1184 1185 1186 1187
			widget: widget,
			position: widget.getPosition()
		};

A
Alex Dima 已提交
1188
		if (this._contentWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1189 1190 1191
			console.warn('Overwriting a content widget with the same id.');
		}

A
Alex Dima 已提交
1192
		this._contentWidgets[widget.getId()] = widgetData;
E
Erich Gamma 已提交
1193

A
Alex Dima 已提交
1194 1195
		if (this._modelData && this._modelData.hasRealView) {
			this._modelData.view.addContentWidget(widgetData);
E
Erich Gamma 已提交
1196 1197 1198
		}
	}

A
Alex Dima 已提交
1199
	public layoutContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1200
		const widgetId = widget.getId();
A
Alex Dima 已提交
1201
		if (this._contentWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1202
			const widgetData = this._contentWidgets[widgetId];
E
Erich Gamma 已提交
1203
			widgetData.position = widget.getPosition();
A
Alex Dima 已提交
1204 1205
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.layoutContentWidget(widgetData);
E
Erich Gamma 已提交
1206 1207 1208 1209
			}
		}
	}

A
Alex Dima 已提交
1210
	public removeContentWidget(widget: editorBrowser.IContentWidget): void {
M
Matt Bierner 已提交
1211
		const widgetId = widget.getId();
A
Alex Dima 已提交
1212
		if (this._contentWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1213
			const widgetData = this._contentWidgets[widgetId];
A
Alex Dima 已提交
1214
			delete this._contentWidgets[widgetId];
A
Alex Dima 已提交
1215 1216
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.removeContentWidget(widgetData);
E
Erich Gamma 已提交
1217 1218 1219 1220
			}
		}
	}

A
Alex Dima 已提交
1221
	public addOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1222
		const widgetData: IOverlayWidgetData = {
E
Erich Gamma 已提交
1223 1224 1225 1226
			widget: widget,
			position: widget.getPosition()
		};

A
Alex Dima 已提交
1227
		if (this._overlayWidgets.hasOwnProperty(widget.getId())) {
E
Erich Gamma 已提交
1228 1229 1230
			console.warn('Overwriting an overlay widget with the same id.');
		}

A
Alex Dima 已提交
1231
		this._overlayWidgets[widget.getId()] = widgetData;
E
Erich Gamma 已提交
1232

A
Alex Dima 已提交
1233 1234
		if (this._modelData && this._modelData.hasRealView) {
			this._modelData.view.addOverlayWidget(widgetData);
E
Erich Gamma 已提交
1235 1236 1237
		}
	}

A
Alex Dima 已提交
1238
	public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1239
		const widgetId = widget.getId();
A
Alex Dima 已提交
1240
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1241
			const widgetData = this._overlayWidgets[widgetId];
E
Erich Gamma 已提交
1242
			widgetData.position = widget.getPosition();
A
Alex Dima 已提交
1243 1244
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.layoutOverlayWidget(widgetData);
E
Erich Gamma 已提交
1245 1246 1247 1248
			}
		}
	}

A
Alex Dima 已提交
1249
	public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
M
Matt Bierner 已提交
1250
		const widgetId = widget.getId();
A
Alex Dima 已提交
1251
		if (this._overlayWidgets.hasOwnProperty(widgetId)) {
M
Matt Bierner 已提交
1252
			const widgetData = this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1253
			delete this._overlayWidgets[widgetId];
A
Alex Dima 已提交
1254 1255
			if (this._modelData && this._modelData.hasRealView) {
				this._modelData.view.removeOverlayWidget(widgetData);
E
Erich Gamma 已提交
1256 1257 1258 1259
			}
		}
	}

J
Johannes Rieken 已提交
1260
	public changeViewZones(callback: (accessor: editorBrowser.IViewZoneChangeAccessor) => void): void {
A
Alex Dima 已提交
1261
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1262 1263
			return;
		}
M
Matt Bierner 已提交
1264
		const hasChanges = this._modelData.view.change(callback);
E
Erich Gamma 已提交
1265
		if (hasChanges) {
A
Alex Dima 已提交
1266
			this._onDidChangeViewZones.fire();
E
Erich Gamma 已提交
1267 1268 1269
		}
	}

A
Alex Dima 已提交
1270 1271
	public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
		if (!this._modelData || !this._modelData.hasRealView) {
1272 1273
			return null;
		}
A
Alex Dima 已提交
1274
		return this._modelData.view.getTargetAtClientPoint(clientX, clientY);
1275 1276
	}

A
Alex Dima 已提交
1277 1278
	public getScrolledVisiblePosition(rawPosition: IPosition): { top: number; left: number; height: number; } | null {
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1279 1280 1281
			return null;
		}

M
Matt Bierner 已提交
1282
		const position = this._modelData.model.validatePosition(rawPosition);
A
Alex Dima 已提交
1283
		const options = this._configuration.options;
A
renames  
Alex Dima 已提交
1284
		const layoutInfo = options.get(EditorOption.layoutInfo);
E
Erich Gamma 已提交
1285

M
Matt Bierner 已提交
1286 1287
		const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop();
		const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft();
E
Erich Gamma 已提交
1288 1289 1290 1291

		return {
			top: top,
			left: left,
A
Alex Dima 已提交
1292
			height: options.get(EditorOption.lineHeight)
E
Erich Gamma 已提交
1293 1294 1295
		};
	}

J
Johannes Rieken 已提交
1296
	public getOffsetForColumn(lineNumber: number, column: number): number {
A
Alex Dima 已提交
1297
		if (!this._modelData || !this._modelData.hasRealView) {
E
Erich Gamma 已提交
1298 1299
			return -1;
		}
A
Alex Dima 已提交
1300
		return this._modelData.view.getOffsetForColumn(lineNumber, column);
E
Erich Gamma 已提交
1301 1302
	}

1303
	public render(forceRedraw: boolean = false): void {
A
Alex Dima 已提交
1304
		if (!this._modelData || !this._modelData.hasRealView) {
1305 1306
			return;
		}
1307
		this._modelData.view.render(true, forceRedraw);
1308 1309
	}

J
Johannes Rieken 已提交
1310
	public applyFontInfo(target: HTMLElement): void {
1311 1312 1313
		Configuration.applyFontInfoSlow(target, this._configuration.editor.fontInfo);
	}

A
Alex Dima 已提交
1314 1315 1316 1317 1318
	protected _attachModel(model: ITextModel | null): void {
		if (!model) {
			this._modelData = null;
			return;
		}
E
Erich Gamma 已提交
1319

A
Alex Dima 已提交
1320
		const listenersToRemove: IDisposable[] = [];
A
Alex Dima 已提交
1321

A
Alex Dima 已提交
1322
		this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1323 1324
		this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());
		this._configuration.setMaxLineNumber(model.getLineCount());
A
Alex Dima 已提交
1325

A
Alex Dima 已提交
1326
		model.onBeforeAttached();
A
Alex Dima 已提交
1327

A
Alex Dima 已提交
1328
		const viewModel = new ViewModel(this._id, this._configuration, model, (callback) => dom.scheduleAtNextAnimationFrame(callback));
A
Alex Dima 已提交
1329

A
Alex Dima 已提交
1330 1331
		listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
		listenersToRemove.push(model.onDidChangeLanguage((e) => {
A
Alex Dima 已提交
1332
			this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
A
Alex Dima 已提交
1333 1334 1335 1336 1337 1338 1339
			this._onDidChangeModelLanguage.fire(e);
		}));
		listenersToRemove.push(model.onDidChangeLanguageConfiguration((e) => this._onDidChangeModelLanguageConfiguration.fire(e)));
		listenersToRemove.push(model.onDidChangeContent((e) => this._onDidChangeModelContent.fire(e)));
		listenersToRemove.push(model.onDidChangeOptions((e) => this._onDidChangeModelOptions.fire(e)));
		// Someone might destroy the model from under the editor, so prevent any exceptions by setting a null model
		listenersToRemove.push(model.onWillDispose(() => this.setModel(null)));
A
Alex Dima 已提交
1340

A
Alex Dima 已提交
1341
		const cursor = new Cursor(this._configuration, model, viewModel);
A
Alex Dima 已提交
1342

A
Alex Dima 已提交
1343 1344 1345
		listenersToRemove.push(cursor.onDidReachMaxCursorCount(() => {
			this._notificationService.warn(nls.localize('cursors.maximum', "The number of cursors has been limited to {0}.", Cursor.MAX_CURSOR_COUNT));
		}));
A
Alex Dima 已提交
1346

A
Alex Dima 已提交
1347
		listenersToRemove.push(cursor.onDidAttemptReadOnlyEdit(() => {
R
Rob Lourens 已提交
1348
			this._onDidAttemptReadOnlyEdit.fire(undefined);
A
Alex Dima 已提交
1349
		}));
A
Alex Dima 已提交
1350

A
Alex Dima 已提交
1351
		listenersToRemove.push(cursor.onDidChange((e: CursorStateChangedEvent) => {
M
Matt Bierner 已提交
1352
			const positions: Position[] = [];
A
Alex Dima 已提交
1353 1354 1355
			for (let i = 0, len = e.selections.length; i < len; i++) {
				positions[i] = e.selections[i].getPosition();
			}
A
Alex Dima 已提交
1356

A
Alex Dima 已提交
1357 1358 1359 1360 1361 1362 1363
			const e1: ICursorPositionChangedEvent = {
				position: positions[0],
				secondaryPositions: positions.slice(1),
				reason: e.reason,
				source: e.source
			};
			this._onDidChangeCursorPosition.fire(e1);
A
Alex Dima 已提交
1364

A
Alex Dima 已提交
1365 1366 1367 1368 1369 1370 1371 1372
			const e2: ICursorSelectionChangedEvent = {
				selection: e.selections[0],
				secondarySelections: e.selections.slice(1),
				source: e.source,
				reason: e.reason
			};
			this._onDidChangeCursorSelection.fire(e2);
		}));
E
Erich Gamma 已提交
1373

A
Alex Dima 已提交
1374 1375
		const [view, hasRealView] = this._createView(viewModel, cursor);
		if (hasRealView) {
A
Alex Dima 已提交
1376
			this._domElement.appendChild(view.domNode.domNode);
E
Erich Gamma 已提交
1377

A
Alex Dima 已提交
1378
			let keys = Object.keys(this._contentWidgets);
A
Alex Dima 已提交
1379
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1380
				const widgetId = keys[i];
A
Alex Dima 已提交
1381
				view.addContentWidget(this._contentWidgets[widgetId]);
A
Alex Dima 已提交
1382
			}
E
Erich Gamma 已提交
1383

A
Alex Dima 已提交
1384
			keys = Object.keys(this._overlayWidgets);
A
Alex Dima 已提交
1385
			for (let i = 0, len = keys.length; i < len; i++) {
M
Matt Bierner 已提交
1386
				const widgetId = keys[i];
A
Alex Dima 已提交
1387
				view.addOverlayWidget(this._overlayWidgets[widgetId]);
A
Alex Dima 已提交
1388
			}
E
Erich Gamma 已提交
1389

A
Alex Dima 已提交
1390 1391
			view.render(false, true);
			view.domNode.domNode.setAttribute('data-uri', model.uri.toString());
E
Erich Gamma 已提交
1392
		}
A
Alex Dima 已提交
1393 1394

		this._modelData = new ModelData(model, viewModel, cursor, view, hasRealView, listenersToRemove);
E
Erich Gamma 已提交
1395 1396
	}

A
Alex Dima 已提交
1397
	protected _createView(viewModel: ViewModel, cursor: Cursor): [View, boolean] {
1398 1399 1400
		let commandDelegate: ICommandDelegate;
		if (this.isSimpleWidget) {
			commandDelegate = {
A
Alex Dima 已提交
1401 1402 1403 1404
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
					editorCommand.runCoreEditorCommand(cursor, args);
				},
				paste: (source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null) => {
1405
					this.trigger(source, editorCommon.Handler.Paste, { text, pasteOnNewLine, multicursorText });
1406 1407
				},
				type: (source: string, text: string) => {
1408
					this.trigger(source, editorCommon.Handler.Type, { text });
1409 1410
				},
				replacePreviousChar: (source: string, text: string, replaceCharCnt: number) => {
1411
					this.trigger(source, editorCommon.Handler.ReplacePreviousChar, { text, replaceCharCnt });
1412 1413
				},
				compositionStart: (source: string) => {
1414
					this.trigger(source, editorCommon.Handler.CompositionStart, undefined);
1415 1416
				},
				compositionEnd: (source: string) => {
1417
					this.trigger(source, editorCommon.Handler.CompositionEnd, undefined);
1418 1419
				},
				cut: (source: string) => {
1420
					this.trigger(source, editorCommon.Handler.Cut, undefined);
1421 1422 1423 1424
				}
			};
		} else {
			commandDelegate = {
A
Alex Dima 已提交
1425 1426 1427 1428
				executeEditorCommand: (editorCommand: CoreEditorCommand, args: any): void => {
					editorCommand.runCoreEditorCommand(cursor, args);
				},
				paste: (source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null) => {
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
					this._commandService.executeCommand(editorCommon.Handler.Paste, {
						text: text,
						pasteOnNewLine: pasteOnNewLine,
						multicursorText: multicursorText
					});
				},
				type: (source: string, text: string) => {
					this._commandService.executeCommand(editorCommon.Handler.Type, {
						text: text
					});
				},
				replacePreviousChar: (source: string, text: string, replaceCharCnt: number) => {
					this._commandService.executeCommand(editorCommon.Handler.ReplacePreviousChar, {
						text: text,
						replaceCharCnt: replaceCharCnt
					});
				},
				compositionStart: (source: string) => {
					this._commandService.executeCommand(editorCommon.Handler.CompositionStart, {});
				},
				compositionEnd: (source: string) => {
					this._commandService.executeCommand(editorCommon.Handler.CompositionEnd, {});
				},
				cut: (source: string) => {
					this._commandService.executeCommand(editorCommon.Handler.Cut, {});
				}
			};
		}

A
Alex Dima 已提交
1458 1459
		const viewOutgoingEvents = new ViewOutgoingEvents(viewModel);
		viewOutgoingEvents.onDidGainFocus = () => {
1460
			this._editorTextFocus.setValue(true);
A
Alex Dima 已提交
1461
			// In IE, the focus is not synchronous, so we give it a little help
A
Alex Dima 已提交
1462
			this._editorWidgetFocus.setValue(true);
A
Alex Dima 已提交
1463
		};
1464

A
Alex Dima 已提交
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
		viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
		viewOutgoingEvents.onDidLoseFocus = () => this._editorTextFocus.setValue(false);
		viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e);
		viewOutgoingEvents.onMouseDown = (e) => this._onMouseDown.fire(e);
		viewOutgoingEvents.onMouseUp = (e) => this._onMouseUp.fire(e);
		viewOutgoingEvents.onMouseDrag = (e) => this._onMouseDrag.fire(e);
		viewOutgoingEvents.onMouseDrop = (e) => this._onMouseDrop.fire(e);
		viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e);
		viewOutgoingEvents.onMouseMove = (e) => this._onMouseMove.fire(e);
		viewOutgoingEvents.onMouseLeave = (e) => this._onMouseLeave.fire(e);
1475
		viewOutgoingEvents.onMouseWheel = (e) => this._onMouseWheel.fire(e);
A
Alex Dima 已提交
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
		viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e);

		const view = new View(
			commandDelegate,
			this._configuration,
			this._themeService,
			viewModel,
			cursor,
			viewOutgoingEvents
		);
A
Alex Dima 已提交
1486

A
Alex Dima 已提交
1487
		return [view, true];
1488
	}
E
Erich Gamma 已提交
1489

A
Alex Dima 已提交
1490
	protected _postDetachModelCleanup(detachedModel: ITextModel | null): void {
A
Alex Dima 已提交
1491
		if (detachedModel) {
A
Alex Dima 已提交
1492
			detachedModel.removeAllDecorationsWithOwnerId(this._id);
1493 1494 1495
		}
	}

A
Alex Dima 已提交
1496 1497 1498
	private _detachModel(): ITextModel | null {
		if (!this._modelData) {
			return null;
A
Alex Dima 已提交
1499
		}
A
Alex Dima 已提交
1500 1501
		const model = this._modelData.model;
		const removeDomNode = this._modelData.hasRealView ? this._modelData.view.domNode.domNode : null;
A
Alex Dima 已提交
1502

A
Alex Dima 已提交
1503 1504
		this._modelData.dispose();
		this._modelData = null;
A
Alex Dima 已提交
1505

A
Alex Dima 已提交
1506
		this._domElement.removeAttribute('data-mode-id');
E
Erich Gamma 已提交
1507
		if (removeDomNode) {
A
Alex Dima 已提交
1508
			this._domElement.removeChild(removeDomNode);
E
Erich Gamma 已提交
1509 1510
		}

A
Alex Dima 已提交
1511
		return model;
E
Erich Gamma 已提交
1512
	}
1513

A
Alex Dima 已提交
1514
	private _registerDecorationType(key: string, options: editorCommon.IDecorationRenderOptions, parentTypeKey?: string): void {
1515 1516 1517
		this._codeEditorService.registerDecorationType(key, options, parentTypeKey);
	}

A
Alex Dima 已提交
1518
	private _removeDecorationType(key: string): void {
1519 1520 1521
		this._codeEditorService.removeDecorationType(key);
	}

A
Alex Dima 已提交
1522
	private _resolveDecorationOptions(typeKey: string, writable: boolean): IModelDecorationOptions {
1523 1524 1525
		return this._codeEditorService.resolveDecorationOptions(typeKey, writable);
	}

M
Matt Bierner 已提交
1526
	public getTelemetryData(): { [key: string]: any; } | undefined {
1527
		return this._telemetryData;
A
Alex Dima 已提交
1528
	}
A
Alex Dima 已提交
1529 1530 1531 1532

	public hasModel(): this is editorBrowser.IActiveCodeEditor {
		return (this._modelData !== null);
	}
A
Alex Dima 已提交
1533
}
1534

A
Alex Dima 已提交
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555
const enum BooleanEventValue {
	NotSet,
	False,
	True
}

export class BooleanEventEmitter extends Disposable {
	private readonly _onDidChangeToTrue: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeToTrue: Event<void> = this._onDidChangeToTrue.event;

	private readonly _onDidChangeToFalse: Emitter<void> = this._register(new Emitter<void>());
	public readonly onDidChangeToFalse: Event<void> = this._onDidChangeToFalse.event;

	private _value: BooleanEventValue;

	constructor() {
		super();
		this._value = BooleanEventValue.NotSet;
	}

	public setValue(_value: boolean) {
M
Matt Bierner 已提交
1556
		const value = (_value ? BooleanEventValue.True : BooleanEventValue.False);
A
Alex Dima 已提交
1557 1558
		if (this._value === value) {
			return;
1559
		}
A
Alex Dima 已提交
1560 1561 1562 1563 1564 1565 1566 1567
		this._value = value;
		if (this._value === BooleanEventValue.True) {
			this._onDidChangeToTrue.fire();
		} else if (this._value === BooleanEventValue.False) {
			this._onDidChangeToFalse.fire();
		}
	}
}
1568

A
Alex Dima 已提交
1569 1570
class EditorContextKeysManager extends Disposable {

1571 1572 1573 1574 1575 1576 1577 1578 1579 1580
	private readonly _editor: CodeEditorWidget;
	private readonly _editorFocus: IContextKey<boolean>;
	private readonly _textInputFocus: IContextKey<boolean>;
	private readonly _editorTextFocus: IContextKey<boolean>;
	private readonly _editorTabMovesFocus: IContextKey<boolean>;
	private readonly _editorReadonly: IContextKey<boolean>;
	private readonly _hasMultipleSelections: IContextKey<boolean>;
	private readonly _hasNonEmptySelection: IContextKey<boolean>;
	private readonly _canUndo: IContextKey<boolean>;
	private readonly _canRedo: IContextKey<boolean>;
A
Alex Dima 已提交
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597

	constructor(
		editor: CodeEditorWidget,
		contextKeyService: IContextKeyService
	) {
		super();

		this._editor = editor;

		contextKeyService.createKey('editorId', editor.getId());
		this._editorFocus = EditorContextKeys.focus.bindTo(contextKeyService);
		this._textInputFocus = EditorContextKeys.textInputFocus.bindTo(contextKeyService);
		this._editorTextFocus = EditorContextKeys.editorTextFocus.bindTo(contextKeyService);
		this._editorTabMovesFocus = EditorContextKeys.tabMovesFocus.bindTo(contextKeyService);
		this._editorReadonly = EditorContextKeys.readOnly.bindTo(contextKeyService);
		this._hasMultipleSelections = EditorContextKeys.hasMultipleSelections.bindTo(contextKeyService);
		this._hasNonEmptySelection = EditorContextKeys.hasNonEmptySelection.bindTo(contextKeyService);
A
Alex Dima 已提交
1598 1599
		this._canUndo = EditorContextKeys.canUndo.bindTo(contextKeyService);
		this._canRedo = EditorContextKeys.canRedo.bindTo(contextKeyService);
A
Alex Dima 已提交
1600 1601 1602

		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromConfig()));
		this._register(this._editor.onDidChangeCursorSelection(() => this._updateFromSelection()));
A
Alex Dima 已提交
1603 1604
		this._register(this._editor.onDidFocusEditorWidget(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorWidget(() => this._updateFromFocus()));
A
Alex Dima 已提交
1605 1606
		this._register(this._editor.onDidFocusEditorText(() => this._updateFromFocus()));
		this._register(this._editor.onDidBlurEditorText(() => this._updateFromFocus()));
A
Alex Dima 已提交
1607 1608
		this._register(this._editor.onDidChangeModel(() => this._updateFromModel()));
		this._register(this._editor.onDidChangeConfiguration(() => this._updateFromModel()));
A
Alex Dima 已提交
1609 1610 1611 1612

		this._updateFromConfig();
		this._updateFromSelection();
		this._updateFromFocus();
A
Alex Dima 已提交
1613
		this._updateFromModel();
A
Alex Dima 已提交
1614 1615 1616
	}

	private _updateFromConfig(): void {
1617
		const options = this._editor.getOptions();
A
Alex Dima 已提交
1618

A
renames  
Alex Dima 已提交
1619 1620
		this._editorTabMovesFocus.set(options.get(EditorOption.tabFocusMode));
		this._editorReadonly.set(options.get(EditorOption.readOnly));
A
Alex Dima 已提交
1621 1622 1623
	}

	private _updateFromSelection(): void {
M
Matt Bierner 已提交
1624
		const selections = this._editor.getSelections();
A
Alex Dima 已提交
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
		if (!selections) {
			this._hasMultipleSelections.reset();
			this._hasNonEmptySelection.reset();
		} else {
			this._hasMultipleSelections.set(selections.length > 1);
			this._hasNonEmptySelection.set(selections.some(s => !s.isEmpty()));
		}
	}

	private _updateFromFocus(): void {
		this._editorFocus.set(this._editor.hasWidgetFocus() && !this._editor.isSimpleWidget);
A
Alex Dima 已提交
1636 1637
		this._editorTextFocus.set(this._editor.hasTextFocus() && !this._editor.isSimpleWidget);
		this._textInputFocus.set(this._editor.hasTextFocus());
A
Alex Dima 已提交
1638
	}
A
Alex Dima 已提交
1639 1640 1641

	private _updateFromModel(): void {
		const model = this._editor.getModel();
A
Alex Dima 已提交
1642 1643
		this._canUndo.set(Boolean(model && model.canUndo()));
		this._canRedo.set(Boolean(model && model.canRedo()));
A
Alex Dima 已提交
1644
	}
A
Alex Dima 已提交
1645 1646 1647 1648
}

export class EditorModeContext extends Disposable {

1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
	private readonly _langId: IContextKey<string>;
	private readonly _hasCompletionItemProvider: IContextKey<boolean>;
	private readonly _hasCodeActionsProvider: IContextKey<boolean>;
	private readonly _hasCodeLensProvider: IContextKey<boolean>;
	private readonly _hasDefinitionProvider: IContextKey<boolean>;
	private readonly _hasDeclarationProvider: IContextKey<boolean>;
	private readonly _hasImplementationProvider: IContextKey<boolean>;
	private readonly _hasTypeDefinitionProvider: IContextKey<boolean>;
	private readonly _hasHoverProvider: IContextKey<boolean>;
	private readonly _hasDocumentHighlightProvider: IContextKey<boolean>;
	private readonly _hasDocumentSymbolProvider: IContextKey<boolean>;
	private readonly _hasReferenceProvider: IContextKey<boolean>;
	private readonly _hasRenameProvider: IContextKey<boolean>;
	private readonly _hasDocumentFormattingProvider: IContextKey<boolean>;
	private readonly _hasDocumentSelectionFormattingProvider: IContextKey<boolean>;
1664 1665
	private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;
	private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;
1666 1667
	private readonly _hasSignatureHelpProvider: IContextKey<boolean>;
	private readonly _isInWalkThrough: IContextKey<boolean>;
A
Alex Dima 已提交
1668 1669

	constructor(
1670 1671
		private readonly _editor: CodeEditorWidget,
		private readonly _contextKeyService: IContextKeyService
A
Alex Dima 已提交
1672 1673 1674
	) {
		super();

1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
		this._langId = EditorContextKeys.languageId.bindTo(_contextKeyService);
		this._hasCompletionItemProvider = EditorContextKeys.hasCompletionItemProvider.bindTo(_contextKeyService);
		this._hasCodeActionsProvider = EditorContextKeys.hasCodeActionsProvider.bindTo(_contextKeyService);
		this._hasCodeLensProvider = EditorContextKeys.hasCodeLensProvider.bindTo(_contextKeyService);
		this._hasDefinitionProvider = EditorContextKeys.hasDefinitionProvider.bindTo(_contextKeyService);
		this._hasDeclarationProvider = EditorContextKeys.hasDeclarationProvider.bindTo(_contextKeyService);
		this._hasImplementationProvider = EditorContextKeys.hasImplementationProvider.bindTo(_contextKeyService);
		this._hasTypeDefinitionProvider = EditorContextKeys.hasTypeDefinitionProvider.bindTo(_contextKeyService);
		this._hasHoverProvider = EditorContextKeys.hasHoverProvider.bindTo(_contextKeyService);
		this._hasDocumentHighlightProvider = EditorContextKeys.hasDocumentHighlightProvider.bindTo(_contextKeyService);
		this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(_contextKeyService);
		this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(_contextKeyService);
		this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(_contextKeyService);
		this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(_contextKeyService);
		this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(_contextKeyService);
		this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
		this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);
		this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
		this._isInWalkThrough = EditorContextKeys.isInEmbeddedEditor.bindTo(_contextKeyService);
A
Alex Dima 已提交
1694 1695 1696 1697

		const update = () => this._update();

		// update when model/mode changes
1698 1699
		this._register(_editor.onDidChangeModel(update));
		this._register(_editor.onDidChangeModelLanguage(update));
A
Alex Dima 已提交
1700 1701

		// update when registries change
1702
		this._register(modes.CompletionProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1703 1704 1705
		this._register(modes.CodeActionProviderRegistry.onDidChange(update));
		this._register(modes.CodeLensProviderRegistry.onDidChange(update));
		this._register(modes.DefinitionProviderRegistry.onDidChange(update));
1706
		this._register(modes.DeclarationProviderRegistry.onDidChange(update));
A
Alex Dima 已提交
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
		this._register(modes.ImplementationProviderRegistry.onDidChange(update));
		this._register(modes.TypeDefinitionProviderRegistry.onDidChange(update));
		this._register(modes.HoverProviderRegistry.onDidChange(update));
		this._register(modes.DocumentHighlightProviderRegistry.onDidChange(update));
		this._register(modes.DocumentSymbolProviderRegistry.onDidChange(update));
		this._register(modes.ReferenceProviderRegistry.onDidChange(update));
		this._register(modes.RenameProviderRegistry.onDidChange(update));
		this._register(modes.DocumentFormattingEditProviderRegistry.onDidChange(update));
		this._register(modes.DocumentRangeFormattingEditProviderRegistry.onDidChange(update));
		this._register(modes.SignatureHelpProviderRegistry.onDidChange(update));

		update();
	}

	dispose() {
		super.dispose();
	}

	reset() {
1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
		this._contextKeyService.bufferChangeEvents(() => {
			this._langId.reset();
			this._hasCompletionItemProvider.reset();
			this._hasCodeActionsProvider.reset();
			this._hasCodeLensProvider.reset();
			this._hasDefinitionProvider.reset();
			this._hasDeclarationProvider.reset();
			this._hasImplementationProvider.reset();
			this._hasTypeDefinitionProvider.reset();
			this._hasHoverProvider.reset();
			this._hasDocumentHighlightProvider.reset();
			this._hasDocumentSymbolProvider.reset();
			this._hasReferenceProvider.reset();
			this._hasRenameProvider.reset();
			this._hasDocumentFormattingProvider.reset();
			this._hasDocumentSelectionFormattingProvider.reset();
			this._hasSignatureHelpProvider.reset();
			this._isInWalkThrough.reset();
		});
A
Alex Dima 已提交
1745 1746 1747 1748 1749 1750 1751 1752
	}

	private _update() {
		const model = this._editor.getModel();
		if (!model) {
			this.reset();
			return;
		}
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769
		this._contextKeyService.bufferChangeEvents(() => {
			this._langId.set(model.getLanguageIdentifier().language);
			this._hasCompletionItemProvider.set(modes.CompletionProviderRegistry.has(model));
			this._hasCodeActionsProvider.set(modes.CodeActionProviderRegistry.has(model));
			this._hasCodeLensProvider.set(modes.CodeLensProviderRegistry.has(model));
			this._hasDefinitionProvider.set(modes.DefinitionProviderRegistry.has(model));
			this._hasDeclarationProvider.set(modes.DeclarationProviderRegistry.has(model));
			this._hasImplementationProvider.set(modes.ImplementationProviderRegistry.has(model));
			this._hasTypeDefinitionProvider.set(modes.TypeDefinitionProviderRegistry.has(model));
			this._hasHoverProvider.set(modes.HoverProviderRegistry.has(model));
			this._hasDocumentHighlightProvider.set(modes.DocumentHighlightProviderRegistry.has(model));
			this._hasDocumentSymbolProvider.set(modes.DocumentSymbolProviderRegistry.has(model));
			this._hasReferenceProvider.set(modes.ReferenceProviderRegistry.has(model));
			this._hasRenameProvider.set(modes.RenameProviderRegistry.has(model));
			this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model));
			this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model));
			this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model));
J
Johannes Rieken 已提交
1770
			this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length + modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
1771 1772 1773
			this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
			this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
		});
1774
	}
E
Erich Gamma 已提交
1775 1776
}

1777 1778
class CodeEditorWidgetFocusTracker extends Disposable {

1779
	private _hasFocus: boolean;
1780
	private readonly _domFocusTracker: dom.IFocusTracker;
1781

M
Matt Bierner 已提交
1782
	private readonly _onChange: Emitter<void> = this._register(new Emitter<void>());
1783
	public readonly onChange: Event<void> = this._onChange.event;
1784

J
Johannes Rieken 已提交
1785
	constructor(domElement: HTMLElement) {
1786 1787
		super();

1788 1789
		this._hasFocus = false;
		this._domFocusTracker = this._register(dom.trackFocus(domElement));
1790

1791
		this._register(this._domFocusTracker.onDidFocus(() => {
1792
			this._hasFocus = true;
R
Rob Lourens 已提交
1793
			this._onChange.fire(undefined);
1794 1795
		}));
		this._register(this._domFocusTracker.onDidBlur(() => {
1796
			this._hasFocus = false;
R
Rob Lourens 已提交
1797
			this._onChange.fire(undefined);
1798
		}));
1799 1800 1801
	}

	public hasFocus(): boolean {
1802
		return this._hasFocus;
1803 1804
	}
}
1805

1806
const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' enable-background='new 0 0 6 3' height='3' width='6'><g fill='`);
1807
const squigglyEnd = encodeURIComponent(`'><polygon points='5.5,0 2.5,3 1.1,3 4.1,0'/><polygon points='4,0 6,2 6,0.6 5.4,0'/><polygon points='0,2 1,3 2.4,3 0,0.6'/></g></svg>`);
1808

1809 1810 1811
function getSquigglySVGData(color: Color) {
	return squigglyStart + encodeURIComponent(color.toString()) + squigglyEnd;
}
1812

1813 1814 1815 1816 1817 1818 1819
const dotdotdotStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" height="3" width="12"><g fill="`);
const dotdotdotEnd = encodeURIComponent(`"><circle cx="1" cy="1" r="1"/><circle cx="5" cy="1" r="1"/><circle cx="9" cy="1" r="1"/></g></svg>`);

function getDotDotDotSVGData(color: Color) {
	return dotdotdotStart + encodeURIComponent(color.toString()) + dotdotdotEnd;
}

1820
registerThemingParticipant((theme, collector) => {
M
Matt Bierner 已提交
1821
	const errorBorderColor = theme.getColor(editorErrorBorder);
1822
	if (errorBorderColor) {
1823
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { border-bottom: 4px double ${errorBorderColor}; }`);
1824
	}
M
Matt Bierner 已提交
1825
	const errorForeground = theme.getColor(editorErrorForeground);
1826
	if (errorForeground) {
1827
		collector.addRule(`.monaco-editor .${ClassName.EditorErrorDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(errorForeground)}") repeat-x bottom left; }`);
1828 1829
	}

M
Matt Bierner 已提交
1830
	const warningBorderColor = theme.getColor(editorWarningBorder);
1831
	if (warningBorderColor) {
1832
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { border-bottom: 4px double ${warningBorderColor}; }`);
1833
	}
M
Matt Bierner 已提交
1834
	const warningForeground = theme.getColor(editorWarningForeground);
1835
	if (warningForeground) {
1836
		collector.addRule(`.monaco-editor .${ClassName.EditorWarningDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(warningForeground)}") repeat-x bottom left; }`);
1837 1838
	}

M
Matt Bierner 已提交
1839
	const infoBorderColor = theme.getColor(editorInfoBorder);
1840 1841
	if (infoBorderColor) {
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { border-bottom: 4px double ${infoBorderColor}; }`);
1842
	}
M
Matt Bierner 已提交
1843
	const infoForeground = theme.getColor(editorInfoForeground);
1844
	if (infoForeground) {
1845
		collector.addRule(`.monaco-editor .${ClassName.EditorInfoDecoration} { background: url("data:image/svg+xml,${getSquigglySVGData(infoForeground)}") repeat-x bottom left; }`);
1846
	}
1847

M
Matt Bierner 已提交
1848
	const hintBorderColor = theme.getColor(editorHintBorder);
1849
	if (hintBorderColor) {
1850
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { border-bottom: 2px dotted ${hintBorderColor}; }`);
1851
	}
M
Matt Bierner 已提交
1852
	const hintForeground = theme.getColor(editorHintForeground);
1853
	if (hintForeground) {
1854
		collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`);
1855
	}
1856

1857
	const unnecessaryForeground = theme.getColor(editorUnnecessaryCodeOpacity);
1858
	if (unnecessaryForeground) {
1859
		collector.addRule(`.${SHOW_UNUSED_ENABLED_CLASS} .monaco-editor .${ClassName.EditorUnnecessaryInlineDecoration} { opacity: ${unnecessaryForeground.rgba.a}; }`);
1860 1861 1862 1863 1864
	}

	const unnecessaryBorder = theme.getColor(editorUnnecessaryCodeBorder);
	if (unnecessaryBorder) {
		collector.addRule(`.${SHOW_UNUSED_ENABLED_CLASS} .monaco-editor .${ClassName.EditorUnnecessaryDecoration} { border-bottom: 2px dashed ${unnecessaryBorder}; }`);
1865
	}
K
Kamran Ayub 已提交
1866

1867 1868
	const deprecatedForeground = theme.getColor(editorForeground) || 'inherit';
	collector.addRule(`.monaco-editor .${ClassName.EditorDeprecatedInlineDecoration} { text-decoration: line-through; text-decoration-color: ${deprecatedForeground}}`);
1869
});