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

A
Alex Dima 已提交
7
import {onUnexpectedError} from 'vs/base/common/errors';
A
Alex Dima 已提交
8
import {EventEmitter, EmitterEvent, IEventEmitter} from 'vs/base/common/eventEmitter';
J
Joao Moreno 已提交
9
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
A
Alex Dima 已提交
10 11 12
import * as timer from 'vs/base/common/timer';
import * as browser from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
A
Alex Dima 已提交
13
import {StyleMutator} from 'vs/base/browser/styleMutator';
A
Alex Dima 已提交
14
import {IContextKey, IContextKeyService} from 'vs/platform/contextkey/common/contextkey';
15
import {ICommandService} from 'vs/platform/commands/common/commands';
A
Alex Dima 已提交
16 17
import {Range} from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
E
Erich Gamma 已提交
18
import {ViewEventHandler} from 'vs/editor/common/viewModel/viewEventHandler';
A
Alex Dima 已提交
19
import {Configuration} from 'vs/editor/browser/config/configuration';
20
import {KeyboardHandler, IKeyboardHandlerHelper} from 'vs/editor/browser/controller/keyboardHandler';
E
Erich Gamma 已提交
21
import {PointerHandler} from 'vs/editor/browser/controller/pointerHandler';
A
Alex Dima 已提交
22
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
A
Alex Dima 已提交
23
import {ViewController, TriggerCursorHandler} from 'vs/editor/browser/view/viewController';
A
Alex Dima 已提交
24
import {ViewEventDispatcher} from 'vs/editor/browser/view/viewEventDispatcher';
E
Erich Gamma 已提交
25
import {ContentViewOverlays, MarginViewOverlays} from 'vs/editor/browser/view/viewOverlays';
A
Alex Dima 已提交
26
import {LayoutProvider} from 'vs/editor/browser/viewLayout/layoutProvider';
E
Erich Gamma 已提交
27 28 29 30 31
import {ViewContentWidgets} from 'vs/editor/browser/viewParts/contentWidgets/contentWidgets';
import {CurrentLineHighlightOverlay} from 'vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight';
import {DecorationsOverlay} from 'vs/editor/browser/viewParts/decorations/decorations';
import {GlyphMarginOverlay} from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
import {LineNumbersOverlay} from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
32
import {IndentGuidesOverlay} from 'vs/editor/browser/viewParts/indentGuides/indentGuides';
A
Alex Dima 已提交
33 34 35 36 37
import {ViewLines} from 'vs/editor/browser/viewParts/lines/viewLines';
import {LinesDecorationsOverlay} from 'vs/editor/browser/viewParts/linesDecorations/linesDecorations';
import {ViewOverlayWidgets} from 'vs/editor/browser/viewParts/overlayWidgets/overlayWidgets';
import {DecorationsOverviewRuler} from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler';
import {OverviewRuler} from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler';
38
import {Rulers} from 'vs/editor/browser/viewParts/rulers/rulers';
A
Alex Dima 已提交
39 40 41 42
import {ScrollDecorationViewPart} from 'vs/editor/browser/viewParts/scrollDecoration/scrollDecoration';
import {SelectionsOverlay} from 'vs/editor/browser/viewParts/selections/selections';
import {ViewCursors} from 'vs/editor/browser/viewParts/viewCursors/viewCursors';
import {ViewZones} from 'vs/editor/browser/viewParts/viewZones/viewZones';
A
Alex Dima 已提交
43
import {ViewPart} from 'vs/editor/browser/view/viewPart';
A
Alex Dima 已提交
44
import {ViewContext, IViewEventHandler} from 'vs/editor/common/view/viewContext';
45 46 47 48
import {IViewModel} from 'vs/editor/common/viewModel/viewModel';
import {ViewLinesViewportData} from 'vs/editor/common/viewLayout/viewLinesViewportData';
import {IRenderingContext} from 'vs/editor/common/view/renderingContext';
import {IPointerHandlerHelper} from 'vs/editor/browser/controller/mouseHandler';
E
Erich Gamma 已提交
49

A
Alex Dima 已提交
50 51
import EditorContextKeys = editorCommon.EditorContextKeys;

A
Alex Dima 已提交
52
export class View extends ViewEventHandler implements editorBrowser.IView, IDisposable {
E
Erich Gamma 已提交
53 54 55

	private eventDispatcher:ViewEventDispatcher;

A
Alex Dima 已提交
56
	private listenersToRemove:IDisposable[];
A
Alex Dima 已提交
57
	private listenersToDispose:IDisposable[];
E
Erich Gamma 已提交
58 59

	private layoutProvider: LayoutProvider;
60
	public _context: ViewContext;
E
Erich Gamma 已提交
61 62 63 64 65 66 67 68

	// The view lines
	private viewLines: ViewLines;

	// These are parts, but we must do some API related calls on them, so we keep a reference
	private viewZones: ViewZones;
	private contentWidgets: ViewContentWidgets;
	private overlayWidgets: ViewOverlayWidgets;
A
Alex Dima 已提交
69
	private viewParts: ViewPart[];
E
Erich Gamma 已提交
70 71 72 73

	private keyboardHandler: KeyboardHandler;
	private pointerHandler: PointerHandler;

A
Alex Dima 已提交
74
	private outgoingEventBus: EventEmitter;
E
Erich Gamma 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88

	// Dom nodes
	private linesContent: HTMLElement;
	public domNode: HTMLElement;
	public textArea: HTMLTextAreaElement;
	private textAreaCover: HTMLElement;
	private linesContentContainer: HTMLElement;
	private overflowGuardContainer: HTMLElement;

	// Actual mutable state
	private hasFocus:boolean;
	private _isDisposed: boolean;

