viewModelImpl.ts 24.2 KB
Newer Older
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';

J
Johannes Rieken 已提交
7 8
import { EmitterEvent, EventEmitter, IEventEmitter } from 'vs/base/common/eventEmitter';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
9
import * as strings from 'vs/base/common/strings';
J
Johannes Rieken 已提交
10 11 12
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
13
import * as editorCommon from 'vs/editor/common/editorCommon';
J
Johannes Rieken 已提交
14 15
import { ViewModelCursors } from 'vs/editor/common/viewModel/viewModelCursors';
import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations';
16
import { ViewModelDecoration, IDecorationsViewportData, IViewModel } from 'vs/editor/common/viewModel/viewModel';
17
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
18 19

export interface ILinesCollection {
J
Johannes Rieken 已提交
20 21 22 23 24 25 26 27
	setTabSize(newTabSize: number, emit: (evenType: string, payload: any) => void): boolean;
	setWrappingColumn(newWrappingColumn: number, columnsForFullWidthChar: number, emit: (evenType: string, payload: any) => void): boolean;
	setWrappingIndent(newWrappingIndent: editorCommon.WrappingIndent, emit: (evenType: string, payload: any) => void): boolean;

	onModelFlushed(versionId: number, emit: (evenType: string, payload: any) => void): void;
	onModelLinesDeleted(versionId: number, fromLineNumber: number, toLineNumber: number, emit: (evenType: string, payload: any) => void): void;
	onModelLinesInserted(versionId: number, fromLineNumber: number, toLineNumber: number, text: string[], emit: (evenType: string, payload: any) => void): void;
	onModelLineChanged(versionId: number, lineNumber: number, newText: string, emit: (evenType: string, payload: any) => void): boolean;
28
	getOutputLineCount(): number;
J
Johannes Rieken 已提交
29 30 31 32
	getOutputLineContent(outputLineNumber: number): string;
	getOutputIndentGuide(outputLineNumber: number): number;
	getOutputLineMinColumn(outputLineNumber: number): number;
	getOutputLineMaxColumn(outputLineNumber: number): number;
33
	getOutputLineTokens(outputLineNumber: number): ViewLineToken[];
J
Johannes Rieken 已提交
34 35 36 37
	convertOutputPositionToInputPosition(viewLineNumber: number, viewColumn: number): Position;
	convertInputPositionToOutputPosition(inputLineNumber: number, inputColumn: number): Position;
	setHiddenAreas(ranges: editorCommon.IRange[], emit: (evenType: string, payload: any) => void): void;
	inputPositionIsVisible(inputLineNumber: number, inputColumn: number): boolean;
38 39 40 41 42
	dispose(): void;
}

export class ViewModel extends EventEmitter implements IViewModel {

J
Johannes Rieken 已提交
43 44 45
	private editorId: number;
	private configuration: editorCommon.IConfiguration;
	private model: editorCommon.IModel;
46

J
Johannes Rieken 已提交
47
	private listenersToRemove: IDisposable[];
48
	private _toDispose: IDisposable[];
J
Johannes Rieken 已提交
49 50 51
	private lines: ILinesCollection;
	private decorations: ViewModelDecorations;
	private cursors: ViewModelCursors;
52

J
Johannes Rieken 已提交
53
	private _renderCustomLineNumbers: (lineNumber: number) => string;
54 55 56
	private _renderRelativeLineNumbers: boolean;
	private _lastCursorPosition: Position;

J
Johannes Rieken 已提交
57
	private getCurrentCenteredModelRange: () => Range;
58

J
Johannes Rieken 已提交
59
	constructor(lines: ILinesCollection, editorId: number, configuration: editorCommon.IConfiguration, model: editorCommon.IModel, getCurrentCenteredModelRange: () => Range) {
60 61 62 63 64 65 66
		super();
		this.lines = lines;

		this.editorId = editorId;
		this.configuration = configuration;
		this.model = model;

J
Johannes Rieken 已提交
67
		this._lastCursorPosition = new Position(1, 1);
68 69 70
		this._renderCustomLineNumbers = this.configuration.editor.viewInfo.renderCustomLineNumbers;
		this._renderRelativeLineNumbers = this.configuration.editor.viewInfo.renderRelativeLineNumbers;

71 72
		this.getCurrentCenteredModelRange = getCurrentCenteredModelRange;

73 74
		this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, {
			convertModelRangeToViewRange: (modelRange: Range, isWholeLine: boolean): Range => {
75 76 77 78
				if (isWholeLine) {
					return this.convertWholeLineModelRangeToViewRange(modelRange);
				}
				return this.convertModelRangeToViewRange(modelRange);
79 80 81
			},
			convertViewRangeToModelRange: (viewRange: Range): Range => {
				return this.convertViewRangeToModelRange(viewRange);
82 83
			}
		});
84
		this.decorations.reset();
85 86 87 88 89

