提交 777c5e0f 编写于 作者: A Alex Dima

Remove VerticalObjects

上级 12992d3c
......@@ -78,11 +78,6 @@ export interface IVerticalLayoutProvider {
*/
getVerticalOffsetForLineNumber(lineNumber: number): number;
/**
* Returns the height in pixels for `lineNumber`.
*/
heightInPxForLine(lineNumber: number): number;
/**
* Return line number at `verticalOffset` or closest line number
*/
......@@ -121,7 +116,7 @@ export class LayoutProvider extends ViewEventHandler implements IDisposable, ILa
this.configuration.setMaxLineNumber(this.model.getMaxLineNumber());
this.linesLayout = new LinesLayout(configuration, this.model.getLineCount());
this.linesLayout = new LinesLayout(this.model.getLineCount(), this.configuration.editor.lineHeight);
this._updateHeight();
}
......@@ -149,21 +144,23 @@ export class LayoutProvider extends ViewEventHandler implements IDisposable, ILa
}
public onModelLinesDeleted(e: editorCommon.IViewLinesDeletedEvent): boolean {
this.linesLayout.onModelLinesDeleted(e);
this.linesLayout.onModelLinesDeleted(e.fromLineNumber, e.toLineNumber);
this.updateLineCount();
this._updateHeight();
return false;
}
public onModelLinesInserted(e: editorCommon.IViewLinesInsertedEvent): boolean {
this.linesLayout.onModelLinesInserted(e);
this.linesLayout.onModelLinesInserted(e.fromLineNumber, e.toLineNumber);
this.updateLineCount();
this._updateHeight();
return false;
}
public onConfigurationChanged(e: editorCommon.IConfigurationChangedEvent): boolean {
this.linesLayout.onConfigurationChanged(e);
if (e.lineHeight) {
this.linesLayout.setLineHeight(this.configuration.editor.lineHeight);
}
if (e.layoutInfo) {
this.scrollManager.onLayoutInfoChanged();
this._emitLayoutChangedEvent();
......@@ -251,15 +248,34 @@ export class LayoutProvider extends ViewEventHandler implements IDisposable, ILa
public getVerticalOffsetForLineNumber(lineNumber: number): number {
return this.linesLayout.getVerticalOffsetForLineNumber(lineNumber);
}
public heightInPxForLine(lineNumber: number): number {
return this.linesLayout.getHeightForLineNumber(lineNumber);
}
public isAfterLines(verticalOffset: number): boolean {
return this.linesLayout.isAfterLines(verticalOffset);
}
public getLineNumberAtVerticalOffset(verticalOffset: number): number {
return this.linesLayout.getLineNumberAtOrAfterVerticalOffset(verticalOffset);
}
/**
* Get the sum of heights for all objects and compute basically the `scrollHeight` for the editor content.
*
* Take into account the `scrollBeyondLastLine` and `reserveHorizontalScrollbarHeight` and produce a scrollHeight that is at least as large as `viewport`.height.
*
* @param viewport The viewport.
* @param reserveHorizontalScrollbarHeight The height of the horizontal scrollbar.
* @return Basically, the `scrollHeight` for the editor content.
*/
private _getTotalHeight(viewport: editorCommon.Viewport, reserveHorizontalScrollbarHeight: number): number {
var totalLinesHeight = this.linesLayout.getLinesTotalHeight();
if (this.configuration.editor.viewInfo.scrollBeyondLastLine) {
totalLinesHeight += viewport.height - this.configuration.editor.lineHeight;
} else {
totalLinesHeight += reserveHorizontalScrollbarHeight;
}
return Math.max(viewport.height, totalLinesHeight);
}
public getTotalHeight(): number {
let reserveHorizontalScrollbarHeight = 0;
if (this.scrollManager.getScrollWidth() > this.scrollManager.getWidth()) {
......@@ -267,16 +283,18 @@ export class LayoutProvider extends ViewEventHandler implements IDisposable, ILa
reserveHorizontalScrollbarHeight = this.configuration.editor.viewInfo.scrollbar.horizontalScrollbarSize;
}
}
return this.linesLayout.getTotalHeight(this.getCurrentViewport(), reserveHorizontalScrollbarHeight);
return this._getTotalHeight(this.getCurrentViewport(), reserveHorizontalScrollbarHeight);
}
public getWhitespaceAtVerticalOffset(verticalOffset: number): editorCommon.IViewWhitespaceViewportData {
return this.linesLayout.getWhitespaceAtVerticalOffset(verticalOffset);
}
public getLinesViewportData(): IPartialViewLinesViewportData {
return this.linesLayout.getLinesViewportData(this.getCurrentViewport());
const visibleBox = this.getCurrentViewport();
return this.linesLayout.getLinesViewportData(visibleBox.top, visibleBox.top + visibleBox.height);
}
public getWhitespaceViewportData(): editorCommon.IViewWhitespaceViewportData[] {
return this.linesLayout.getWhitespaceViewportData(this.getCurrentViewport());
const visibleBox = this.getCurrentViewport();
return this.linesLayout.getWhitespaceViewportData(visibleBox.top, visibleBox.top + visibleBox.height);
}
public getWhitespaces(): editorCommon.IEditorWhitespace[] {
return this.linesLayout.getWhitespaces();
......
......@@ -486,7 +486,7 @@ export class ViewLines extends ViewLayer<ViewLine> implements IViewLines {
// Have a box that includes one extra line height (for the horizontal scrollbar)
boxStartY = this._layoutProvider.getVerticalOffsetForLineNumber(range.startLineNumber);
boxEndY = this._layoutProvider.getVerticalOffsetForLineNumber(range.endLineNumber) + this._layoutProvider.heightInPxForLine(range.endLineNumber);
boxEndY = this._layoutProvider.getVerticalOffsetForLineNumber(range.endLineNumber) + this._lineHeight;
if (verticalType === editorCommon.VerticalRevealType.Simple || verticalType === editorCommon.VerticalRevealType.Bottom) {
// Reveal one line more when the last line would be covered by the scrollbar - arrow down case or revealing a line explicitly at bottom
boxEndY += this._lineHeight;
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IEditorWhitespace, IViewWhitespaceViewportData } from 'vs/editor/common/editorCommon';
import { WhitespaceComputer } from 'vs/editor/common/viewLayout/whitespaceComputer';
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
/**
* Layouting of objects that take vertical space (by having a height) and push down other objects.
*
* These objects are basically either text (lines) or spaces between those lines (whitespaces).
* This provides commodity operations for working with lines that contain whitespace that pushes lines lower (vertically).
* This is written with no knowledge of an editor in mind.
*/
export class VerticalObjects {
/**
* Keep track of the total number of lines.
* This is useful for doing binary searches or for doing hit-testing.
*/
private linesCount: number;
/**
* Contains whitespace information in pixels
*/
private whitespaces: WhitespaceComputer;
constructor() {
this.linesCount = 0;
this.whitespaces = new WhitespaceComputer();
}
/**
* Set the number of lines.
*
* @param newLineCount New number of lines.
*/
public replaceLines(newLineCount: number): void {
this.linesCount = newLineCount;
}
/**
* Insert a new whitespace of a certain height after a line number.
* The whitespace has a "sticky" characteristic.
* Irrespective of edits above or below `afterLineNumber`, the whitespace will follow the initial line.
*
* @param afterLineNumber The conceptual position of this whitespace. The whitespace will follow this line as best as possible even when deleting/inserting lines above/below.
* @param heightInPx The height of the whitespace, in pixels.
* @return An id that can be used later to mutate or delete the whitespace
*/
public insertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number): number {
return this.whitespaces.insertWhitespace(afterLineNumber, ordinal, heightInPx);
}
public changeWhitespace(id: number, newAfterLineNumber: number, newHeight: number): boolean {
return this.whitespaces.changeWhitespace(id, newAfterLineNumber, newHeight);
}
/**
* Remove an existing whitespace.
*
* @param id The whitespace to remove
* @return Returns true if the whitespace is found and it is removed.
*/
public removeWhitespace(id: number): boolean {
return this.whitespaces.removeWhitespace(id);
}
/**
* Notify the layouter that lines have been deleted (a continuous zone of lines).
*
* @param fromLineNumber The line number at which the deletion started, inclusive
* @param toLineNumber The line number at which the deletion ended, inclusive
*/
public onModelLinesDeleted(fromLineNumber: number, toLineNumber: number): void {
this.linesCount -= (toLineNumber - fromLineNumber + 1);
this.whitespaces.onModelLinesDeleted(fromLineNumber, toLineNumber);
}
/**
* Notify the layouter that lines have been inserted (a continuous zone of lines).
*
* @param fromLineNumber The line number at which the insertion started, inclusive
* @param toLineNumber The line number at which the insertion ended, inclusive.
*/
public onModelLinesInserted(fromLineNumber: number, toLineNumber: number): void {
this.linesCount += (toLineNumber - fromLineNumber + 1);
this.whitespaces.onModelLinesInserted(fromLineNumber, toLineNumber);
}
/**
* Get the sum of heights for all objects.
*
* @param deviceLineHeight The height, in pixels, for one rendered line.
* @return The sum of heights for all objects.
*/
public getTotalHeight(deviceLineHeight: number): number {
deviceLineHeight = deviceLineHeight | 0;
let linesHeight = deviceLineHeight * this.linesCount;
let whitespacesHeight = this.whitespaces.getTotalHeight();
return linesHeight + whitespacesHeight;
}
/**
* Get the vertical offset (the sum of heights for all objects above) a certain line number.
*
* @param lineNumber The line number
* @param deviceLineHeight The height, in pixels, for one rendered line.
* @return The sum of heights for all objects above `lineNumber`.
*/
public getVerticalOffsetForLineNumber(lineNumber: number, deviceLineHeight: number): number {
lineNumber = lineNumber | 0;
deviceLineHeight = deviceLineHeight | 0;
let previousLinesHeight: number;
if (lineNumber > 1) {
previousLinesHeight = deviceLineHeight * (lineNumber - 1);
} else {
previousLinesHeight = 0;
}
let previousWhitespacesHeight = this.whitespaces.getAccumulatedHeightBeforeLineNumber(lineNumber);
return previousLinesHeight + previousWhitespacesHeight;
}
/**
* Returns the accumulated height of whitespaces before the given line number.
*
* @param lineNumber The line number
*/
public getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber: number): number {
return this.whitespaces.getAccumulatedHeightBeforeLineNumber(lineNumber);
}
/**
* Returns if there is any whitespace in the document.
*/
public hasWhitespace(): boolean {
return this.whitespaces.getCount() > 0;
}
public isAfterLines(verticalOffset: number, deviceLineHeight: number): boolean {
let totalHeight = this.getTotalHeight(deviceLineHeight);
return verticalOffset > totalHeight;
}
/**
* Find the first line number that is at or after vertical offset `verticalOffset`.
* i.e. if getVerticalOffsetForLine(line) is x and getVerticalOffsetForLine(line + 1) is y, then
* getLineNumberAtOrAfterVerticalOffset(i) = line, x <= i < y.
*
* @param verticalOffset The vertical offset to search at.
* @param deviceLineHeight The height, in piexels, for one rendered line.
* @return The line number at or after vertical offset `verticalOffset`.
*/
public getLineNumberAtOrAfterVerticalOffset(verticalOffset: number, deviceLineHeight: number): number {
verticalOffset = verticalOffset | 0;
deviceLineHeight = deviceLineHeight | 0;
if (verticalOffset < 0) {
return 1;
}
let minLineNumber = 1;
let linesCount = this.linesCount | 0;
let maxLineNumber = linesCount;
while (minLineNumber < maxLineNumber) {
let midLineNumber = ((minLineNumber + maxLineNumber) / 2) | 0;
let midLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(midLineNumber, deviceLineHeight) | 0;
if (verticalOffset >= midLineNumberVerticalOffset + deviceLineHeight) {
// vertical offset is after mid line number
minLineNumber = midLineNumber + 1;
} else if (verticalOffset >= midLineNumberVerticalOffset) {
// Hit
return midLineNumber;
} else {
// vertical offset is before mid line number, but mid line number could still be what we're searching for
maxLineNumber = midLineNumber;
}
}
if (minLineNumber > linesCount) {
return linesCount;
}
return minLineNumber;
}
/**
* Get all the lines and their relative vertical offsets that are positioned between `verticalOffset1` and `verticalOffset2`.
*
* @param verticalOffset1 The beginning of the viewport.
* @param verticalOffset2 The end of the viewport.
* @param deviceLineHeight The height, in pixels, for one rendered line.
* @return A structure describing the lines positioned between `verticalOffset1` and `verticalOffset2`.
*/
public getLinesViewportData(verticalOffset1: number, verticalOffset2: number, deviceLineHeight: number): IPartialViewLinesViewportData {
verticalOffset1 = verticalOffset1 | 0;
verticalOffset2 = verticalOffset2 | 0;
deviceLineHeight = deviceLineHeight | 0;
// Find first line number
// We don't live in a perfect world, so the line number might start before or after verticalOffset1
let startLineNumber = this.getLineNumberAtOrAfterVerticalOffset(verticalOffset1, deviceLineHeight) | 0;
let endLineNumber = this.linesCount | 0;
let startLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(startLineNumber, deviceLineHeight) | 0;
// Also keep track of what whitespace we've got
let whitespaceIndex = this.whitespaces.getFirstWhitespaceIndexAfterLineNumber(startLineNumber) | 0;
let whitespaceCount = this.whitespaces.getCount() | 0;
let currentWhitespaceHeight: number;
let currentWhitespaceAfterLineNumber: number;
if (whitespaceIndex === -1) {
whitespaceIndex = whitespaceCount;
currentWhitespaceAfterLineNumber = endLineNumber + 1;
currentWhitespaceHeight = 0;
} else {
currentWhitespaceAfterLineNumber = this.whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
currentWhitespaceHeight = this.whitespaces.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
}
let currentVerticalOffset = startLineNumberVerticalOffset;
let currentLineRelativeOffset = currentVerticalOffset;
// IE (all versions) cannot handle units above about 1,533,908 px, so every 500k pixels bring numbers down
const STEP_SIZE = 500000;
let bigNumbersDelta = 0;
if (startLineNumberVerticalOffset >= STEP_SIZE) {
// Compute a delta that guarantees that lines are positioned at `lineHeight` increments
bigNumbersDelta = Math.floor(startLineNumberVerticalOffset / STEP_SIZE) * STEP_SIZE;
bigNumbersDelta = Math.floor(bigNumbersDelta / deviceLineHeight) * deviceLineHeight;
currentLineRelativeOffset -= bigNumbersDelta;
}
let linesOffsets: number[] = [];
let verticalCenter = verticalOffset1 + (verticalOffset2 - verticalOffset1) / 2;
let centeredLineNumber = -1;
// Figure out how far the lines go
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
if (centeredLineNumber === -1) {
let currentLineTop = currentVerticalOffset;
let currentLineBottom = currentVerticalOffset + deviceLineHeight;
if ((currentLineTop <= verticalCenter && verticalCenter < currentLineBottom) || currentLineTop > verticalCenter) {
centeredLineNumber = lineNumber;
}
}
// Count current line height in the vertical offsets
currentVerticalOffset += deviceLineHeight;
linesOffsets[lineNumber - startLineNumber] = currentLineRelativeOffset;
// Next line starts immediately after this one
currentLineRelativeOffset += deviceLineHeight;
while (currentWhitespaceAfterLineNumber === lineNumber) {
// Push down next line with the height of the current whitespace
currentLineRelativeOffset += currentWhitespaceHeight;
// Count current whitespace in the vertical offsets
currentVerticalOffset += currentWhitespaceHeight;
whitespaceIndex++;
if (whitespaceIndex >= whitespaceCount) {
currentWhitespaceAfterLineNumber = endLineNumber + 1;
} else {
currentWhitespaceAfterLineNumber = this.whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
currentWhitespaceHeight = this.whitespaces.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
}
}
if (currentVerticalOffset >= verticalOffset2) {
// We have covered the entire viewport area, time to stop
endLineNumber = lineNumber;
break;
}
}
if (centeredLineNumber === -1) {
centeredLineNumber = endLineNumber;
}
return {
viewportTop: verticalOffset1 - bigNumbersDelta,
viewportHeight: verticalOffset2 - verticalOffset1,
bigNumbersDelta: bigNumbersDelta,
startLineNumber: startLineNumber,
endLineNumber: endLineNumber,
visibleRangesDeltaTop: -(verticalOffset1 - bigNumbersDelta),
relativeVerticalOffset: linesOffsets,
centeredLineNumber: centeredLineNumber
};
}
public getVerticalOffsetForWhitespaceIndex(whitespaceIndex: number, deviceLineHeight: number): number {
whitespaceIndex = whitespaceIndex | 0;
deviceLineHeight = deviceLineHeight | 0;
let afterLineNumber = this.whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex);
let previousLinesHeight: number;
if (afterLineNumber >= 1) {
previousLinesHeight = deviceLineHeight * afterLineNumber;
} else {
previousLinesHeight = 0;
}
let previousWhitespacesHeight: number;
if (whitespaceIndex > 0) {
previousWhitespacesHeight = this.whitespaces.getAccumulatedHeight(whitespaceIndex - 1);
} else {
previousWhitespacesHeight = 0;
}
return previousLinesHeight + previousWhitespacesHeight;
}
public getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset: number, deviceLineHeight: number): number {
verticalOffset = verticalOffset | 0;
deviceLineHeight = deviceLineHeight | 0;
let midWhitespaceIndex: number,
minWhitespaceIndex = 0,
maxWhitespaceIndex = this.whitespaces.getCount() - 1,
midWhitespaceVerticalOffset: number,
midWhitespaceHeight: number;
if (maxWhitespaceIndex < 0) {
return -1;
}
// Special case: nothing to be found
let maxWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(maxWhitespaceIndex, deviceLineHeight);
let maxWhitespaceHeight = this.whitespaces.getHeightForWhitespaceIndex(maxWhitespaceIndex);
if (verticalOffset >= maxWhitespaceVerticalOffset + maxWhitespaceHeight) {
return -1;
}
while (minWhitespaceIndex < maxWhitespaceIndex) {
midWhitespaceIndex = Math.floor((minWhitespaceIndex + maxWhitespaceIndex) / 2);
midWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(midWhitespaceIndex, deviceLineHeight);
midWhitespaceHeight = this.whitespaces.getHeightForWhitespaceIndex(midWhitespaceIndex);
if (verticalOffset >= midWhitespaceVerticalOffset + midWhitespaceHeight) {
// vertical offset is after whitespace
minWhitespaceIndex = midWhitespaceIndex + 1;
} else if (verticalOffset >= midWhitespaceVerticalOffset) {
// Hit
return midWhitespaceIndex;
} else {
// vertical offset is before whitespace, but midWhitespaceIndex might still be what we're searching for
maxWhitespaceIndex = midWhitespaceIndex;
}
}
return minWhitespaceIndex;
}
/**
* Get exactly the whitespace that is layouted at `verticalOffset`.
*
* @param verticalOffset The vertical offset.
* @param deviceLineHeight The height, in pixels, for one rendered line.
* @return Precisely the whitespace that is layouted at `verticaloffset` or null.
*/
public getWhitespaceAtVerticalOffset(verticalOffset: number, deviceLineHeight: number): IViewWhitespaceViewportData {
verticalOffset = verticalOffset | 0;
deviceLineHeight = deviceLineHeight | 0;
let candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset, deviceLineHeight);
if (candidateIndex < 0) {
return null;
}
if (candidateIndex >= this.whitespaces.getCount()) {
return null;
}
let candidateTop = this.getVerticalOffsetForWhitespaceIndex(candidateIndex, deviceLineHeight);
if (candidateTop > verticalOffset) {
return null;
}
let candidateHeight = this.whitespaces.getHeightForWhitespaceIndex(candidateIndex);
let candidateId = this.whitespaces.getIdForWhitespaceIndex(candidateIndex);
let candidateAfterLineNumber = this.whitespaces.getAfterLineNumberForWhitespaceIndex(candidateIndex);
return {
id: candidateId,
afterLineNumber: candidateAfterLineNumber,
verticalOffset: candidateTop,
height: candidateHeight
};
}
/**
* Get a list of whitespaces that are positioned between `verticalOffset1` and `verticalOffset2`.
*
* @param verticalOffset1 The beginning of the viewport.
* @param verticalOffset2 The end of the viewport.
* @param deviceLineHeight The height, in pixels, for one rendered line.
* @return An array with all the whitespaces in the viewport. If no whitespace is in viewport, the array is empty.
*/
public getWhitespaceViewportData(verticalOffset1: number, verticalOffset2: number, deviceLineHeight: number): IViewWhitespaceViewportData[] {
verticalOffset1 = verticalOffset1 | 0;
verticalOffset2 = verticalOffset2 | 0;
deviceLineHeight = deviceLineHeight | 0;
let startIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset1, deviceLineHeight);
let endIndex = this.whitespaces.getCount() - 1;
if (startIndex < 0) {
return [];
}
let result: IViewWhitespaceViewportData[] = [],
i: number,
top: number,
height: number;
for (i = startIndex; i <= endIndex; i++) {
top = this.getVerticalOffsetForWhitespaceIndex(i, deviceLineHeight);
height = this.whitespaces.getHeightForWhitespaceIndex(i);
if (top >= verticalOffset2) {
break;
}
result.push({
id: this.whitespaces.getIdForWhitespaceIndex(i),
afterLineNumber: this.whitespaces.getAfterLineNumberForWhitespaceIndex(i),
verticalOffset: top,
height: height
});
}
return result;
}
public getWhitespaces(deviceLineHeight: number): IEditorWhitespace[] {
return this.whitespaces.getWhitespaces(deviceLineHeight);
}
}
\ No newline at end of file
......@@ -15,54 +15,54 @@ export class WhitespaceComputer {
/**
* heights[i] is the height in pixels for whitespace at index i
*/
private heights: number[];
private _heights: number[];
/**
* afterLineNumbers[i] is the line number whitespace at index i is after
*/
private afterLineNumbers: number[];
private _afterLineNumbers: number[];
/**
* ordinals[i] is the orinal of the whitespace at index i
*/
private ordinals: number[];
private _ordinals: number[];
/**
* prefixSum[i] = SUM(heights[j]), 1 <= j <= i
*/
private prefixSum: number[];
private _prefixSum: number[];
/**
* prefixSum[i], 1 <= i <= prefixSumValidIndex can be trusted
*/
private prefixSumValidIndex: number;
private _prefixSumValidIndex: number;
/**
* ids[i] is the whitespace id of whitespace at index i
*/
private ids: number[];
private _ids: number[];
/**
* index at which a whitespace is positioned (inside heights, afterLineNumbers, prefixSum members)
*/
private whitespaceId2Index: {
private _whitespaceId2Index: {
[id: string]: number;
};
/**
* last whitespace id issued
*/
private lastWhitespaceId: number;
private _lastWhitespaceId: number;
constructor() {
this.heights = [];
this.ids = [];
this.afterLineNumbers = [];
this.ordinals = [];
this.prefixSum = [];
this.prefixSumValidIndex = -1;
this.whitespaceId2Index = {};
this.lastWhitespaceId = 0;
this._heights = [];
this._ids = [];
this._afterLineNumbers = [];
this._ordinals = [];
this._prefixSum = [];
this._prefixSumValidIndex = -1;
this._whitespaceId2Index = {};
this._lastWhitespaceId = 0;
}
/**
......@@ -70,12 +70,11 @@ export class WhitespaceComputer {
* If the value is already present in the sorted array, the insertion index will be after the already existing value.
*/
public static findInsertionIndex(sortedArray: number[], value: number, ordinals: number[], valueOrdinal: number): number {
var low = 0,
high = sortedArray.length,
mid: number;
let low = 0;
let high = sortedArray.length;
while (low < high) {
mid = ((low + high) >>> 1);
let mid = ((low + high) >>> 1);
if (value === sortedArray[mid]) {
if (valueOrdinal < ordinals[mid]) {
......@@ -107,38 +106,41 @@ export class WhitespaceComputer {
ordinal = ordinal | 0;
heightInPx = heightInPx | 0;
var id = (++this.lastWhitespaceId);
var insertionIndex = WhitespaceComputer.findInsertionIndex(this.afterLineNumbers, afterLineNumber, this.ordinals, ordinal);
this.insertWhitespaceAtIndex(id, insertionIndex, afterLineNumber, ordinal, heightInPx);
let id = (++this._lastWhitespaceId);
let insertionIndex = WhitespaceComputer.findInsertionIndex(this._afterLineNumbers, afterLineNumber, this._ordinals, ordinal);
this._insertWhitespaceAtIndex(id, insertionIndex, afterLineNumber, ordinal, heightInPx);
return id;
}
private insertWhitespaceAtIndex(id: number, insertIndex: number, afterLineNumber: number, ordinal: number, heightInPx: number): void {
private _insertWhitespaceAtIndex(id: number, insertIndex: number, afterLineNumber: number, ordinal: number, heightInPx: number): void {
id = id | 0;
insertIndex = insertIndex | 0;
afterLineNumber = afterLineNumber | 0;
ordinal = ordinal | 0;
heightInPx = heightInPx | 0;
this.heights.splice(insertIndex, 0, heightInPx);
this.ids.splice(insertIndex, 0, id);
this.afterLineNumbers.splice(insertIndex, 0, afterLineNumber);
this.ordinals.splice(insertIndex, 0, ordinal);
this.prefixSum.splice(insertIndex, 0, 0);
this._heights.splice(insertIndex, 0, heightInPx);
this._ids.splice(insertIndex, 0, id);
this._afterLineNumbers.splice(insertIndex, 0, afterLineNumber);
this._ordinals.splice(insertIndex, 0, ordinal);
this._prefixSum.splice(insertIndex, 0, 0);
let keys = Object.keys(this.whitespaceId2Index);
let keys = Object.keys(this._whitespaceId2Index);
for (let i = 0, len = keys.length; i < len; i++) {
let sid = keys[i];
let oldIndex = this.whitespaceId2Index[sid];
let oldIndex = this._whitespaceId2Index[sid];
if (oldIndex >= insertIndex) {
this.whitespaceId2Index[sid] = oldIndex + 1;
this._whitespaceId2Index[sid] = oldIndex + 1;
}
}
this.whitespaceId2Index[id.toString()] = insertIndex;
this.prefixSumValidIndex = Math.min(this.prefixSumValidIndex, insertIndex - 1);
this._whitespaceId2Index[id.toString()] = insertIndex;
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, insertIndex - 1);
}
/**
* Change properties associated with a certain whitespace.
*/
public changeWhitespace(id: number, newAfterLineNumber: number, newHeight: number): boolean {
id = id | 0;
newAfterLineNumber = newAfterLineNumber | 0;
......@@ -161,12 +163,12 @@ export class WhitespaceComputer {
id = id | 0;
newHeightInPx = newHeightInPx | 0;
var sid = id.toString();
if (this.whitespaceId2Index.hasOwnProperty(sid)) {
var index = this.whitespaceId2Index[sid];
if (this.heights[index] !== newHeightInPx) {
this.heights[index] = newHeightInPx;
this.prefixSumValidIndex = Math.min(this.prefixSumValidIndex, index - 1);
let sid = id.toString();
if (this._whitespaceId2Index.hasOwnProperty(sid)) {
let index = this._whitespaceId2Index[sid];
if (this._heights[index] !== newHeightInPx) {
this._heights[index] = newHeightInPx;
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, index - 1);
return true;
}
}
......@@ -184,24 +186,24 @@ export class WhitespaceComputer {
id = id | 0;
newAfterLineNumber = newAfterLineNumber | 0;
var sid = id.toString();
if (this.whitespaceId2Index.hasOwnProperty(sid)) {
var index = this.whitespaceId2Index[sid];
if (this.afterLineNumbers[index] !== newAfterLineNumber) {
let sid = id.toString();
if (this._whitespaceId2Index.hasOwnProperty(sid)) {
let index = this._whitespaceId2Index[sid];
if (this._afterLineNumbers[index] !== newAfterLineNumber) {
// `afterLineNumber` changed for this whitespace
// Record old ordinal
var ordinal = this.ordinals[index];
let ordinal = this._ordinals[index];
// Record old height
var heightInPx = this.heights[index];
let heightInPx = this._heights[index];
// Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace
this.removeWhitespace(id);
// And add it again
var insertionIndex = WhitespaceComputer.findInsertionIndex(this.afterLineNumbers, newAfterLineNumber, this.ordinals, ordinal);
this.insertWhitespaceAtIndex(id, insertionIndex, newAfterLineNumber, ordinal, heightInPx);
let insertionIndex = WhitespaceComputer.findInsertionIndex(this._afterLineNumbers, newAfterLineNumber, this._ordinals, ordinal);
this._insertWhitespaceAtIndex(id, insertionIndex, newAfterLineNumber, ordinal, heightInPx);
return true;
}
......@@ -218,34 +220,34 @@ export class WhitespaceComputer {
public removeWhitespace(id: number): boolean {
id = id | 0;
var sid = id.toString();
let sid = id.toString();
if (this.whitespaceId2Index.hasOwnProperty(sid)) {
var index = this.whitespaceId2Index[sid];
delete this.whitespaceId2Index[sid];
this.removeWhitespaceAtIndex(index);
if (this._whitespaceId2Index.hasOwnProperty(sid)) {
let index = this._whitespaceId2Index[sid];
delete this._whitespaceId2Index[sid];
this._removeWhitespaceAtIndex(index);
return true;
}
return false;
}
private removeWhitespaceAtIndex(removeIndex: number): void {
private _removeWhitespaceAtIndex(removeIndex: number): void {
removeIndex = removeIndex | 0;
this.heights.splice(removeIndex, 1);
this.ids.splice(removeIndex, 1);
this.afterLineNumbers.splice(removeIndex, 1);
this.ordinals.splice(removeIndex, 1);
this.prefixSum.splice(removeIndex, 1);
this.prefixSumValidIndex = Math.min(this.prefixSumValidIndex, removeIndex - 1);
this._heights.splice(removeIndex, 1);
this._ids.splice(removeIndex, 1);
this._afterLineNumbers.splice(removeIndex, 1);
this._ordinals.splice(removeIndex, 1);
this._prefixSum.splice(removeIndex, 1);
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);
let keys = Object.keys(this.whitespaceId2Index);
let keys = Object.keys(this._whitespaceId2Index);
for (let i = 0, len = keys.length; i < len; i++) {
let sid = keys[i];
let oldIndex = this.whitespaceId2Index[sid];
let oldIndex = this._whitespaceId2Index[sid];
if (oldIndex >= removeIndex) {
this.whitespaceId2Index[sid] = oldIndex - 1;
this._whitespaceId2Index[sid] = oldIndex - 1;
}
}
}
......@@ -261,21 +263,17 @@ export class WhitespaceComputer {
fromLineNumber = fromLineNumber | 0;
toLineNumber = toLineNumber | 0;
var afterLineNumber: number,
i: number,
len: number;
for (i = 0, len = this.afterLineNumbers.length; i < len; i++) {
afterLineNumber = this.afterLineNumbers[i];
for (let i = 0, len = this._afterLineNumbers.length; i < len; i++) {
let afterLineNumber = this._afterLineNumbers[i];
if (fromLineNumber <= afterLineNumber && afterLineNumber <= toLineNumber) {
// The line this whitespace was after has been deleted
// => move whitespace to before first deleted line
this.afterLineNumbers[i] = fromLineNumber - 1;
this._afterLineNumbers[i] = fromLineNumber - 1;
} else if (afterLineNumber > toLineNumber) {
// The line this whitespace was after has been moved up
// => move whitespace up
this.afterLineNumbers[i] -= (toLineNumber - fromLineNumber + 1);
this._afterLineNumbers[i] -= (toLineNumber - fromLineNumber + 1);
}
}
}
......@@ -291,15 +289,11 @@ export class WhitespaceComputer {
fromLineNumber = fromLineNumber | 0;
toLineNumber = toLineNumber | 0;
var afterLineNumber: number,
i: number,
len: number;
for (i = 0, len = this.afterLineNumbers.length; i < len; i++) {
afterLineNumber = this.afterLineNumbers[i];
for (let i = 0, len = this._afterLineNumbers.length; i < len; i++) {
let afterLineNumber = this._afterLineNumbers[i];
if (fromLineNumber <= afterLineNumber) {
this.afterLineNumbers[i] += (toLineNumber - fromLineNumber + 1);
this._afterLineNumbers[i] += (toLineNumber - fromLineNumber + 1);
}
}
}
......@@ -308,10 +302,10 @@ export class WhitespaceComputer {
* Get the sum of all the whitespaces.
*/
public getTotalHeight(): number {
if (this.heights.length === 0) {
if (this._heights.length === 0) {
return 0;
}
return this.getAccumulatedHeight(this.heights.length - 1);
return this.getAccumulatedHeight(this._heights.length - 1);
}
/**
......@@ -324,17 +318,17 @@ export class WhitespaceComputer {
public getAccumulatedHeight(index: number): number {
index = index | 0;
var startIndex = Math.max(0, this.prefixSumValidIndex + 1);
let startIndex = Math.max(0, this._prefixSumValidIndex + 1);
if (startIndex === 0) {
this.prefixSum[0] = this.heights[0];
this._prefixSum[0] = this._heights[0];
startIndex++;
}
for (var i = startIndex; i <= index; i++) {
this.prefixSum[i] = this.prefixSum[i - 1] + this.heights[i];
for (let i = startIndex; i <= index; i++) {
this._prefixSum[i] = this._prefixSum[i - 1] + this._heights[i];
}
this.prefixSumValidIndex = Math.max(this.prefixSumValidIndex, index);
return this.prefixSum[index];
this._prefixSumValidIndex = Math.max(this._prefixSumValidIndex, index);
return this._prefixSum[index];
}
/**
......@@ -346,7 +340,7 @@ export class WhitespaceComputer {
public getAccumulatedHeightBeforeLineNumber(lineNumber: number): number {
lineNumber = lineNumber | 0;
var lastWhitespaceBeforeLineNumber = this.findLastWhitespaceBeforeLineNumber(lineNumber);
let lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
if (lastWhitespaceBeforeLineNumber === -1) {
return 0;
......@@ -355,11 +349,11 @@ export class WhitespaceComputer {
return this.getAccumulatedHeight(lastWhitespaceBeforeLineNumber);
}
private findLastWhitespaceBeforeLineNumber(lineNumber: number): number {
private _findLastWhitespaceBeforeLineNumber(lineNumber: number): number {
lineNumber = lineNumber | 0;
// Find the whitespace before line number
let afterLineNumbers = this.afterLineNumbers;
let afterLineNumbers = this._afterLineNumbers;
let low = 0;
let high = afterLineNumbers.length - 1;
......@@ -382,13 +376,13 @@ export class WhitespaceComputer {
return -1;
}
private findFirstWhitespaceAfterLineNumber(lineNumber: number): number {
private _findFirstWhitespaceAfterLineNumber(lineNumber: number): number {
lineNumber = lineNumber | 0;
var lastWhitespaceBeforeLineNumber = this.findLastWhitespaceBeforeLineNumber(lineNumber);
var firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;
let lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
let firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;
if (firstWhitespaceAfterLineNumber < this.heights.length) {
if (firstWhitespaceAfterLineNumber < this._heights.length) {
return firstWhitespaceAfterLineNumber;
}
......@@ -402,14 +396,14 @@ export class WhitespaceComputer {
public getFirstWhitespaceIndexAfterLineNumber(lineNumber: number): number {
lineNumber = lineNumber | 0;
return this.findFirstWhitespaceAfterLineNumber(lineNumber);
return this._findFirstWhitespaceAfterLineNumber(lineNumber);
}
/**
* The number of whitespaces.
*/
public getCount(): number {
return this.heights.length;
return this._heights.length;
}
/**
......@@ -421,7 +415,7 @@ export class WhitespaceComputer {
public getAfterLineNumberForWhitespaceIndex(index: number): number {
index = index | 0;
return this.afterLineNumbers[index];
return this._afterLineNumbers[index];
}
/**
......@@ -433,7 +427,7 @@ export class WhitespaceComputer {
public getIdForWhitespaceIndex(index: number): number {
index = index | 0;
return this.ids[index];
return this._ids[index];
}
/**
......@@ -445,20 +439,23 @@ export class WhitespaceComputer {
public getHeightForWhitespaceIndex(index: number): number {
index = index | 0;
return this.heights[index];
return this._heights[index];
}
/**
* Get all whitespaces.
*/
public getWhitespaces(deviceLineHeight: number): IEditorWhitespace[] {
deviceLineHeight = deviceLineHeight | 0;
var result: IEditorWhitespace[] = [];
for (var i = 0; i < this.heights.length; i++) {
let result: IEditorWhitespace[] = [];
for (let i = 0; i < this._heights.length; i++) {
result.push({
id: this.ids[i],
afterLineNumber: this.afterLineNumbers[i],
heightInLines: this.heights[i] / deviceLineHeight
id: this._ids[i],
afterLineNumber: this._afterLineNumbers[i],
heightInLines: this._heights[i] / deviceLineHeight
});
}
return result;
}
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册