	private handleAccumulatedModelEventsTimeout:number;
A
Alex Dima 已提交
89
	private accumulatedModelEvents: EmitterEvent[];
A
Alex Dima 已提交
90
	private _renderAnimationFrame: IDisposable;
E
Erich Gamma 已提交
91

A
Alex Dima 已提交
92
	private _editorTextFocusContextKey: IContextKey<boolean>;
E
Erich Gamma 已提交
93

A
Alex Dima 已提交
94
	constructor(
95
		contextKeyService: IContextKeyService,
96
		commandService: ICommandService,
A
Alex Dima 已提交
97 98 99 100
		configuration:Configuration,
		model:IViewModel,
		triggerCursorHandler:TriggerCursorHandler
	) {
E
Erich Gamma 已提交
101 102 103
		super();
		this._isDisposed = false;
		this._renderAnimationFrame = null;
A
Alex Dima 已提交
104
		this.outgoingEventBus = new EventEmitter();
E
Erich Gamma 已提交
105

106
		var viewController = new ViewController(model, triggerCursorHandler, this.outgoingEventBus, commandService);
E
Erich Gamma 已提交
107 108 109 110 111 112 113 114 115

		this.listenersToRemove = [];
		this.listenersToDispose = [];

		// The event dispatcher will always go through _renderOnce before dispatching any events
		this.eventDispatcher = new ViewEventDispatcher((callback:()=>void) => this._renderOnce(callback));

		// These two dom nodes must be constructed up front, since references are needed in the layout provider (scrolling & co.)
		this.linesContent = document.createElement('div');
A
Alex Dima 已提交
116
		this.linesContent.className = editorBrowser.ClassNames.LINES_CONTENT + ' monaco-editor-background';
E
Erich Gamma 已提交
117
		this.domNode = document.createElement('div');
118
		this.domNode.className = configuration.editor.viewInfo.editorClassName;
E
Erich Gamma 已提交
119 120

		this.overflowGuardContainer = document.createElement('div');
A
Alex Dima 已提交
121
		this.overflowGuardContainer.className = editorBrowser.ClassNames.OVERFLOW_GUARD;
E
Erich Gamma 已提交
122 123 124 125 126 127 128 129 130

		// The layout provider has such responsibilities as:
		// - scrolling (i.e. viewport / full size) & co.
		// - whitespaces (a.k.a. view zones) management & co.
		// - line heights updating & co.
		this.layoutProvider = new LayoutProvider(configuration, model, this.eventDispatcher, this.linesContent, this.domNode, this.overflowGuardContainer);
		this.eventDispatcher.addEventHandler(this.layoutProvider);

		// The view context is passed on to most classes (basically to reduce param. counts in ctors)
131 132
		this._context = new ViewContext(
				configuration, model, this.eventDispatcher,
A
Alex Dima 已提交
133 134
				(eventHandler:IViewEventHandler) => this.eventDispatcher.addEventHandler(eventHandler),
				(eventHandler:IViewEventHandler) => this.eventDispatcher.removeEventHandler(eventHandler)
E
Erich Gamma 已提交
135 136
		);

137
		this.createTextArea(contextKeyService);
E
Erich Gamma 已提交
138 139 140
		this.createViewParts();

		// Keyboard handler
141
		this.keyboardHandler = new KeyboardHandler(this._context, viewController, this.createKeyboardHandlerHelper());
E
Erich Gamma 已提交
142 143

		// Pointer handler
144
		this.pointerHandler = new PointerHandler(this._context, viewController, this.createPointerHandlerHelper());
E
Erich Gamma 已提交
145 146 147 148 149 150 151 152 153 154

		this.hasFocus = false;
		this.codeEditorHelper = null;

		this.eventDispatcher.addEventHandler(this);

		// The view lines rendering calls model.getLineTokens() that might emit events that its tokens have changed.
		// This delayed processing of incoming model events acts as a guard against undesired/unexpected recursion.
		this.handleAccumulatedModelEventsTimeout = -1;
		this.accumulatedModelEvents = [];
A
Alex Dima 已提交
155
		this.listenersToRemove.push(model.addBulkListener2((events:EmitterEvent[]) => {
E
Erich Gamma 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
			this.accumulatedModelEvents = this.accumulatedModelEvents.concat(events);
			if (this.handleAccumulatedModelEventsTimeout === -1) {
				this.handleAccumulatedModelEventsTimeout = setTimeout(() => {
					this.handleAccumulatedModelEventsTimeout = -1;
					this._flushAnyAccumulatedEvents();
				});
			}
		}));
	}

	private _flushAnyAccumulatedEvents(): void {
		var toEmit = this.accumulatedModelEvents;
		this.accumulatedModelEvents = [];
		if (toEmit.length > 0) {
			this.eventDispatcher.emitMany(toEmit);
		}
	}

174
	private createTextArea(contextKeyService: IContextKeyService): void {
E
Erich Gamma 已提交
175 176
		// Text Area (The focus will always be in the textarea when the cursor is blinking)
		this.textArea = <HTMLTextAreaElement>document.createElement('textarea');
177
		this._editorTextFocusContextKey = EditorContextKeys.TextFocus.bindTo(contextKeyService);
A
Alex Dima 已提交
178
		this.textArea.className = editorBrowser.ClassNames.TEXTAREA;
E
Erich Gamma 已提交
179 180 181 182
		this.textArea.setAttribute('wrap', 'off');
		this.textArea.setAttribute('autocorrect', 'off');
		this.textArea.setAttribute('autocapitalize', 'off');
		this.textArea.setAttribute('spellcheck', 'false');
183
		this.textArea.setAttribute('aria-label', this._context.configuration.editor.viewInfo.ariaLabel);
E
Erich Gamma 已提交
184 185
		this.textArea.setAttribute('role', 'textbox');
		this.textArea.setAttribute('aria-multiline', 'true');
A
Alex Dima 已提交
186 187 188
		this.textArea.setAttribute('aria-haspopup', 'false');
		this.textArea.setAttribute('aria-autocomplete', 'both');

A
Alex Dima 已提交
189 190
		StyleMutator.setTop(this.textArea, 0);
		StyleMutator.setLeft(this.textArea, 0);
E
Erich Gamma 已提交
191

A
Alex Dima 已提交
192 193
		this.listenersToDispose.push(dom.addDisposableListener(this.textArea, 'focus', () => this._setHasFocus(true)));
		this.listenersToDispose.push(dom.addDisposableListener(this.textArea, 'blur', () => this._setHasFocus(false)));
E
Erich Gamma 已提交
194 195 196 197 198

		// On top of the text area, we position a dom node to cover it up
		// (there have been reports of tiny blinking cursors)
		// (in WebKit the textarea is 1px by 1px because it cannot handle input to a 0x0 textarea)
		this.textAreaCover = document.createElement('div');
199
		if (this._context.configuration.editor.viewInfo.glyphMargin) {
A
Alex Dima 已提交
200
			this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.GLYPH_MARGIN + ' ' + editorBrowser.ClassNames.TEXTAREA_COVER;
E
Erich Gamma 已提交
201
		} else {
202
			if (this._context.configuration.editor.viewInfo.lineNumbers) {
A
Alex Dima 已提交
203
				this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.LINE_NUMBERS + ' ' + editorBrowser.ClassNames.TEXTAREA_COVER;
E
Erich Gamma 已提交
204
			} else {
A
Alex Dima 已提交
205
				this.textAreaCover.className = 'monaco-editor-background ' + editorBrowser.ClassNames.TEXTAREA_COVER;
E
Erich Gamma 已提交
206 207 208
			}
		}
		this.textAreaCover.style.position = 'absolute';
A
Alex Dima 已提交
209 210 211 212
		StyleMutator.setWidth(this.textAreaCover, 1);
		StyleMutator.setHeight(this.textAreaCover, 1);
		StyleMutator.setTop(this.textAreaCover, 0);
		StyleMutator.setLeft(this.textAreaCover, 0);
E
Erich Gamma 已提交
213 214 215 216 217 218
	}

