提交 d0e2ea00 编写于 作者: A Alex Dima

Extract RangeUtil to its own file

上级 2e8f2350
/*---------------------------------------------------------------------------------------------
* 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 {HorizontalRange} from 'vs/editor/common/editorCommon';
export class RangeUtil {
/**
* Reusing the same range here
* because IE is buggy and constantly freezes when using a large number
* of ranges and calling .detach on them
*/
private static _handyReadyRange:Range;
private static _createRange(): Range {
if (!this._handyReadyRange) {
this._handyReadyRange = document.createRange();
}
return this._handyReadyRange;
}
private static _detachRange(range:Range, endNode:HTMLElement): void {
// Move range out of the span node, IE doesn't like having many ranges in
// the same spot and will act badly for lines containing dashes ('-')
range.selectNodeContents(endNode);
}
private static _readClientRects(startElement:Node, startOffset:number, endElement:Node, endOffset:number, endNode:HTMLElement): ClientRectList {
let range = this._createRange();
try {
range.setStart(startElement, startOffset);
range.setEnd(endElement, endOffset);
return range.getClientRects();
} catch (e) {
// This is life ...
return null;
} finally {
this._detachRange(range, endNode);
}
}
private static _createHorizontalRangesFromClientRects(clientRects:ClientRectList, clientRectDeltaLeft:number, scaleRatio:number): HorizontalRange[] {
if (!clientRects || clientRects.length === 0) {
return null;
}
let result:HorizontalRange[] = [];
let prevLeft = Math.max(0, clientRects[0].left * scaleRatio - clientRectDeltaLeft);
let prevWidth = clientRects[0].width * scaleRatio;
for (let i = 1, len = clientRects.length; i < len; i++) {
let myLeft = Math.max(0, clientRects[i].left * scaleRatio - clientRectDeltaLeft);
let myWidth = clientRects[i].width * scaleRatio;
if (myLeft < prevLeft) {
console.error('Unexpected: RangeUtil._createHorizontalRangesFromClientRects: client rects are not sorted');
}
if (prevLeft + prevWidth + 0.9 /* account for browser's rounding errors*/ >= myLeft) {
prevWidth = Math.max(prevWidth, myLeft + myWidth - prevLeft);
} else {
result.push(new HorizontalRange(prevLeft, prevWidth));
prevLeft = myLeft;
prevWidth = myWidth;
}
}
result.push(new HorizontalRange(prevLeft, prevWidth));
return result;
}
public static readHorizontalRanges(domNode:HTMLElement, startChildIndex:number, startOffset:number, endChildIndex:number, endOffset:number, clientRectDeltaLeft:number, scaleRatio:number, endNode:HTMLElement): HorizontalRange[] {
// Panic check
let min = 0;
let max = domNode.children.length - 1;
if (min > max) {
return null;
}
startChildIndex = Math.min(max, Math.max(min, startChildIndex));
endChildIndex = Math.min(max, Math.max(min, endChildIndex));
// If crossing over to a span only to select offset 0, then use the previous span's maximum offset
// Chrome is buggy and doesn't handle 0 offsets well sometimes.
if (startChildIndex !== endChildIndex) {
if (endChildIndex > 0 && endOffset === 0) {
endChildIndex--;
endOffset = Number.MAX_VALUE;
}
}
let startElement = domNode.children[startChildIndex].firstChild;
let endElement = domNode.children[endChildIndex].firstChild;
if (!startElement || !endElement) {
return null;
}
startOffset = Math.min(startElement.textContent.length, Math.max(0, startOffset));
endOffset = Math.min(endElement.textContent.length, Math.max(0, endOffset));
let clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, scaleRatio);
}
}
......@@ -11,6 +11,7 @@ import {ILineParts, createLineParts} from 'vs/editor/common/viewLayout/viewLineP
import {renderLine, RenderLineInput} from 'vs/editor/common/viewLayout/viewLineRenderer';
import {ClassNames, IViewContext} from 'vs/editor/browser/editorBrowser';
import {IVisibleLineData} from 'vs/editor/browser/view/viewLayer';
import {RangeUtil} from 'vs/editor/browser/viewParts/lines/rangeUtil';
export class ViewLine implements IVisibleLineData {
......@@ -412,107 +413,6 @@ class WebKitViewLine extends ViewLine {
}
}
class RangeUtil {
/**
* Reusing the same range here
* because IE is buggy and constantly freezes when using a large number
* of ranges and calling .detach on them
*/
private static _handyReadyRange:Range;
private static _createRange(): Range {
if (!this._handyReadyRange) {
this._handyReadyRange = document.createRange();
}
return this._handyReadyRange;
}
private static _detachRange(range:Range, endNode:HTMLElement): void {
// Move range out of the span node, IE doesn't like having many ranges in
// the same spot and will act badly for lines containing dashes ('-')
range.selectNodeContents(endNode);
}
private static _readClientRects(startElement:Node, startOffset:number, endElement:Node, endOffset:number, endNode:HTMLElement): ClientRectList {
let range = this._createRange();
try {
range.setStart(startElement, startOffset);
range.setEnd(endElement, endOffset);
return range.getClientRects();
} catch (e) {
// This is life ...
return null;
} finally {
this._detachRange(range, endNode);
}
}
private static _createHorizontalRangesFromClientRects(clientRects:ClientRectList, clientRectDeltaLeft:number, scaleRatio:number): HorizontalRange[] {
if (!clientRects || clientRects.length === 0) {
return null;
}
let result:HorizontalRange[] = [];
let prevLeft = Math.max(0, clientRects[0].left * scaleRatio - clientRectDeltaLeft);
let prevWidth = clientRects[0].width * scaleRatio;
for (let i = 1, len = clientRects.length; i < len; i++) {
let myLeft = Math.max(0, clientRects[i].left * scaleRatio - clientRectDeltaLeft);
let myWidth = clientRects[i].width * scaleRatio;
if (myLeft < prevLeft) {
console.error('Unexpected: RangeUtil._createHorizontalRangesFromClientRects: client rects are not sorted');
}
if (prevLeft + prevWidth + 0.9 /* account for browser's rounding errors*/ >= myLeft) {
prevWidth = Math.max(prevWidth, myLeft + myWidth - prevLeft);
} else {
result.push(new HorizontalRange(prevLeft, prevWidth));
prevLeft = myLeft;
prevWidth = myWidth;
}
}
result.push(new HorizontalRange(prevLeft, prevWidth));
return result;
}
public static readHorizontalRanges(domNode:HTMLElement, startChildIndex:number, startOffset:number, endChildIndex:number, endOffset:number, clientRectDeltaLeft:number, scaleRatio:number, endNode:HTMLElement): HorizontalRange[] {
// Panic check
let min = 0;
let max = domNode.children.length - 1;
if (min > max) {
return null;
}
startChildIndex = Math.min(max, Math.max(min, startChildIndex));
endChildIndex = Math.min(max, Math.max(min, endChildIndex));
// If crossing over to a span only to select offset 0, then use the previous span's maximum offset
// Chrome is buggy and doesn't handle 0 offsets well sometimes.
if (startChildIndex !== endChildIndex) {
if (endChildIndex > 0 && endOffset === 0) {
endChildIndex--;
endOffset = Number.MAX_VALUE;
}
}
let startElement = domNode.children[startChildIndex].firstChild;
let endElement = domNode.children[endChildIndex].firstChild;
if (!startElement || !endElement) {
return null;
}
startOffset = Math.min(startElement.textContent.length, Math.max(0, startOffset));
endOffset = Math.min(endElement.textContent.length, Math.max(0, endOffset));
let clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft, scaleRatio);
}
}
function findIndexInArrayWithMax(lineParts:ILineParts, desiredIndex: number, maxResult:number): number {
let r = lineParts.findIndexOfOffset(desiredIndex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册