private _registerModelEvents()

in src/vs/editor/common/viewModel/viewModelImpl.ts [180:328]


	private _registerModelEvents(): void {

		this._register(this.model.onDidChangeRawContentFast((e) => {
			try {
				const eventsCollector = this._beginEmit();

				let hadOtherModelChange = false;
				let hadModelLineChangeThatChangedLineMapping = false;

				const changes = e.changes;
				const versionId = e.versionId;

				for (let j = 0, lenJ = changes.length; j < lenJ; j++) {
					const change = changes[j];

					switch (change.changeType) {
						case textModelEvents.RawContentChangedType.Flush: {
							this.lines.onModelFlushed();
							eventsCollector.emit(new viewEvents.ViewFlushedEvent());
							this.decorations.reset();
							this.viewLayout.onFlushed(this.getLineCount());
							hadOtherModelChange = true;
							break;
						}
						case textModelEvents.RawContentChangedType.LinesDeleted: {
							const linesDeletedEvent = this.lines.onModelLinesDeleted(versionId, change.fromLineNumber, change.toLineNumber);
							if (linesDeletedEvent !== null) {
								eventsCollector.emit(linesDeletedEvent);
								this.viewLayout.onLinesDeleted(linesDeletedEvent.fromLineNumber, linesDeletedEvent.toLineNumber);
							}
							hadOtherModelChange = true;
							break;
						}
						case textModelEvents.RawContentChangedType.LinesInserted: {
							const linesInsertedEvent = this.lines.onModelLinesInserted(versionId, change.fromLineNumber, change.toLineNumber, change.detail);
							if (linesInsertedEvent !== null) {
								eventsCollector.emit(linesInsertedEvent);
								this.viewLayout.onLinesInserted(linesInsertedEvent.fromLineNumber, linesInsertedEvent.toLineNumber);
							}
							hadOtherModelChange = true;
							break;
						}
						case textModelEvents.RawContentChangedType.LineChanged: {
							const [lineMappingChanged, linesChangedEvent, linesInsertedEvent, linesDeletedEvent] = this.lines.onModelLineChanged(versionId, change.lineNumber, change.detail);
							hadModelLineChangeThatChangedLineMapping = lineMappingChanged;
							if (linesChangedEvent) {
								eventsCollector.emit(linesChangedEvent);
							}
							if (linesInsertedEvent) {
								eventsCollector.emit(linesInsertedEvent);
								this.viewLayout.onLinesInserted(linesInsertedEvent.fromLineNumber, linesInsertedEvent.toLineNumber);
							}
							if (linesDeletedEvent) {
								eventsCollector.emit(linesDeletedEvent);
								this.viewLayout.onLinesDeleted(linesDeletedEvent.fromLineNumber, linesDeletedEvent.toLineNumber);
							}
							break;
						}
						case textModelEvents.RawContentChangedType.EOLChanged: {
							// Nothing to do. The new version will be accepted below
							break;
						}
					}
				}
				this.lines.acceptVersionId(versionId);
				this.viewLayout.onHeightMaybeChanged();

				if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {
					eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
					eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
					this.decorations.onLineMappingChanged();
				}
			} finally {
				this._endEmit();
			}

			// Update the configuration and reset the centered view line
			this.viewportStartLine = -1;
			this.configuration.setMaxLineNumber(this.model.getLineCount());

			// Recover viewport
			if (!this.hasFocus && this.model.getAttachedEditorCount() >= 2 && this.viewportStartLineTrackedRange) {
				const modelRange = this.model._getTrackedRange(this.viewportStartLineTrackedRange);
				if (modelRange) {
					const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(modelRange.getStartPosition());
					const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
					this.viewLayout.setScrollPositionNow({ scrollTop: viewPositionTop + this.viewportStartLineDelta });
				}
			}
		}));

		this._register(this.model.onDidChangeTokens((e) => {
			let viewRanges: { fromLineNumber: number; toLineNumber: number; }[] = [];
			for (let j = 0, lenJ = e.ranges.length; j < lenJ; j++) {
				const modelRange = e.ranges[j];
				const viewStartLineNumber = this.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.fromLineNumber, 1)).lineNumber;
				const viewEndLineNumber = this.coordinatesConverter.convertModelPositionToViewPosition(new Position(modelRange.toLineNumber, this.model.getLineMaxColumn(modelRange.toLineNumber))).lineNumber;
				viewRanges[j] = {
					fromLineNumber: viewStartLineNumber,
					toLineNumber: viewEndLineNumber
				};
			}
			try {
				const eventsCollector = this._beginEmit();
				eventsCollector.emit(new viewEvents.ViewTokensChangedEvent(viewRanges));
			} finally {
				this._endEmit();
			}

			if (e.tokenizationSupportChanged) {
				this._tokenizeViewportSoon.schedule();
			}
		}));

		this._register(this.model.onDidChangeLanguageConfiguration((e) => {
			try {
				const eventsCollector = this._beginEmit();
				eventsCollector.emit(new viewEvents.ViewLanguageConfigurationEvent());
			} finally {
				this._endEmit();
			}
		}));

		this._register(this.model.onDidChangeOptions((e) => {
			// A tab size change causes a line mapping changed event => all view parts will repaint OK, no further event needed here
			if (this.lines.setTabSize(this.model.getOptions().tabSize)) {
				this.decorations.onLineMappingChanged();
				this.viewLayout.onFlushed(this.getLineCount());
				try {
					const eventsCollector = this._beginEmit();
					eventsCollector.emit(new viewEvents.ViewFlushedEvent());
					eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
					eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
				} finally {
					this._endEmit();
				}
			}
		}));

		this._register(this.model.onDidChangeDecorations((e) => {
			this.decorations.onModelDecorationsChanged();
			try {
				const eventsCollector = this._beginEmit();
				eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
			} finally {
				this._endEmit();
			}
		}));
	}