	private createViewParts(): void {
		this.viewParts = [];

		// View Lines
219
		this.viewLines = new ViewLines(this._context, this.layoutProvider);
E
Erich Gamma 已提交
220 221

		// View Zones
222
		this.viewZones = new ViewZones(this._context, this.layoutProvider);
E
Erich Gamma 已提交
223 224 225 226
		this.viewParts.push(this.viewZones);

		// Decorations overview ruler
		var decorationsOverviewRuler = new DecorationsOverviewRuler(
227
				this._context, this.layoutProvider.getScrollHeight(),
E
Erich Gamma 已提交
228 229 230 231 232
				(lineNumber:number) => this.layoutProvider.getVerticalOffsetForLineNumber(lineNumber)
		);
		this.viewParts.push(decorationsOverviewRuler);


233
		var scrollDecoration = new ScrollDecorationViewPart(this._context);
E
Erich Gamma 已提交
234 235
		this.viewParts.push(scrollDecoration);

236
		var contentViewOverlays = new ContentViewOverlays(this._context, this.layoutProvider);
E
Erich Gamma 已提交
237
		this.viewParts.push(contentViewOverlays);
238 239 240
		contentViewOverlays.addDynamicOverlay(new CurrentLineHighlightOverlay(this._context, this.layoutProvider));
		contentViewOverlays.addDynamicOverlay(new SelectionsOverlay(this._context));
		contentViewOverlays.addDynamicOverlay(new DecorationsOverlay(this._context));
241
		contentViewOverlays.addDynamicOverlay(new IndentGuidesOverlay(this._context));
E
Erich Gamma 已提交
242

243
		var marginViewOverlays = new MarginViewOverlays(this._context, this.layoutProvider);
E
Erich Gamma 已提交
244
		this.viewParts.push(marginViewOverlays);
245 246 247
		marginViewOverlays.addDynamicOverlay(new GlyphMarginOverlay(this._context));
		marginViewOverlays.addDynamicOverlay(new LinesDecorationsOverlay(this._context));
		marginViewOverlays.addDynamicOverlay(new LineNumbersOverlay(this._context));
E
Erich Gamma 已提交
248 249 250


		// Content widgets
251
		this.contentWidgets = new ViewContentWidgets(this._context, this.domNode);
E
Erich Gamma 已提交
252 253
		this.viewParts.push(this.contentWidgets);

254
		var viewCursors = new ViewCursors(this._context);
E
Erich Gamma 已提交
255 256 257
		this.viewParts.push(viewCursors);

		// Overlay widgets
258
		this.overlayWidgets = new ViewOverlayWidgets(this._context);
E
Erich Gamma 已提交
259 260
		this.viewParts.push(this.overlayWidgets);

261
		var rulers = new Rulers(this._context, this.layoutProvider);
262 263
		this.viewParts.push(rulers);

E
Erich Gamma 已提交
264 265 266 267 268 269 270 271 272 273 274
		// -------------- Wire dom nodes up

		this.linesContentContainer = this.layoutProvider.getScrollbarContainerDomNode();
		this.linesContentContainer.style.position = 'absolute';

		if (decorationsOverviewRuler) {
			var overviewRulerData = this.layoutProvider.getOverviewRulerInsertData();
			overviewRulerData.parent.insertBefore(decorationsOverviewRuler.getDomNode(), overviewRulerData.insertBefore);
		}

		this.linesContent.appendChild(contentViewOverlays.getDomNode());
275
		this.linesContent.appendChild(rulers.domNode);
E
Erich Gamma 已提交
276
		this.linesContent.appendChild(this.viewZones.domNode);
A
Alex Dima 已提交
277
		this.linesContent.appendChild(this.viewLines.getDomNode());
E
Erich Gamma 已提交
278 279 280 281 282 283 284 285 286
		this.linesContent.appendChild(this.contentWidgets.domNode);
		this.linesContent.appendChild(viewCursors.getDomNode());
		this.overflowGuardContainer.appendChild(marginViewOverlays.getDomNode());
		this.overflowGuardContainer.appendChild(this.linesContentContainer);
		this.overflowGuardContainer.appendChild(scrollDecoration.getDomNode());
		this.overflowGuardContainer.appendChild(this.overlayWidgets.domNode);
		this.overflowGuardContainer.appendChild(this.textArea);
		this.overflowGuardContainer.appendChild(this.textAreaCover);
		this.domNode.appendChild(this.overflowGuardContainer);
287
		this.domNode.appendChild(this.contentWidgets.overflowingContentWidgetsDomNode);
E
Erich Gamma 已提交
288 289 290 291 292 293 294
	}