		this.cursors = new ViewModelCursors(this.configuration, this);

		this.listenersToRemove = [];
		this._toDispose = [];
J
Johannes Rieken 已提交
90
		this.listenersToRemove.push(this.model.addBulkListener((events: EmitterEvent[]) => this.onEvents(events)));
91 92 93 94 95
		this._toDispose.push(this.configuration.onDidChange((e) => {
			this.onEvents([new EmitterEvent(editorCommon.EventType.ConfigurationChanged, e)]);
		}));
	}

J
Johannes Rieken 已提交
96
	public setHiddenAreas(ranges: editorCommon.IRange[]): void {
A
Alex Dima 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
		try {
			this._beginDeferredEmit();
			this._setHiddenAreas(ranges);
		} finally {
			this._endDeferredEmit();
		}
	}

	private _setHiddenAreas(ranges: editorCommon.IRange[]): void {
		let lineMappingChanged = this.lines.setHiddenAreas(ranges, (eventType: string, payload: any) => this.emit(eventType, payload));
		if (lineMappingChanged) {
			this.emit(editorCommon.ViewEventNames.LineMappingChangedEvent);
			this.decorations.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
			this.cursors.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
		}
112 113 114
	}

	public dispose(): void {
A
Alex Dima 已提交
115
		this.listenersToRemove = dispose(this.listenersToRemove);
116 117 118 119 120 121 122 123 124
		this._toDispose = dispose(this._toDispose);
		this.decorations.dispose();
		this.decorations = null;
		this.lines.dispose();
		this.lines = null;
		this.configuration = null;
		this.model = null;
	}

J
Johannes Rieken 已提交
125 126
	private _onTabSizeChange(newTabSize: number): boolean {
		var lineMappingChanged = this.lines.setTabSize(newTabSize, (eventType: string, payload: any) => this.emit(eventType, payload));
127 128
		if (lineMappingChanged) {
			this.emit(editorCommon.ViewEventNames.LineMappingChangedEvent);
J
Johannes Rieken 已提交
129
			this.decorations.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
130 131 132 133 134
			this.cursors.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
		}
		return lineMappingChanged;
	}

J
Johannes Rieken 已提交
135 136
	private _onWrappingIndentChange(newWrappingIndent: editorCommon.WrappingIndent): boolean {
		var lineMappingChanged = this.lines.setWrappingIndent(newWrappingIndent, (eventType: string, payload: any) => this.emit(eventType, payload));
137 138
		if (lineMappingChanged) {
			this.emit(editorCommon.ViewEventNames.LineMappingChangedEvent);
J
Johannes Rieken 已提交
139
			this.decorations.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
140 141 142 143 144
			this.cursors.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
		}
		return lineMappingChanged;
	}

J
Johannes Rieken 已提交
145
	private _restoreCenteredModelRange(range: Range): void {
146 147 148 149
		// modelLine -> viewLine
		var newCenteredViewRange = this.convertModelRangeToViewRange(range);

		// Send a reveal event to restore the centered content
J
Johannes Rieken 已提交
150
		var restoreRevealEvent: editorCommon.IViewRevealRangeEvent = {
151 152
			range: newCenteredViewRange,
			verticalType: editorCommon.VerticalRevealType.Center,
153 154
			revealHorizontal: false,
			revealCursor: false
155 156 157 158
		};
		this.emit(editorCommon.ViewEventNames.RevealRangeEvent, restoreRevealEvent);
	}