	private _flushAccumulatedAndRenderNow(): void {
		this._flushAnyAccumulatedEvents();
		this._renderNow();
	}

295
	private createPointerHandlerHelper(): IPointerHandlerHelper {
E
Erich Gamma 已提交
296 297 298 299 300 301 302 303 304 305 306
		return {
			viewDomNode: this.domNode,
			linesContentDomNode: this.linesContent,

			focusTextArea: () => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.focusTextArea: View is disposed');
				}
				this.focus();
			},

307 308 309 310
			isDirty: (): boolean => {
				return (this.accumulatedModelEvents.length > 0);
			},

E
Erich Gamma 已提交
311 312 313 314 315 316
			getScrollLeft: () => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getScrollLeft: View is disposed');
				}
				return this.layoutProvider.getScrollLeft();
			},
317 318 319 320 321 322 323 324
			getScrollTop: () => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getScrollTop: View is disposed');
				}
				return this.layoutProvider.getScrollTop();
			},

			setScrollPosition: (position:editorCommon.INewScrollPosition) => {
E
Erich Gamma 已提交
325
				if (this._isDisposed) {
326
					throw new Error('ViewImpl.pointerHandler.setScrollPosition: View is disposed');
E
Erich Gamma 已提交
327
				}
328
				this.layoutProvider.setScrollPosition(position);
E
Erich Gamma 已提交
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
			},

			isAfterLines: (verticalOffset: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.isAfterLines: View is disposed');
				}
				return this.layoutProvider.isAfterLines(verticalOffset);
			},
			getLineNumberAtVerticalOffset: (verticalOffset: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getLineNumberAtVerticalOffset: View is disposed');
				}
				return this.layoutProvider.getLineNumberAtVerticalOffset(verticalOffset);
			},
			getVerticalOffsetForLineNumber: (lineNumber: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getVerticalOffsetForLineNumber: View is disposed');
				}
				return this.layoutProvider.getVerticalOffsetForLineNumber(lineNumber);
			},
			getWhitespaceAtVerticalOffset: (verticalOffset: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getWhitespaceAtVerticalOffset: View is disposed');
				}
				return this.layoutProvider.getWhitespaceAtVerticalOffset(verticalOffset);
			},
			shouldSuppressMouseDownOnViewZone: (viewZoneId: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.shouldSuppressMouseDownOnViewZone: View is disposed');
				}
				return this.viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId);
			},
361 362 363 364 365 366
			shouldSuppressMouseDownOnWidget: (widgetId: string) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.shouldSuppressMouseDownOnWidget: View is disposed');
				}
				return this.contentWidgets.shouldSuppressMouseDownOnWidget(widgetId);
			},
E
Erich Gamma 已提交
367 368 369 370 371 372 373 374 375 376 377 378 379
			getPositionFromDOMInfo: (spanNode: HTMLElement, offset: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getPositionFromDOMInfo: View is disposed');
				}
				this._flushAccumulatedAndRenderNow();
				return this.viewLines.getPositionFromDOMInfo(spanNode, offset);
			},

			visibleRangeForPosition2: (lineNumber: number, column: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.visibleRangeForPosition2: View is disposed');
				}
				this._flushAccumulatedAndRenderNow();
A
Alex Dima 已提交
380
				var visibleRanges = this.viewLines.visibleRangesForRange2(new Range(lineNumber, column, lineNumber, column), 0);
E
Erich Gamma 已提交
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
				if (!visibleRanges) {
					return null;
				}
				return visibleRanges[0];
			},

			getLineWidth: (lineNumber: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.pointerHandler.getLineWidth: View is disposed');
				}
				this._flushAccumulatedAndRenderNow();
				return this.viewLines.getLineWidth(lineNumber);
			}
		};
	}

397
	private createKeyboardHandlerHelper(): IKeyboardHandlerHelper {
E
Erich Gamma 已提交
398 399 400 401 402 403 404 405 406
		return {
			viewDomNode: this.domNode,
			textArea: this.textArea,
			visibleRangeForPositionRelativeToEditor: (lineNumber: number, column: number) => {
				if (this._isDisposed) {
					throw new Error('ViewImpl.keyboardHandler.visibleRangeForPositionRelativeToEditor: View is disposed');
				}
				this._flushAccumulatedAndRenderNow();
				var linesViewPortData = this.layoutProvider.getLinesViewportData();
A
Alex Dima 已提交
407
				var visibleRanges = this.viewLines.visibleRangesForRange2(new Range(lineNumber, column, lineNumber, column), linesViewPortData.visibleRangesDeltaTop);
E
Erich Gamma 已提交
408 409 410 411
				if (!visibleRanges) {
					return null;
				}
				return visibleRanges[0];
412 413 414
			},
			flushAnyAccumulatedEvents: () => {
				this._flushAnyAccumulatedEvents();
E
Erich Gamma 已提交
415 416 417 418
			}
		};
	}

A
Alex Dima 已提交
419 420 421 422 423 424 425 426 427 428 429 430 431 432
	public setAriaActiveDescendant(id:string): void {
		if (id) {
			this.textArea.setAttribute('role', 'combobox');
			if (this.textArea.getAttribute('aria-activedescendant') !== id) {
				this.textArea.setAttribute('aria-haspopup', 'true');
				this.textArea.setAttribute('aria-activedescendant', id);
			}
		} else {
			this.textArea.setAttribute('role', 'textbox');
			this.textArea.removeAttribute('aria-activedescendant');
			this.textArea.removeAttribute('aria-haspopup');
		}
	}

E
Erich Gamma 已提交
433 434
	// --- begin event handlers

435
	public onLayoutChanged(layoutInfo:editorCommon.EditorLayoutInfo): boolean {
A
Alex Dima 已提交
436
		if (browser.isChrome) {
A
tslint  
Alex Dima 已提交
437
			/* tslint:disable:no-unused-variable */
E
Erich Gamma 已提交
438 439 440
			// Access overflowGuardContainer.clientWidth to prevent relayouting bug in Chrome
			// See Bug 19676: Editor misses a layout event
			var clientWidth = this.overflowGuardContainer.clientWidth + 'px';
A
tslint  
Alex Dima 已提交
441
			/* tslint:enable:no-unused-variable */
E
Erich Gamma 已提交
442
		}
A
Alex Dima 已提交
443 444
		StyleMutator.setWidth(this.domNode, layoutInfo.width);
		StyleMutator.setHeight(this.domNode, layoutInfo.height);
E
Erich Gamma 已提交
445

A
Alex Dima 已提交
446 447
		StyleMutator.setWidth(this.overflowGuardContainer, layoutInfo.width);
		StyleMutator.setHeight(this.overflowGuardContainer, layoutInfo.height);
E
Erich Gamma 已提交
448

A
Alex Dima 已提交
449 450
		StyleMutator.setWidth(this.linesContent, 1000000);
		StyleMutator.setHeight(this.linesContent, 1000000);
E
Erich Gamma 已提交
451

A
Alex Dima 已提交
452 453 454
		StyleMutator.setLeft(this.linesContentContainer, layoutInfo.contentLeft);
		StyleMutator.setWidth(this.linesContentContainer, layoutInfo.contentWidth);
		StyleMutator.setHeight(this.linesContentContainer, layoutInfo.contentHeight);
E
Erich Gamma 已提交
455

A
Alex Dima 已提交
456
		this.outgoingEventBus.emit(editorCommon.EventType.ViewLayoutChanged, layoutInfo);
E
Erich Gamma 已提交
457 458
		return false;
	}
A
Alex Dima 已提交
459
	public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean {
460 461
		if (e.viewInfo.editorClassName) {
			this.domNode.className = this._context.configuration.editor.viewInfo.editorClassName;
E
Erich Gamma 已提交
462
		}
463 464
		if (e.viewInfo.ariaLabel) {
			this.textArea.setAttribute('aria-label', this._context.configuration.editor.viewInfo.ariaLabel);
465
		}
E
Erich Gamma 已提交
466 467
		return false;
	}
A
Alex Dima 已提交
468
	public onScrollChanged(e:editorCommon.IScrollEvent): boolean {
A
Alex Dima 已提交
469
		this.outgoingEventBus.emit('scroll', e);
470
		return false;
E
Erich Gamma 已提交
471 472
	}
	public onViewFocusChanged(isFocused:boolean): boolean {
A
Alex Dima 已提交
473
		dom.toggleClass(this.domNode, 'focused', isFocused);
E
Erich Gamma 已提交
474 475
		if (isFocused) {
			this._editorTextFocusContextKey.set(true);
A
Alex Dima 已提交
476
			this.outgoingEventBus.emit(editorCommon.EventType.ViewFocusGained, {});
E
Erich Gamma 已提交
477 478
		} else {
			this._editorTextFocusContextKey.reset();
A
Alex Dima 已提交
479
			this.outgoingEventBus.emit(editorCommon.EventType.ViewFocusLost, {});
E
Erich Gamma 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
		}
		return false;
	}
	// --- end event handlers

	public dispose(): void {
		this._isDisposed = true;
		if (this.handleAccumulatedModelEventsTimeout !== -1) {
			clearTimeout(this.handleAccumulatedModelEventsTimeout);
			this.handleAccumulatedModelEventsTimeout = -1;
		}
		if (this._renderAnimationFrame !== null) {
			this._renderAnimationFrame.dispose();
			this._renderAnimationFrame = null;
		}
		this.accumulatedModelEvents = [];

		this.eventDispatcher.removeEventHandler(this);
		this.outgoingEventBus.dispose();
A
Alex Dima 已提交
499
		this.listenersToRemove = dispose(this.listenersToRemove);
J
Joao Moreno 已提交
500
		this.listenersToDispose = dispose(this.listenersToDispose);
E
Erich Gamma 已提交
501 502 503 504 505 506 507 508 509 510 511 512 513

		this.keyboardHandler.dispose();
		this.pointerHandler.dispose();

		this.viewLines.dispose();

		// Destroy IViewPart second
		for (var i = 0, len = this.viewParts.length; i < len; i++) {
			this.viewParts[i].dispose();
		}
		this.viewParts = [];

		this.layoutProvider.dispose();
514
		this._editorTextFocusContextKey.reset();
E
Erich Gamma 已提交
515 516 517 518
	}

	// --- begin Code Editor APIs

A
Alex Dima 已提交
519 520
	private codeEditorHelper:editorBrowser.ICodeEditorHelper;
	public getCodeEditorHelper(): editorBrowser.ICodeEditorHelper {
E
Erich Gamma 已提交
521 522
		if (!this.codeEditorHelper) {
			this.codeEditorHelper = {
523
				getScrollWidth: () => {
E
Erich Gamma 已提交
524
					if (this._isDisposed) {
525
						throw new Error('ViewImpl.codeEditorHelper.getScrollWidth: View is disposed');
E
Erich Gamma 已提交
526
					}
527
					return this.layoutProvider.getScrollWidth();
E
Erich Gamma 已提交
528 529 530 531 532 533 534
				},
				getScrollLeft: () => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.getScrollLeft: View is disposed');
					}
					return this.layoutProvider.getScrollLeft();
				},
535

E
Erich Gamma 已提交
536 537 538 539 540 541
				getScrollHeight: () => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.getScrollHeight: View is disposed');
					}
					return this.layoutProvider.getScrollHeight();
				},
542
				getScrollTop: () => {
E
Erich Gamma 已提交
543
					if (this._isDisposed) {
544
						throw new Error('ViewImpl.codeEditorHelper.getScrollTop: View is disposed');
E
Erich Gamma 已提交
545
					}
546
					return this.layoutProvider.getScrollTop();
E
Erich Gamma 已提交
547
				},