J
Johannes Rieken 已提交
159 160
	private _onWrappingColumnChange(newWrappingColumn: number, columnsForFullWidthChar: number): boolean {
		let lineMappingChanged = this.lines.setWrappingColumn(newWrappingColumn, columnsForFullWidthChar, (eventType: string, payload: any) => this.emit(eventType, payload));
161 162
		if (lineMappingChanged) {
			this.emit(editorCommon.ViewEventNames.LineMappingChangedEvent);
J
Johannes Rieken 已提交
163
			this.decorations.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
164 165 166 167 168
			this.cursors.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
		}
		return lineMappingChanged;
	}

J
Johannes Rieken 已提交
169 170
	public addEventSource(eventSource: IEventEmitter): void {
		this.listenersToRemove.push(eventSource.addBulkListener2((events: EmitterEvent[]) => this.onEvents(events)));
171 172
	}

J
Johannes Rieken 已提交
173
	private onEvents(events: EmitterEvent[]): void {
A
Alex Dima 已提交
174 175 176 177 178 179 180
		try {
			this._beginDeferredEmit();
			this._onEvents(events);
		} finally {
			this._endDeferredEmit();
		}
	}
181

A
Alex Dima 已提交
182 183 184 185 186 187 188
	private _onEvents(events: EmitterEvent[]): void {
		let hasContentChange = events.some((e) => e.getType() === editorCommon.EventType.ModelRawContentChanged),
			previousCenteredModelRange: Range;
		if (!hasContentChange) {
			// We can only convert the current centered view range to the current centered model range if the model has no changes.
			previousCenteredModelRange = this.getCurrentCenteredModelRange();
		}
189

A
Alex Dima 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
		let i: number,
			len: number,
			e: EmitterEvent,
			data: any,
			modelContentChangedEvent: editorCommon.IModelContentChangedEvent,
			hadOtherModelChange = false,
			hadModelLineChangeThatChangedLineMapping = false,
			revealPreviousCenteredModelRange = false;

		for (i = 0, len = events.length; i < len; i++) {
			e = events[i];
			data = e.getData();

			switch (e.getType()) {

				case editorCommon.EventType.ModelRawContentChanged:
					modelContentChangedEvent = <editorCommon.IModelContentChangedEvent>data;

					switch (modelContentChangedEvent.changeType) {
						case editorCommon.EventType.ModelRawContentChangedFlush:
							this.onModelFlushed(<editorCommon.IModelContentChangedFlushEvent>modelContentChangedEvent);
							hadOtherModelChange = true;
							break;

						case editorCommon.EventType.ModelRawContentChangedLinesDeleted:
							this.onModelLinesDeleted(<editorCommon.IModelContentChangedLinesDeletedEvent>modelContentChangedEvent);
							hadOtherModelChange = true;
							break;

						case editorCommon.EventType.ModelRawContentChangedLinesInserted:
							this.onModelLinesInserted(<editorCommon.IModelContentChangedLinesInsertedEvent>modelContentChangedEvent);
							hadOtherModelChange = true;
							break;

						case editorCommon.EventType.ModelRawContentChangedLineChanged:
							hadModelLineChangeThatChangedLineMapping = this.onModelLineChanged(<editorCommon.IModelContentChangedLineChangedEvent>modelContentChangedEvent);
							break;

						default:
							console.info('ViewModel received unknown event: ');
							console.info(e);
					}
					break;

				case editorCommon.EventType.ModelTokensChanged:
					this.onModelTokensChanged(<editorCommon.IModelTokensChangedEvent>data);
					break;

A
Alex Dima 已提交
238
				case editorCommon.EventType.ModelLanguageChanged:
A
Alex Dima 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
					// That's ok, a model tokens changed event will follow shortly
					break;

				case editorCommon.EventType.ModelContentChanged2:
					// Ignore
					break;

				case editorCommon.EventType.ModelOptionsChanged:
					// A tab size change causes a line mapping changed event => all view parts will repaint OK, no further event needed here
					let prevLineCount = this.lines.getOutputLineCount();
					let tabSizeChanged = this._onTabSizeChange(this.model.getOptions().tabSize);
					let newLineCount = this.lines.getOutputLineCount();
					if (tabSizeChanged && prevLineCount !== newLineCount) {
						revealPreviousCenteredModelRange = true;
					}

					break;

				case editorCommon.EventType.ModelDecorationsChanged:
					this.onModelDecorationsChanged(<editorCommon.IModelDecorationsChangedEvent>data);
					break;

				case editorCommon.EventType.ModelDispose:
					// Ignore, since the editor will take care of this and destroy the view shortly
					break;

				case editorCommon.EventType.CursorPositionChanged:
					this.onCursorPositionChanged(<editorCommon.ICursorPositionChangedEvent>data);
					this._lastCursorPosition = (<editorCommon.ICursorPositionChangedEvent>data).position;
					break;

				case editorCommon.EventType.CursorSelectionChanged:
					this.onCursorSelectionChanged(<editorCommon.ICursorSelectionChangedEvent>data);
					break;

				case editorCommon.EventType.CursorRevealRange:
					this.onCursorRevealRange(<editorCommon.ICursorRevealRangeEvent>data);
					break;

				case editorCommon.EventType.CursorScrollRequest:
					this.onCursorScrollRequest(<editorCommon.ICursorScrollRequestEvent>data);
					break;

				case editorCommon.EventType.ConfigurationChanged:
					revealPreviousCenteredModelRange = this._onWrappingIndentChange(this.configuration.editor.wrappingInfo.wrappingIndent) || revealPreviousCenteredModelRange;
					revealPreviousCenteredModelRange = this._onWrappingColumnChange(this.configuration.editor.wrappingInfo.wrappingColumn, this.configuration.editor.fontInfo.typicalFullwidthCharacterWidth / this.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth) || revealPreviousCenteredModelRange;

					this._renderCustomLineNumbers = this.configuration.editor.viewInfo.renderCustomLineNumbers;
					this._renderRelativeLineNumbers = this.configuration.editor.viewInfo.renderRelativeLineNumbers;

					if ((<editorCommon.IConfigurationChangedEvent>data).readOnly) {
						// Must read again all decorations due to readOnly filtering
291 292
						this.decorations.reset();
						this.emit(editorCommon.ViewEventNames.DecorationsChangedEvent, {});
A
Alex Dima 已提交
293 294 295 296 297 298 299
					}
					this.emit(e.getType(), <editorCommon.IConfigurationChangedEvent>data);
					break;

				default:
					console.info('View received unknown event: ');
					console.info(e);
300
			}
A
Alex Dima 已提交
301
		}
302

A
Alex Dima 已提交
303 304 305 306 307
		if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {
			this.emit(editorCommon.ViewEventNames.LineMappingChangedEvent);
			this.decorations.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
			this.cursors.onLineMappingChanged((eventType: string, payload: any) => this.emit(eventType, payload));
		}
308

A
Alex Dima 已提交
309 310 311
		if (revealPreviousCenteredModelRange && previousCenteredModelRange) {
			this._restoreCenteredModelRange(previousCenteredModelRange);
		}
312 313 314
	}

	// --- begin inbound event conversion