548 549 550 551 552 553 554 555

				setScrollPosition: (position:editorCommon.INewScrollPosition) => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.setScrollPosition: View is disposed');
					}
					this.layoutProvider.setScrollPosition(position);
				},

E
Erich Gamma 已提交
556 557 558 559
				getVerticalOffsetForPosition: (modelLineNumber:number, modelColumn:number) => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.getVerticalOffsetForPosition: View is disposed');
					}
560
					var modelPosition = this._context.model.validateModelPosition({
E
Erich Gamma 已提交
561 562 563
						lineNumber: modelLineNumber,
						column: modelColumn
					});
564
					var viewPosition = this._context.model.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column);
E
Erich Gamma 已提交
565 566 567 568 569 570 571 572 573 574 575 576
					return this.layoutProvider.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
				},
				delegateVerticalScrollbarMouseDown: (browserEvent: MouseEvent) => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.delegateVerticalScrollbarMouseDown: View is disposed');
					}
					this.layoutProvider.delegateVerticalScrollbarMouseDown(browserEvent);
				},
				getOffsetForColumn: (modelLineNumber: number, modelColumn: number) => {
					if (this._isDisposed) {
						throw new Error('ViewImpl.codeEditorHelper.getOffsetForColumn: View is disposed');
					}
577
					var modelPosition = this._context.model.validateModelPosition({
E
Erich Gamma 已提交
578 579 580
						lineNumber: modelLineNumber,
						column: modelColumn
					});
581
					var viewPosition = this._context.model.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column);
E
Erich Gamma 已提交
582
					this._flushAccumulatedAndRenderNow();
A
Alex Dima 已提交
583
					var visibleRanges = this.viewLines.visibleRangesForRange2(new Range(viewPosition.lineNumber, viewPosition.column, viewPosition.lineNumber, viewPosition.column), 0);
E
Erich Gamma 已提交
584 585 586 587 588 589 590 591 592 593
					if (!visibleRanges) {
						return -1;
					}
					return visibleRanges[0].left;
				}
			};
		}
		return this.codeEditorHelper;
	}

594
	public getCenteredRangeInViewport(): Range {
E
Erich Gamma 已提交
595 596 597 598
		if (this._isDisposed) {
			throw new Error('ViewImpl.getCenteredRangeInViewport: View is disposed');
		}
		var viewLineNumber = this.layoutProvider.getCenteredViewLineNumberInViewport();
599
		var viewModel = this._context.model;
E
Erich Gamma 已提交
600 601 602 603
		var currentCenteredViewRange = new Range(viewLineNumber, 1, viewLineNumber, viewModel.getLineMaxColumn(viewLineNumber));
		return viewModel.convertViewRangeToModelRange(currentCenteredViewRange);
	}

604
	public getCompletelyVisibleLinesRangeInViewport(): Range {
605
		if (this._isDisposed) {
606
			throw new Error('ViewImpl.getVisibleRangeInViewportExcludingPartialRenderedLines: View is disposed');
607
		}
608 609
		let completelyVisibleLinesRange = this.layoutProvider.getLinesViewportData().completelyVisibleLinesRange;
		return this._context.model.convertViewRangeToModelRange(completelyVisibleLinesRange);
610 611
	}

E
Erich Gamma 已提交
612 613 614 615
//	public getLineInfoProvider():view.ILineInfoProvider {
//		return this.viewLines;
//	}

A
Alex Dima 已提交
616
	public getInternalEventBus(): IEventEmitter {
E
Erich Gamma 已提交
617 618 619 620 621 622
		if (this._isDisposed) {
			throw new Error('ViewImpl.getInternalEventBus: View is disposed');
		}
		return this.outgoingEventBus;
	}

A
Alex Dima 已提交
623
	public saveState(): editorCommon.IViewState {
E
Erich Gamma 已提交
624 625 626 627 628 629
		if (this._isDisposed) {
			throw new Error('ViewImpl.saveState: View is disposed');
		}
		return this.layoutProvider.saveState();
	}

A
Alex Dima 已提交
630
	public restoreState(state: editorCommon.IViewState): void {
E
Erich Gamma 已提交
631 632 633 634 635 636 637 638 639 640 641
		if (this._isDisposed) {
			throw new Error('ViewImpl.restoreState: View is disposed');
		}
		this._flushAnyAccumulatedEvents();
		return this.layoutProvider.restoreState(state);
	}

	public focus(): void {
		if (this._isDisposed) {
			throw new Error('ViewImpl.focus: View is disposed');
		}
642
		this.keyboardHandler.focusTextArea();
E
Erich Gamma 已提交
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659

		// IE does not trigger the focus event immediately, so we must help it a little bit
		this._setHasFocus(true);
	}

	public isFocused(): boolean {
		if (this._isDisposed) {
			throw new Error('ViewImpl.isFocused: View is disposed');
		}
		return this.hasFocus;
	}

	public createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): OverviewRuler {
		if (this._isDisposed) {
			throw new Error('ViewImpl.createOverviewRuler: View is disposed');
		}
		return new OverviewRuler(
660
				this._context, cssClassName, this.layoutProvider.getScrollHeight(), minimumHeight, maximumHeight,
E
Erich Gamma 已提交
661 662 663 664
				(lineNumber:number) => this.layoutProvider.getVerticalOffsetForLineNumber(lineNumber)
		);
	}