J
Johannes Rieken 已提交
315 316
	private onModelFlushed(e: editorCommon.IModelContentChangedFlushEvent): void {
		this.lines.onModelFlushed(e.versionId, (eventType: string, payload: any) => this.emit(eventType, payload));
317
		this.decorations.reset();
318
	}
J
Johannes Rieken 已提交
319 320
	private onModelDecorationsChanged(e: editorCommon.IModelDecorationsChangedEvent): void {
		this.decorations.onModelDecorationsChanged(e, (eventType: string, payload: any) => this.emit(eventType, payload));
321
	}
J
Johannes Rieken 已提交
322 323
	private onModelLinesDeleted(e: editorCommon.IModelContentChangedLinesDeletedEvent): void {
		this.lines.onModelLinesDeleted(e.versionId, e.fromLineNumber, e.toLineNumber, (eventType: string, payload: any) => this.emit(eventType, payload));
324
	}
J
Johannes Rieken 已提交
325
	private onModelTokensChanged(e: editorCommon.IModelTokensChangedEvent): void {
A
Alex Dima 已提交
326 327 328 329 330 331 332 333 334 335 336
		let viewRanges: { fromLineNumber: number; toLineNumber: number; }[] = [];

		for (let i = 0, len = e.ranges.length; i < len; i++) {
			let modelRange = e.ranges[i];
			let viewStartLineNumber = this.convertModelPositionToViewPosition(modelRange.fromLineNumber, 1).lineNumber;
			let viewEndLineNumber = this.convertModelPositionToViewPosition(modelRange.toLineNumber, this.model.getLineMaxColumn(modelRange.toLineNumber)).lineNumber;
			viewRanges[i] = {
				fromLineNumber: viewStartLineNumber,
				toLineNumber: viewEndLineNumber
			};
		}
337

J
Johannes Rieken 已提交
338
		var e: editorCommon.IViewTokensChangedEvent = {
A
Alex Dima 已提交
339
			ranges: viewRanges
340 341 342
		};
		this.emit(editorCommon.ViewEventNames.TokensChangedEvent, e);
	}