A
Alex Dima 已提交
665
	public change(callback: (changeAccessor: editorBrowser.IViewZoneChangeAccessor) => any): boolean {
E
Erich Gamma 已提交
666 667 668 669 670 671 672
		if (this._isDisposed) {
			throw new Error('ViewImpl.change: View is disposed');
		}
		var zonesHaveChanged = false;
		this._renderOnce(() => {
			// Handle events to avoid "adjusting" newly inserted view zones
			this._flushAnyAccumulatedEvents();
A
Alex Dima 已提交
673 674
			var changeAccessor:editorBrowser.IViewZoneChangeAccessor = {
				addZone: (zone:editorBrowser.IViewZone): number => {
E
Erich Gamma 已提交
675 676 677 678 679 680 681 682 683 684 685
					zonesHaveChanged = true;
					return this.viewZones.addZone(zone);
				},
				removeZone: (id:number): void => {
					zonesHaveChanged = this.viewZones.removeZone(id) || zonesHaveChanged;
				},
				layoutZone: (id: number): void => {
					zonesHaveChanged = this.viewZones.layoutZone(id) || zonesHaveChanged;
				}
			};

A
Alex Dima 已提交
686
			var r: any = safeInvoke1Arg(callback, changeAccessor);
E
Erich Gamma 已提交
687 688 689 690 691 692

			// Invalidate changeAccessor
			changeAccessor.addZone = null;
			changeAccessor.removeZone = null;

			if (zonesHaveChanged) {
693
				this._context.privateViewEventBus.emit(editorCommon.EventType.ViewZonesChanged, null);
E
Erich Gamma 已提交
694 695 696 697 698 699 700
			}

			return r;
		});
		return zonesHaveChanged;
	}

A
Alex Dima 已提交
701
	public getWhitespaces(): editorCommon.IEditorWhitespace[]{
E
Erich Gamma 已提交
702 703 704 705 706 707
		if (this._isDisposed) {
			throw new Error('ViewImpl.getWhitespaces: View is disposed');
		}
		return this.layoutProvider.getWhitespaces();
	}

A
Alex Dima 已提交
708
	public addContentWidget(widgetData: editorBrowser.IContentWidgetData): void {
E
Erich Gamma 已提交
709 710 711 712 713 714 715 716 717
		if (this._isDisposed) {
			throw new Error('ViewImpl.addContentWidget: View is disposed');
		}
		this._renderOnce(() => {
			this.contentWidgets.addWidget(widgetData.widget);
			this.layoutContentWidget(widgetData);
		});
	}

A
Alex Dima 已提交
718
	public layoutContentWidget(widgetData: editorBrowser.IContentWidgetData): void {
E
Erich Gamma 已提交
719 720 721
		if (this._isDisposed) {
			throw new Error('ViewImpl.layoutContentWidget: View is disposed');
		}
722

723 724 725 726 727
		this._renderOnce(() => {
			let newPosition = widgetData.position ? widgetData.position.position : null;
			let newPreference = widgetData.position ? widgetData.position.preference : null;
			this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newPreference);
		});
E
Erich Gamma 已提交
728 729
	}

A
Alex Dima 已提交
730
	public removeContentWidget(widgetData: editorBrowser.IContentWidgetData): void {
E
Erich Gamma 已提交
731 732 733 734 735 736 737 738
		if (this._isDisposed) {
			throw new Error('ViewImpl.removeContentWidget: View is disposed');
		}
		this._renderOnce(() => {
			this.contentWidgets.removeWidget(widgetData.widget);
		});
	}

A
Alex Dima 已提交
739
	public addOverlayWidget(widgetData: editorBrowser.IOverlayWidgetData): void {
E
Erich Gamma 已提交
740 741 742 743 744 745 746 747 748
		if (this._isDisposed) {
			throw new Error('ViewImpl.addOverlayWidget: View is disposed');
		}
		this._renderOnce(() => {
			this.overlayWidgets.addWidget(widgetData.widget);
			this.layoutOverlayWidget(widgetData);
		});
	}

A
Alex Dima 已提交
749
	public layoutOverlayWidget(widgetData: editorBrowser.IOverlayWidgetData): void {
E
Erich Gamma 已提交
750 751 752
		if (this._isDisposed) {
			throw new Error('ViewImpl.layoutOverlayWidget: View is disposed');
		}
753 754 755 756 757 758

		let newPreference = widgetData.position ? widgetData.position.preference : null;
		let shouldRender = this.overlayWidgets.setWidgetPosition(widgetData.widget, newPreference);
		if (shouldRender) {
			this._scheduleRender();
		}
E
Erich Gamma 已提交
759 760
	}

A
Alex Dima 已提交
761
	public removeOverlayWidget(widgetData: editorBrowser.IOverlayWidgetData): void {
E
Erich Gamma 已提交
762 763 764 765 766 767 768 769
		if (this._isDisposed) {
			throw new Error('ViewImpl.removeOverlayWidget: View is disposed');
		}
		this._renderOnce(() => {
			this.overlayWidgets.removeWidget(widgetData.widget);
		});
	}

770
	public render(now:boolean, everything:boolean): void {
E
Erich Gamma 已提交
771 772 773
		if (this._isDisposed) {
			throw new Error('ViewImpl.render: View is disposed');
		}
774 775 776 777
		if (everything) {
			// Force a render with a layout event
			this.layoutProvider.emitLayoutChangedEvent();
		}
778 779 780
		if (now) {
			this._flushAccumulatedAndRenderNow();
		}
E
Erich Gamma 已提交
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
	}

	public renderOnce(callback: () => any): any {
		if (this._isDisposed) {
			throw new Error('ViewImpl.renderOnce: View is disposed');
		}
		return this._renderOnce(callback);
	}

	// --- end Code Editor APIs

	private _renderOnce(callback: () => any): any {
		if (this._isDisposed) {
			throw new Error('ViewImpl._renderOnce: View is disposed');
		}
		return this.outgoingEventBus.deferredEmit(() => {
A
Alex Dima 已提交
797 798
			let r = safeInvokeNoArg(callback);
			this._scheduleRender();
E
Erich Gamma 已提交
799 800 801 802 803 804 805 806 807
			return r;
		});
	}

	private _scheduleRender(): void {
		if (this._isDisposed) {
			throw new Error('ViewImpl._scheduleRender: View is disposed');
		}
		if (this._renderAnimationFrame === null) {
A
Alex Dima 已提交
808
			this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);
E
Erich Gamma 已提交
809 810 811 812 813 814 815 816 817
		}
	}

	private _onRenderScheduled(): void {
		this._renderAnimationFrame = null;
		this._flushAccumulatedAndRenderNow();
	}

	private _renderNow(): void {
A
Alex Dima 已提交
818
		safeInvokeNoArg(() => this._actualRender());
E
Erich Gamma 已提交
819 820
	}