J
Johannes Rieken 已提交
343 344
	private onModelLineChanged(e: editorCommon.IModelContentChangedLineChangedEvent): boolean {
		var lineMappingChanged = this.lines.onModelLineChanged(e.versionId, e.lineNumber, e.detail, (eventType: string, payload: any) => this.emit(eventType, payload));
345 346
		return lineMappingChanged;
	}
J
Johannes Rieken 已提交
347 348
	private onModelLinesInserted(e: editorCommon.IModelContentChangedLinesInsertedEvent): void {
		this.lines.onModelLinesInserted(e.versionId, e.fromLineNumber, e.toLineNumber, e.detail.split('\n'), (eventType: string, payload: any) => this.emit(eventType, payload));
349 350
	}

J
Johannes Rieken 已提交
351
	public validateViewRange(viewStartLineNumber: number, viewStartColumn: number, viewEndLineNumber: number, viewEndColumn: number, modelRange: Range): Range {
A
Alex Dima 已提交
352
		var validViewStart = this.validateViewPosition(viewStartLineNumber, viewStartColumn, modelRange.getStartPosition());
353 354 355 356
		var validViewEnd = this.validateViewPosition(viewEndLineNumber, viewEndColumn, modelRange.getEndPosition());
		return new Range(validViewStart.lineNumber, validViewStart.column, validViewEnd.lineNumber, validViewEnd.column);
	}

J
Johannes Rieken 已提交
357
	public validateViewPosition(viewLineNumber: number, viewColumn: number, modelPosition: Position): Position {
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
		if (viewLineNumber < 1) {
			viewLineNumber = 1;
		}
		var lineCount = this.getLineCount();
		if (viewLineNumber > lineCount) {
			viewLineNumber = lineCount;
		}
		var viewMinColumn = this.getLineMinColumn(viewLineNumber);
		var viewMaxColumn = this.getLineMaxColumn(viewLineNumber);
		if (viewColumn < viewMinColumn) {
			viewColumn = viewMinColumn;
		}
		if (viewColumn > viewMaxColumn) {
			viewColumn = viewMaxColumn;
		}
		var computedModelPosition = this.convertViewPositionToModelPosition(viewLineNumber, viewColumn);
		if (computedModelPosition.equals(modelPosition)) {
			return new Position(viewLineNumber, viewColumn);
		}
		return this.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column);
	}

J
Johannes Rieken 已提交
380
	public validateViewSelection(viewSelection: Selection, modelSelection: Selection): Selection {
381 382 383 384 385 386 387 388 389
		let modelSelectionStart = new Position(modelSelection.selectionStartLineNumber, modelSelection.selectionStartColumn);
		let modelPosition = new Position(modelSelection.positionLineNumber, modelSelection.positionColumn);

		let viewSelectionStart = this.validateViewPosition(viewSelection.selectionStartLineNumber, viewSelection.selectionStartColumn, modelSelectionStart);
		let viewPosition = this.validateViewPosition(viewSelection.positionLineNumber, viewSelection.positionColumn, modelPosition);

		return new Selection(viewSelectionStart.lineNumber, viewSelectionStart.column, viewPosition.lineNumber, viewPosition.column);
	}

J
Johannes Rieken 已提交
390 391
	private onCursorPositionChanged(e: editorCommon.ICursorPositionChangedEvent): void {
		this.cursors.onCursorPositionChanged(e, (eventType: string, payload: any) => this.emit(eventType, payload));
392
	}
J
Johannes Rieken 已提交
393 394
	private onCursorSelectionChanged(e: editorCommon.ICursorSelectionChangedEvent): void {
		this.cursors.onCursorSelectionChanged(e, (eventType: string, payload: any) => this.emit(eventType, payload));
395
	}
J
Johannes Rieken 已提交
396 397
	private onCursorRevealRange(e: editorCommon.ICursorRevealRangeEvent): void {
		this.cursors.onCursorRevealRange(e, (eventType: string, payload: any) => this.emit(eventType, payload));
398
	}
J
Johannes Rieken 已提交
399 400
	private onCursorScrollRequest(e: editorCommon.ICursorScrollRequestEvent): void {
		this.cursors.onCursorScrollRequest(e, (eventType: string, payload: any) => this.emit(eventType, payload));
401 402 403 404 405 406 407 408 409 410 411
	}
	// --- end inbound event conversion

	public getTabSize(): number {
		return this.model.getOptions().tabSize;
	}

	public getLineCount(): number {
		return this.lines.getOutputLineCount();
	}

412 413 414 415
	public mightContainRTL(): boolean {
		return this.model.mightContainRTL();
	}

J
Johannes Rieken 已提交
416
	public getLineContent(lineNumber: number): string {
417 418 419
		return this.lines.getOutputLineContent(lineNumber);
	}

J
Johannes Rieken 已提交
420
	public getLineIndentGuide(lineNumber: number): number {
421 422 423
		return this.lines.getOutputIndentGuide(lineNumber);
	}

J
Johannes Rieken 已提交
424
	public getLineMinColumn(lineNumber: number): number {
425 426 427
		return this.lines.getOutputLineMinColumn(lineNumber);
	}

J
Johannes Rieken 已提交
428
	public getLineMaxColumn(lineNumber: number): number {
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
		return this.lines.getOutputLineMaxColumn(lineNumber);
	}

	public getLineFirstNonWhitespaceColumn(lineNumber: number): number {
		var result = strings.firstNonWhitespaceIndex(this.getLineContent(lineNumber));
		if (result === -1) {
			return 0;
		}
		return result + 1;
	}

	public getLineLastNonWhitespaceColumn(lineNumber: number): number {
		var result = strings.lastNonWhitespaceIndex(this.getLineContent(lineNumber));
		if (result === -1) {
			return 0;
		}
		return result + 2;
	}

448
	public getLineTokens(lineNumber: number): ViewLineToken[] {
449 450 451
		return this.lines.getOutputLineTokens(lineNumber);
	}

J
Johannes Rieken 已提交
452
	public getLineRenderLineNumber(viewLineNumber: number): string {
453
		let modelPosition = this.convertViewPositionToModelPosition(viewLineNumber, 1);
454 455 456
		if (modelPosition.column !== 1) {
			return '';
		}
457
		let modelLineNumber = modelPosition.lineNumber;
458

459 460 461 462 463 464 465 466 467 468
		if (this._renderCustomLineNumbers) {
			return this._renderCustomLineNumbers(modelLineNumber);
		}

		if (this._renderRelativeLineNumbers) {
			let diff = Math.abs(this._lastCursorPosition.lineNumber - modelLineNumber);
			if (diff === 0) {
				return '<span class="relative-current-line-number">' + modelLineNumber + '</span>';
			}
			return String(diff);
469 470
		}

471
		return String(modelLineNumber);
472 473
	}

474 475 476 477 478
	public getMaxLineNumber(): number {
		// The largest value for a line number will be that of the model line count
		return this.model.getLineCount();
	}