821
	private createRenderingContext(linesViewportData:ViewLinesViewportData): IRenderingContext {
E
Erich Gamma 已提交
822 823 824 825 826

		var vInfo = this.layoutProvider.getCurrentViewport();

		var deltaTop = linesViewportData.visibleRangesDeltaTop;

827
		var r:IRenderingContext = {
E
Erich Gamma 已提交
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
			linesViewportData: linesViewportData,
			scrollWidth: this.layoutProvider.getScrollWidth(),
			scrollHeight: this.layoutProvider.getScrollHeight(),

			visibleRange: linesViewportData.visibleRange,
			bigNumbersDelta: linesViewportData.bigNumbersDelta,

			viewportWidth: vInfo.width,
			viewportHeight: vInfo.height,
			viewportLeft: vInfo.left,
			viewportTop: vInfo.top,

			getScrolledTopFromAbsoluteTop: (absoluteTop:number) => {
				return this.layoutProvider.getScrolledTopFromAbsoluteTop(absoluteTop);
			},

			getViewportVerticalOffsetForLineNumber: (lineNumber:number) => {
				var verticalOffset = this.layoutProvider.getVerticalOffsetForLineNumber(lineNumber);
				var scrolledTop = this.layoutProvider.getScrolledTopFromAbsoluteTop(verticalOffset);
				return scrolledTop;
			},

			getDecorationsInViewport: () => linesViewportData.getDecorationsInViewport(),

A
Alex Dima 已提交
852
			linesVisibleRangesForRange: (range:editorCommon.IRange, includeNewLines:boolean) => {
E
Erich Gamma 已提交
853 854 855
				return this.viewLines.linesVisibleRangesForRange(range, includeNewLines);
			},

A
Alex Dima 已提交
856
			visibleRangeForPosition: (position:editorCommon.IPosition) => {
A
Alex Dima 已提交
857
				var visibleRanges = this.viewLines.visibleRangesForRange2(new Range(position.lineNumber, position.column, position.lineNumber, position.column), deltaTop);
E
Erich Gamma 已提交
858 859 860 861 862 863 864 865 866 867 868 869 870
				if (!visibleRanges) {
					return null;
				}
				return visibleRanges[0];
			},

			lineIsVisible: (lineNumber:number) => {
				return linesViewportData.visibleRange.startLineNumber <= lineNumber && lineNumber <= linesViewportData.visibleRange.endLineNumber;
			}
		};
		return r;
	}

871 872 873 874 875 876 877 878 879 880 881
	private _getViewPartsToRender(): ViewPart[] {
		let result:ViewPart[] = [];
		for (let i = 0, len = this.viewParts.length; i < len; i++) {
			let viewPart = this.viewParts[i];
			if (viewPart.shouldRender()) {
				result.push(viewPart);
			}
		}
		return result;
	}

A
Alex Dima 已提交
882
	private _actualRender(): void {
A
Alex Dima 已提交
883
		if (!dom.isInDOM(this.domNode)) {
E
Erich Gamma 已提交
884 885
			return;
		}
A
Alex Dima 已提交
886
		let t = timer.start(timer.Topic.EDITOR, 'View.render');
E
Erich Gamma 已提交
887

888
		let viewPartsToRender = this._getViewPartsToRender();
E
Erich Gamma 已提交
889

A
Alex Dima 已提交
890 891
		if (!this.viewLines.shouldRender() && viewPartsToRender.length === 0) {
			// Nothing to render
892
			this.keyboardHandler.writeToTextArea();
A
Alex Dima 已提交
893 894 895
			t.stop();
			return;
		}
E
Erich Gamma 已提交
896

A
Alex Dima 已提交
897
		let linesViewportData = this.layoutProvider.getLinesViewportData();
E
Erich Gamma 已提交
898

A
Alex Dima 已提交
899
		if (this.viewLines.shouldRender()) {
900 901 902
			this.viewLines.renderText(linesViewportData, () => {
				this.keyboardHandler.writeToTextArea();
			});
A
Alex Dima 已提交
903
			this.viewLines.onDidRender();
904 905 906

			// Rendering of viewLines might cause scroll events to occur, so collect view parts to render again
			viewPartsToRender = this._getViewPartsToRender();
907 908
		} else {
			this.keyboardHandler.writeToTextArea();
A
Alex Dima 已提交
909
		}
E
Erich Gamma 已提交
910

A
Alex Dima 已提交
911
		let renderingContext = this.createRenderingContext(linesViewportData);
A
Alex Dima 已提交
912

A
Alex Dima 已提交
913 914 915 916 917
		// Render the rest of the parts
		for (let i = 0, len = viewPartsToRender.length; i < len; i++) {
			let viewPart = viewPartsToRender[i];
			viewPart.prepareRender(renderingContext);
		}
A
Alex Dima 已提交
918

A
Alex Dima 已提交
919 920 921 922
		for (let i = 0, len = viewPartsToRender.length; i < len; i++) {
			let viewPart = viewPartsToRender[i];
			viewPart.render(renderingContext);
			viewPart.onDidRender();
E
Erich Gamma 已提交
923 924
		}

925 926 927
		// Render the scrollbar
		this.layoutProvider.renderScrollbar();

E
Erich Gamma 已提交
928 929 930 931 932 933
		t.stop();
	}

	private _setHasFocus(newHasFocus:boolean): void {
		if (this.hasFocus !== newHasFocus) {
			this.hasFocus = newHasFocus;
934
			this._context.privateViewEventBus.emit(editorCommon.EventType.ViewFocusChanged, this.hasFocus);
E
Erich Gamma 已提交
935 936 937 938
		}
	}
}

A
Alex Dima 已提交
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
function safeInvokeNoArg(func:Function): any {
	try {
		return func();
	} catch(e) {
		onUnexpectedError(e);
	}
}

function safeInvoke1Arg(func:Function, arg1:any): any {
	try {
		return func(arg1);
	} catch(e) {
		onUnexpectedError(e);
	}
}