J
Johannes Rieken 已提交
479
	public getDecorationsViewportData(startLineNumber: number, endLineNumber: number): IDecorationsViewportData {
480 481 482 483 484 485 486
		let viewRange = new Range(
			startLineNumber,
			this.getLineMinColumn(startLineNumber),
			endLineNumber,
			this.getLineMaxColumn(endLineNumber)
		);
		return this.decorations.getDecorationsViewportData(viewRange);
487 488
	}

489 490
	public getAllOverviewRulerDecorations(): ViewModelDecoration[] {
		return this.decorations.getAllOverviewRulerDecorations();
491 492 493 494 495 496
	}

	public getEOL(): string {
		return this.model.getEOL();
	}

497
	public getValueInRange(range: Range, eol: editorCommon.EndOfLinePreference): string {
498 499 500 501
		var modelRange = this.convertViewRangeToModelRange(range);
		return this.model.getValueInRange(modelRange, eol);
	}

502
	public getSelections(): Selection[] {
503 504 505 506 507
		return this.cursors.getSelections();
	}

	// View -> Model conversion and related methods

J
Johannes Rieken 已提交
508
	public convertViewPositionToModelPosition(viewLineNumber: number, viewColumn: number): Position {
509 510 511
		return this.lines.convertOutputPositionToInputPosition(viewLineNumber, viewColumn);
	}

512
	public convertViewRangeToModelRange(viewRange: Range): Range {
513 514 515 516 517
		var start = this.convertViewPositionToModelPosition(viewRange.startLineNumber, viewRange.startColumn);
		var end = this.convertViewPositionToModelPosition(viewRange.endLineNumber, viewRange.endColumn);
		return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
	}

J
Johannes Rieken 已提交
518
	public convertViewSelectionToModelSelection(viewSelection: editorCommon.ISelection): Selection {
519 520 521 522 523 524 525
		let selectionStart = this.convertViewPositionToModelPosition(viewSelection.selectionStartLineNumber, viewSelection.selectionStartColumn);
		let position = this.convertViewPositionToModelPosition(viewSelection.positionLineNumber, viewSelection.positionColumn);
		return new Selection(selectionStart.lineNumber, selectionStart.column, position.lineNumber, position.column);
	}

	// Model -> View conversion and related methods

J
Johannes Rieken 已提交
526
	public getModelLineContent(modelLineNumber: number): string {
527 528 529
		return this.model.getLineContent(modelLineNumber);
	}

J
Johannes Rieken 已提交
530
	public getModelLineMaxColumn(modelLineNumber: number): number {
531 532 533
		return this.model.getLineMaxColumn(modelLineNumber);
	}

J
Johannes Rieken 已提交
534
	public validateModelPosition(position: editorCommon.IPosition): Position {
535 536 537
		return this.model.validatePosition(position);
	}

J
Johannes Rieken 已提交
538
	public convertModelPositionToViewPosition(modelLineNumber: number, modelColumn: number): Position {
539 540 541
		return this.lines.convertInputPositionToOutputPosition(modelLineNumber, modelColumn);
	}

542
	public convertModelRangeToViewRange(modelRange: Range): Range {
543 544 545 546 547
		var start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn);
		var end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, modelRange.endColumn);
		return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
	}

548
	public convertWholeLineModelRangeToViewRange(modelRange: Range): Range {
549 550 551 552 553
		var start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, 1);
		var end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, this.model.getLineMaxColumn(modelRange.endLineNumber));
		return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
	}

J
Johannes Rieken 已提交
554
	public convertModelSelectionToViewSelection(modelSelection: Selection): Selection {
555 556 557 558 559
		var selectionStart = this.convertModelPositionToViewPosition(modelSelection.selectionStartLineNumber, modelSelection.selectionStartColumn);
		var position = this.convertModelPositionToViewPosition(modelSelection.positionLineNumber, modelSelection.positionColumn);
		return new Selection(selectionStart.lineNumber, selectionStart.column, position.lineNumber, position.column);
	}

560
	public modelPositionIsVisible(position: Position): boolean {
561 562 563 564
		return this.lines.inputPositionIsVisible(position.lineNumber, position.column);
	}

}