提交 3a093b39 编写于 作者: A Alex Dima

Clean up cursorMove

上级 386f9929
......@@ -46,6 +46,8 @@ export interface ICodeEditorHelper {
delegateVerticalScrollbarMouseDown(browserEvent: MouseEvent): void;
getOffsetForColumn(lineNumber: number, column: number): number;
getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget;
getCompletelyVisibleViewRange(): Range;
}
/**
......@@ -59,11 +61,6 @@ export interface IView extends IDisposable {
createOverviewRuler(cssClassName: string, minimumHeight: number, maximumHeight: number): IOverviewRuler;
getCodeEditorHelper(): ICodeEditorHelper;
/**
* Returns the range of lines in the view port which are completely visible.
*/
getCompletelyVisibleLinesRangeInViewport(): Range;
change(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean;
getWhitespaces(): editorCommon.IEditorWhitespace[];
......
......@@ -574,6 +574,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
}
return this.layoutProvider.getScrollWidth();
},
getScrollLeft: () => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.getScrollLeft: View is disposed');
......@@ -587,6 +588,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
}
return this.layoutProvider.getScrollHeight();
},
getScrollTop: () => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.getScrollTop: View is disposed');
......@@ -594,11 +596,11 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
return this.layoutProvider.getScrollTop();
},
setScrollPosition: (position: editorCommon.INewScrollPosition) => {
setScrollPosition: (scrollPosition: editorCommon.INewScrollPosition) => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.setScrollPosition: View is disposed');
}
this.layoutProvider.setScrollPosition(position);
this.layoutProvider.setScrollPosition(scrollPosition);
},
getVerticalOffsetForPosition: (modelLineNumber: number, modelColumn: number) => {
......@@ -612,12 +614,14 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
let viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
return this.layoutProvider.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
},
delegateVerticalScrollbarMouseDown: (browserEvent: MouseEvent) => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.delegateVerticalScrollbarMouseDown: View is disposed');
}
this._scrollbar.delegateVerticalScrollbarMouseDown(browserEvent);
},
getOffsetForColumn: (modelLineNumber: number, modelColumn: number) => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.getOffsetForColumn: View is disposed');
......@@ -640,6 +644,24 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
throw new Error('ViewImpl.codeEditorHelper.getTargetAtClientPoint: View is disposed');
}
return this.pointerHandler.getTargetAtClientPoint(clientX, clientY);
},
getCompletelyVisibleViewRange: (): Range => {
if (this._isDisposed) {
throw new Error('ViewImpl.codeEditorHelper.getCompletelyVisibleViewRange: View is disposed');
}
// Ensure we share the state of the view model
this._flushAnyAccumulatedEvents();
const partialData = this.layoutProvider.getLinesViewportData();
const startViewLineNumber = partialData.completelyVisibleStartLineNumber;
const endViewLineNumber = partialData.completelyVisibleEndLineNumber;
return new Range(
startViewLineNumber, this._context.model.getLineMinColumn(startViewLineNumber),
endViewLineNumber, this._context.model.getLineMaxColumn(endViewLineNumber)
);
}
};
......@@ -647,22 +669,6 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
return this.codeEditorHelper;
}
public getCompletelyVisibleLinesRangeInViewport(): Range {
if (this._isDisposed) {
throw new Error('ViewImpl.getCompletelyVisibleLinesRangeInViewport: View is disposed');
}
const partialData = this.layoutProvider.getLinesViewportData();
const completelyVisibleLinesRange = new Range(
partialData.completelyVisibleStartLineNumber,
1,
partialData.completelyVisibleEndLineNumber,
this._context.model.getLineMaxColumn(partialData.completelyVisibleEndLineNumber)
);
return this._context.model.coordinatesConverter.convertViewRangeToModelRange(completelyVisibleLinesRange);
}
public getInternalEventBus(): IEventEmitter {
if (this._isDisposed) {
throw new Error('ViewImpl.getInternalEventBus: View is disposed');
......
......@@ -170,11 +170,16 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
return this.viewModel.getCenteredRangeInViewport();
}
public getCompletelyVisibleLinesRangeInViewport(): Range {
protected _getCompletelyVisibleViewRange(): Range {
if (!this.hasView) {
return null;
}
return this._view.getCompletelyVisibleLinesRangeInViewport();
return this._view.getCodeEditorHelper().getCompletelyVisibleViewRange();
}
public getCompletelyVisibleLinesRangeInViewport(): Range {
const viewRange = this._getCompletelyVisibleViewRange();
return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(viewRange);
}
public getScrollWidth(): number {
......
......@@ -223,7 +223,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
public abstract getCenteredRangeInViewport(): Range;
public abstract getCompletelyVisibleLinesRangeInViewport(): Range;
protected abstract _getCompletelyVisibleViewRange(): Range;
public getVisibleColumnFromPosition(rawPosition: editorCommon.IPosition): number {
if (!this.model) {
......@@ -761,12 +761,9 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
let viewModelHelper: IViewModelHelper = {
viewModel: this.viewModel,
coordinatesConverter: this.viewModel.coordinatesConverter,
getCurrentCompletelyVisibleViewLinesRangeInViewport: () => {
return this.viewModel.coordinatesConverter.convertModelRangeToViewRange(this.getCompletelyVisibleLinesRangeInViewport());
},
getCurrentCompletelyVisibleModelLinesRangeInViewport: () => {
return this.getCompletelyVisibleLinesRangeInViewport();
},
getCompletelyVisibleViewRange: (): Range => {
return this._getCompletelyVisibleViewRange();
}
};
this.listenersToRemove.push(this.model.addBulkListener((events) => {
......
......@@ -14,7 +14,7 @@ import * as strings from 'vs/base/common/strings';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
export interface IFindWordResult {
interface IFindWordResult {
/**
* The index where the word starts.
*/
......@@ -29,7 +29,7 @@ export interface IFindWordResult {
wordType: WordType;
}
export const enum WordType {
const enum WordType {
None = 0,
Regular = 1,
Separator = 2
......@@ -82,12 +82,12 @@ export class WordOperations {
return { start: start, end: end, wordType: wordType };
}
private static findPreviousWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult {
private static _findPreviousWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult {
let lineContent = model.getLineContent(position.lineNumber);
return this._findPreviousWordOnLine(lineContent, wordSeparators, position);
return this._doFindPreviousWordOnLine(lineContent, wordSeparators, position);
}
private static _findPreviousWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult {
private static _doFindPreviousWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult {
let wordType = WordType.None;
for (let chIndex = position.column - 2; chIndex >= 0; chIndex--) {
let chCode = lineContent.charCodeAt(chIndex);
......@@ -136,12 +136,12 @@ export class WordOperations {
return len;
}
private static findNextWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult {
private static _findNextWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult {
let lineContent = model.getLineContent(position.lineNumber);
return this._findNextWordOnLine(lineContent, wordSeparators, position);
return this._doFindNextWordOnLine(lineContent, wordSeparators, position);
}
private static _findNextWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult {
private static _doFindNextWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult {
let wordType = WordType.None;
let len = lineContent.length;
......@@ -202,7 +202,7 @@ export class WordOperations {
}
}
let prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, column));
let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, column));
if (wordNavigationType === WordNavigationType.WordStart) {
if (prevWordOnLine) {
......@@ -212,7 +212,7 @@ export class WordOperations {
}
} else {
if (prevWordOnLine && column <= prevWordOnLine.end + 1) {
prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));
prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));
}
if (prevWordOnLine) {
column = prevWordOnLine.end + 1;
......@@ -235,7 +235,7 @@ export class WordOperations {
}
}
let nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, new Position(lineNumber, column));
let nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, column));
if (wordNavigationType === WordNavigationType.WordEnd) {
if (nextWordOnLine) {
......@@ -245,7 +245,7 @@ export class WordOperations {
}
} else {
if (nextWordOnLine && column >= nextWordOnLine.start + 1) {
nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
}
if (nextWordOnLine) {
column = nextWordOnLine.start + 1;
......@@ -267,7 +267,7 @@ export class WordOperations {
return null;
}
public static _deleteWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
public static deleteWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
if (!selection.isEmpty()) {
return selection;
}
......@@ -289,7 +289,7 @@ export class WordOperations {
}
}
let prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, position);
let prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);
if (wordNavigationType === WordNavigationType.WordStart) {
if (prevWordOnLine) {
......@@ -299,7 +299,7 @@ export class WordOperations {
column = 1;
} else {
lineNumber--;
prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, model.getLineMaxColumn(lineNumber)));
prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, model.getLineMaxColumn(lineNumber)));
if (prevWordOnLine) {
column = prevWordOnLine.start + 1;
} else {
......@@ -309,7 +309,7 @@ export class WordOperations {
}
} else {
if (prevWordOnLine && column <= prevWordOnLine.end + 1) {
prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));
prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, prevWordOnLine.start + 1));
}
if (prevWordOnLine) {
column = prevWordOnLine.end + 1;
......@@ -318,7 +318,7 @@ export class WordOperations {
column = 1;
} else {
lineNumber--;
prevWordOnLine = WordOperations.findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, model.getLineMaxColumn(lineNumber)));
prevWordOnLine = WordOperations._findPreviousWordOnLine(wordSeparators, model, new Position(lineNumber, model.getLineMaxColumn(lineNumber)));
if (prevWordOnLine) {
column = prevWordOnLine.end + 1;
} else {
......@@ -353,7 +353,7 @@ export class WordOperations {
return null;
}
public static _deleteWordRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
public static deleteWordRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
if (!selection.isEmpty()) {
return selection;
}
......@@ -377,7 +377,7 @@ export class WordOperations {
}
}
let nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, position);
let nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, position);
if (wordNavigationType === WordNavigationType.WordEnd) {
if (nextWordOnLine) {
......@@ -387,7 +387,7 @@ export class WordOperations {
column = maxColumn;
} else {
lineNumber++;
nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));
if (nextWordOnLine) {
column = nextWordOnLine.start + 1;
} else {
......@@ -397,7 +397,7 @@ export class WordOperations {
}
} else {
if (nextWordOnLine && column >= nextWordOnLine.start + 1) {
nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
}
if (nextWordOnLine) {
column = nextWordOnLine.start + 1;
......@@ -406,7 +406,7 @@ export class WordOperations {
column = maxColumn;
} else {
lineNumber++;
nextWordOnLine = WordOperations.findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, 1));
if (nextWordOnLine) {
column = nextWordOnLine.start + 1;
} else {
......@@ -421,9 +421,9 @@ export class WordOperations {
public static word(config: CursorConfiguration, model: ICursorSimpleModel, cursor: SingleCursorState, inSelectionMode: boolean, position: Position): SingleMoveOperationResult {
const wordSeparators = getMapForWordSeparators(config.wordSeparators);
let prevWord = WordOperations.findPreviousWordOnLine(wordSeparators, model, position);
let prevWord = WordOperations._findPreviousWordOnLine(wordSeparators, model, position);
let isInPrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start < position.column - 1 && position.column - 1 <= prevWord.end);
let nextWord = WordOperations.findNextWordOnLine(wordSeparators, model, position);
let nextWord = WordOperations._findNextWordOnLine(wordSeparators, model, position);
let isInNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start < position.column - 1 && position.column - 1 <= nextWord.end);
if (!inSelectionMode || !cursor.hasSelection()) {
......
......@@ -56,9 +56,7 @@ export interface IViewModelHelper {
viewModel: ICursorSimpleModel;
getCurrentCompletelyVisibleViewLinesRangeInViewport(): Range;
getCurrentCompletelyVisibleModelLinesRangeInViewport(): Range;
getCompletelyVisibleViewRange(): Range;
}
export interface IOneCursorState {
......@@ -70,16 +68,13 @@ export interface IOneCursorState {
selectionStartLeftoverVisibleColumns: number;
}
export interface IOneCursor {
readonly modelState: SingleCursorState;
readonly viewState: SingleCursorState;
readonly config: CursorConfiguration;
}
export class MoveOperationResult {
class MoveOperationResult {
readonly modelState: SingleCursorState;
readonly viewState: SingleCursorState;
readonly ensureInEditableRange: boolean;
......@@ -96,7 +91,6 @@ export class MoveOperationResult {
this.ensureInEditableRange = ensureInEditableRange;
this.reason = reason;
}
}
export class OneCursor implements IOneCursor {
......@@ -406,9 +400,18 @@ export class OneCursor implements IOneCursor {
return this.coordinatesConverter.convertModelPositionToViewPosition(new Position(lineNumber, column));
}
public getCurrentCompletelyVisibleViewLinesRangeInViewport(): Range {
return this.viewModelHelper.getCompletelyVisibleViewRange();
}
public getCurrentCompletelyVisibleModelLinesRangeInViewport(): Range {
const viewRange = this.viewModelHelper.getCompletelyVisibleViewRange();
return this.coordinatesConverter.convertViewRangeToModelRange(viewRange);
}
// -- model
public getRangeToRevealModelLinesBeforeViewPortTop(noOfLinesBeforeTop: number): Range {
let visibleModelRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let visibleModelRange = this.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let startLineNumber: number;
if (this.model.getLineMinColumn(visibleModelRange.startLineNumber) !== visibleModelRange.startColumn) {
......@@ -427,7 +430,7 @@ export class OneCursor implements IOneCursor {
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
}
public getRangeToRevealModelLinesAfterViewPortBottom(noOfLinesAfterBottom: number): Range {
let visibleModelRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let visibleModelRange = this.getCurrentCompletelyVisibleModelLinesRangeInViewport();
// Last line in the view port is not considered revealed because scroll bar would cover it
// Hence consider last line to reveal in the range
......@@ -438,55 +441,13 @@ export class OneCursor implements IOneCursor {
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
}
public getLineFromViewPortTop(lineFromTop: number = 1): number {
let visibleRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let startColumn = this.model.getLineMinColumn(visibleRange.startLineNumber);
// Use next line if the first line is partially visible
let visibleLineNumber = visibleRange.startColumn === startColumn ? visibleRange.startLineNumber : visibleRange.startLineNumber + 1;
visibleLineNumber = visibleLineNumber + lineFromTop - 1;
return visibleLineNumber > visibleRange.endLineNumber ? visibleRange.endLineNumber : visibleLineNumber;
}
public getCenterLineInViewPort(): number {
return Math.round((this.getLineFromViewPortTop() + this.getLineFromViewPortBottom() - 1) / 2);
}
public getLineFromViewPortBottom(lineFromBottom: number = 1): number {
let visibleRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let visibleLineNumber = visibleRange.endLineNumber - (lineFromBottom - 1);
return visibleLineNumber > visibleRange.startLineNumber ? visibleLineNumber : this.getLineFromViewPortTop();
}
// -- view
public isLastLineVisibleInViewPort(): boolean {
return this.viewModel.getLineCount() <= this.getCompletelyVisibleViewLinesRangeInViewport().getEndPosition().lineNumber;
}
public getCompletelyVisibleViewLinesRangeInViewport(): Range {
return this.viewModelHelper.getCurrentCompletelyVisibleViewLinesRangeInViewport();
}
public getRevealViewLinesRangeInViewport(): Range {
let visibleRange = this.getCompletelyVisibleViewLinesRangeInViewport().cloneRange();
if (!this.isLastLineVisibleInViewPort() && visibleRange.endLineNumber > visibleRange.startLineNumber) {
visibleRange = new Range(
visibleRange.startLineNumber,
visibleRange.startColumn,
visibleRange.endLineNumber - 1,
this.viewModel.getLineLastNonWhitespaceColumn(visibleRange.endLineNumber - 1)
);
}
return visibleRange;
}
public getNearestRevealViewPositionInViewport(): Position {
const position = this.viewState.position;
const revealRange = this.getRevealViewLinesRangeInViewport();
if (position.lineNumber < revealRange.startLineNumber) {
return new Position(revealRange.startLineNumber, this.viewModel.getLineFirstNonWhitespaceColumn(revealRange.startLineNumber));
}
if (position.lineNumber > revealRange.endLineNumber) {
return new Position(revealRange.endLineNumber, this.viewModel.getLineFirstNonWhitespaceColumn(revealRange.endLineNumber));
}
return position;
return this.getCurrentCompletelyVisibleViewLinesRangeInViewport();
}
// -------------------- END reading API
}
......@@ -515,66 +476,147 @@ export class OneCursorOp {
return true;
}
private static _getViewHalfLineSize(cursor: OneCursor, lineNumber: number): number {
return Math.round((cursor.viewModel.getLineMaxColumn(lineNumber) - cursor.viewModel.getLineMinColumn(lineNumber)) / 2);
}
public static move(cursor: OneCursor, moveParams: CursorMoveArguments, eventSource: string, ctx: IOneCursorOperationContext): boolean {
if (!moveParams.to) {
illegalArgument('to');
}
let inSelectionMode = !!moveParams.select;
let validatedViewPosition = cursor.viewState.position;
let viewLineNumber = validatedViewPosition.lineNumber;
let viewColumn: number;
let viewLineNumber = cursor.viewState.position.lineNumber;
switch (moveParams.to) {
case editorCommon.CursorMovePosition.Left:
return this._moveLeft(cursor, inSelectionMode, editorCommon.CursorMoveByUnit.HalfLine === moveParams.by ? this._getViewHalfLineSize(cursor, viewLineNumber) : moveParams.value, ctx);
case editorCommon.CursorMovePosition.Right:
return this._moveRight(cursor, inSelectionMode, editorCommon.CursorMoveByUnit.HalfLine === moveParams.by ? this._getViewHalfLineSize(cursor, viewLineNumber) : moveParams.value, ctx);
case editorCommon.CursorMovePosition.Up:
return this._moveUp(cursor, moveParams, ctx);
case editorCommon.CursorMovePosition.Down:
return this._moveDown(cursor, moveParams, ctx);
case editorCommon.CursorMovePosition.WrappedLineStart:
viewColumn = cursor.viewModel.getLineMinColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.WrappedLineFirstNonWhitespaceCharacter:
viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.WrappedLineColumnCenter:
viewColumn = Math.round((cursor.viewModel.getLineMaxColumn(viewLineNumber) + cursor.viewModel.getLineMinColumn(viewLineNumber)) / 2);
break;
case editorCommon.CursorMovePosition.WrappedLineEnd:
viewColumn = cursor.viewModel.getLineMaxColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.WrappedLineLastNonWhitespaceCharacter:
viewColumn = cursor.viewModel.getLineLastNonWhitespaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.ViewPortTop:
viewLineNumber = cursor.convertModelPositionToViewPosition(cursor.getLineFromViewPortTop(moveParams.value), 1).lineNumber;
viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.ViewPortBottom:
viewLineNumber = cursor.convertModelPositionToViewPosition(cursor.getLineFromViewPortBottom(moveParams.value), 1).lineNumber;;
viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.ViewPortCenter:
viewLineNumber = cursor.convertModelPositionToViewPosition(cursor.getCenterLineInViewPort(), 1).lineNumber;;
viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.ViewPortIfOutside:
const position = cursor.getNearestRevealViewPositionInViewport();
viewLineNumber = position.lineNumber;
viewColumn = position.column;
break;
default:
return false;
case editorCommon.CursorMovePosition.Left: {
if (moveParams.by === editorCommon.CursorMoveByUnit.HalfLine) {
// Move left by half the current line length
const halfLine = Math.round(cursor.viewModel.getLineContent(viewLineNumber).length / 2);
return this._moveLeft(cursor, inSelectionMode, halfLine, ctx);
} else {
// Move left by `moveParams.value` columns
return this._moveLeft(cursor, inSelectionMode, moveParams.value, ctx);
}
}
case editorCommon.CursorMovePosition.Right: {
if (moveParams.by === editorCommon.CursorMoveByUnit.HalfLine) {
// Move right by half the current line length
const halfLine = Math.round(cursor.viewModel.getLineContent(viewLineNumber).length / 2);
return this._moveRight(cursor, inSelectionMode, halfLine, ctx);
} else {
// Move right by `moveParams.value` columns
return this._moveRight(cursor, inSelectionMode, moveParams.value, ctx);
}
}
case editorCommon.CursorMovePosition.Up: {
const linesCount = (moveParams.isPaged ? (moveParams.pageSize || cursor.config.pageSize) : moveParams.value) || 1;
if (moveParams.by === editorCommon.CursorMoveByUnit.WrappedLine) {
// Move up by `linesCount` view lines
return this._moveUpByViewLines(cursor, inSelectionMode, linesCount, ctx);
} else {
// Move up by `linesCount` model lines
return this._moveUpByModelLines(cursor, inSelectionMode, linesCount, ctx);
}
}
case editorCommon.CursorMovePosition.Down: {
const linesCount = (moveParams.isPaged ? (moveParams.pageSize || cursor.config.pageSize) : moveParams.value) || 1;
if (editorCommon.CursorMoveByUnit.WrappedLine === moveParams.by) {
// Move down by `linesCount` view lines
return this._moveDownByViewLines(cursor, inSelectionMode, linesCount, ctx);
} else {
// Move down by `linesCount` model lines
return this._moveDownByModelLines(cursor, inSelectionMode, linesCount, ctx);
}
}
case editorCommon.CursorMovePosition.WrappedLineStart: {
// Move to the beginning of the current view line
const viewColumn = cursor.viewModel.getLineMinColumn(viewLineNumber);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
case editorCommon.CursorMovePosition.WrappedLineFirstNonWhitespaceCharacter: {
// Move to the first non-whitespace column of the current view line
const viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
case editorCommon.CursorMovePosition.WrappedLineColumnCenter: {
// Move to the "center" of the current view line
const viewColumn = Math.round((cursor.viewModel.getLineMaxColumn(viewLineNumber) + cursor.viewModel.getLineMinColumn(viewLineNumber)) / 2);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
case editorCommon.CursorMovePosition.WrappedLineEnd: {
// Move to the end of the current view line
const viewColumn = cursor.viewModel.getLineMaxColumn(viewLineNumber);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
case editorCommon.CursorMovePosition.WrappedLineLastNonWhitespaceCharacter: {
// Move to the last non-whitespace column of the current view line
const viewColumn = cursor.viewModel.getLineLastNonWhitespaceColumn(viewLineNumber);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
case editorCommon.CursorMovePosition.ViewPortTop: {
// Move to the nth line start in the viewport (from the top)
const cnt = (moveParams.value || 1);
const visibleModelRange = cursor.getCurrentCompletelyVisibleModelLinesRangeInViewport();
const modelLineNumber = this._firstLineNumberInRange(cursor.model, visibleModelRange, cnt);
const modelColumn = cursor.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
return this._moveToModelPosition(cursor, inSelectionMode, modelLineNumber, modelColumn, ctx);
}
case editorCommon.CursorMovePosition.ViewPortBottom: {
// Move to the nth line start in the viewport (from the bottom)
const cnt = (moveParams.value || 1);
const visibleModelRange = cursor.getCurrentCompletelyVisibleModelLinesRangeInViewport();
const modelLineNumber = this._lastLineNumberInRange(cursor.model, visibleModelRange, cnt);
const modelColumn = cursor.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
return this._moveToModelPosition(cursor, inSelectionMode, modelLineNumber, modelColumn, ctx);
}
case editorCommon.CursorMovePosition.ViewPortCenter: {
// Move to the line start in the viewport center
const visibleModelRange = cursor.getCurrentCompletelyVisibleModelLinesRangeInViewport();
const modelLineNumber = Math.round((visibleModelRange.startLineNumber + visibleModelRange.endLineNumber) / 2);
const modelColumn = cursor.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
return this._moveToModelPosition(cursor, inSelectionMode, modelLineNumber, modelColumn, ctx);
}
case editorCommon.CursorMovePosition.ViewPortIfOutside: {
// Move to a position inside the viewport
const visibleViewRange = cursor.getCompletelyVisibleViewLinesRangeInViewport();
if (visibleViewRange.startLineNumber <= viewLineNumber && viewLineNumber <= visibleViewRange.endLineNumber) {
// Nothing to do, cursor is in viewport
return false;
}
if (viewLineNumber > visibleViewRange.endLineNumber) {
viewLineNumber = visibleViewRange.endLineNumber - 1;
}
if (viewLineNumber < visibleViewRange.startLineNumber) {
viewLineNumber = visibleViewRange.startLineNumber;
}
const viewColumn = cursor.viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
return this._moveToViewPosition(cursor, inSelectionMode, viewLineNumber, viewColumn, ctx);
}
}
ctx.cursorPositionChangeReason = editorCommon.CursorChangeReason.Explicit;
cursor.moveViewPosition(inSelectionMode, viewLineNumber, viewColumn, 0, true);
return true;
return false;
}
/**
* Find the nth line start included in the range (from the start).
*/
public static _firstLineNumberInRange(model: ICursorSimpleModel, range: Range, count: number): number {
let startLineNumber = range.startLineNumber;
if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {
// Move on to the second line if the first line start is not included in the range
startLineNumber++;
}
return Math.min(range.endLineNumber, startLineNumber + count - 1);
}
/**
* Find the nth line start included in the range (from the end).
*/
public static _lastLineNumberInRange(model: ICursorSimpleModel, range: Range, count: number): number {
let startLineNumber = range.startLineNumber;
if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {
// Move on to the second line if the first line start is not included in the range
startLineNumber++;
}
return Math.max(startLineNumber, range.endLineNumber - count + 1);
}
private static _applyMoveOperationResult(cursor: OneCursor, ctx: IOneCursorOperationContext, r: MoveOperationResult): boolean {
......@@ -609,6 +651,38 @@ export class OneCursorOp {
);
}
private static _moveToViewPosition(cursor: OneCursor, inSelectionMode: boolean, toViewLineNumber: number, toViewColumn: number, ctx: IOneCursorOperationContext): boolean {
const res = SingleMoveOperationResult.fromMove(
cursor.viewState,
inSelectionMode,
toViewLineNumber,
toViewColumn,
0,
true,
editorCommon.CursorChangeReason.Explicit
);
return this._applyMoveOperationResult(
cursor, ctx,
this._fromViewCursorState(cursor, res)
);
}
private static _moveToModelPosition(cursor: OneCursor, inSelectionMode: boolean, toModelLineNumber: number, toModelColumn: number, ctx: IOneCursorOperationContext): boolean {
const res = SingleMoveOperationResult.fromMove(
cursor.modelState,
inSelectionMode,
toModelLineNumber,
toModelColumn,
0,
true,
editorCommon.CursorChangeReason.Explicit
);
return this._applyMoveOperationResult(
cursor, ctx,
this._fromModelCursorState(cursor, res)
);
}
private static _moveLeft(cursor: OneCursor, inSelectionMode: boolean, noOfColumns: number = 1, ctx: IOneCursorOperationContext): boolean {
return this._applyMoveOperationResult(
cursor, ctx,
......@@ -623,14 +697,6 @@ export class OneCursorOp {
);
}
private static _moveDown(cursor: OneCursor, moveArguments: CursorMoveArguments, ctx: IOneCursorOperationContext): boolean {
let linesCount = (moveArguments.isPaged ? (moveArguments.pageSize || cursor.config.pageSize) : moveArguments.value) || 1;
if (editorCommon.CursorMoveByUnit.WrappedLine === moveArguments.by) {
return this._moveDownByViewLines(cursor, moveArguments.select, linesCount, ctx);
}
return this._moveDownByModelLines(cursor, moveArguments.select, linesCount, ctx);
}
private static _moveDownByViewLines(cursor: OneCursor, inSelectionMode: boolean, linesCount: number, ctx: IOneCursorOperationContext): boolean {
return this._applyMoveOperationResult(
cursor, ctx,
......@@ -652,14 +718,6 @@ export class OneCursorOp {
);
}
private static _moveUp(cursor: OneCursor, moveArguments: CursorMoveArguments, ctx: IOneCursorOperationContext): boolean {
let linesCount = (moveArguments.isPaged ? (moveArguments.pageSize || cursor.config.pageSize) : moveArguments.value) || 1;
if (editorCommon.CursorMoveByUnit.WrappedLine === moveArguments.by) {
return this._moveUpByViewLines(cursor, moveArguments.select, linesCount, ctx);
}
return this._moveUpByModelLines(cursor, moveArguments.select, linesCount, ctx);
}
private static _moveUpByViewLines(cursor: OneCursor, inSelectionMode: boolean, linesCount: number, ctx: IOneCursorOperationContext): boolean {
return this._applyMoveOperationResult(
cursor, ctx,
......
......@@ -278,7 +278,7 @@ export abstract class DeleteWordCommand extends EditorCommand {
export class DeleteWordLeftCommand extends DeleteWordCommand {
protected _delete(wordSeparators: WordCharacterClassifier, model: IModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordOperations._deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
let r = WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
if (r) {
return r;
}
......@@ -288,7 +288,7 @@ export class DeleteWordLeftCommand extends DeleteWordCommand {
export class DeleteWordRightCommand extends DeleteWordCommand {
protected _delete(wordSeparators: WordCharacterClassifier, model: IModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordOperations._deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
let r = WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
if (r) {
return r;
}
......
......@@ -18,23 +18,19 @@ import { Range } from 'vs/editor/common/core/range';
let H = Handler;
suite('Cursor move command test', () => {
const LINE1 = ' \tMy First Line\t ';
const LINE2 = '\tMy Second Line';
const LINE3 = ' Third Line🐶';
const LINE4 = '';
const LINE5 = '1';
let thisModel: Model;
let thisConfiguration: TestConfiguration;
let thisCursor: Cursor;
setup(() => {
let text =
LINE1 + '\r\n' +
LINE2 + '\n' +
LINE3 + '\n' +
LINE4 + '\r\n' +
LINE5;
let text = [
' \tMy First Line\t ',
'\tMy Second Line',
' Third Line🐶',
'',
'1'
].join('\n');
thisModel = Model.createFromString(text);
thisConfiguration = new TestConfiguration(null);
......@@ -79,7 +75,7 @@ suite('Cursor move command test', () => {
moveLeft(thisCursor, 10);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
});
test('move right should move to right character', () => {
......@@ -176,25 +172,25 @@ suite('Cursor move command test', () => {
moveToLineEnd(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
});
test('move to end of line from last non white space character', () => {
thisCursor = aCursor();
moveTo(thisCursor, 1, LINE1.length - 1);
moveTo(thisCursor, 1, 19);
moveToLineEnd(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
});
test('move to end of line from line end', () => {
thisCursor = aCursor();
moveTo(thisCursor, 1, LINE1.length + 1);
moveTo(thisCursor, 1, 21);
moveToLineEnd(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
});
test('move to last non white space character from middle', () => {
......@@ -203,25 +199,25 @@ suite('Cursor move command test', () => {
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length - 1);
cursorEqual(thisCursor, 1, 19);
});
test('move to last non white space character from last non white space character', () => {
thisCursor = aCursor();
moveTo(thisCursor, 1, LINE1.length - 1);
moveTo(thisCursor, 1, 19);
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length - 1);
cursorEqual(thisCursor, 1, 19);
});
test('move to last non white space character from line end', () => {
thisCursor = aCursor();
moveTo(thisCursor, 1, LINE1.length + 1);
moveTo(thisCursor, 1, 21);
moveToLineLastNonWhiteSpaceCharacter(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length - 1);
cursorEqual(thisCursor, 1, 19);
});
test('move to center of line not from center', () => {
......@@ -338,27 +334,27 @@ suite('Cursor move command test', () => {
thisCursor = aCursor();
moveToEndOfLine(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
moveToEndOfLine(thisCursor);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
moveDown(thisCursor, 2);
cursorEqual(thisCursor, 3, LINE3.length + 1);
cursorEqual(thisCursor, 3, 17);
moveDown(thisCursor, 1);
cursorEqual(thisCursor, 4, LINE4.length + 1);
cursorEqual(thisCursor, 4, 1);
moveDown(thisCursor, 1);
cursorEqual(thisCursor, 5, LINE5.length + 1);
cursorEqual(thisCursor, 5, 2);
moveUp(thisCursor, 4);
cursorEqual(thisCursor, 1, LINE1.length + 1);
cursorEqual(thisCursor, 1, 21);
});
test('move to view top line moves to first visible line if it is first line', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(1, 1, 10, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(1, 1, 10, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -369,7 +365,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to top visible line when first line is not visible', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(2, 1, 10, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(2, 1, 10, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -380,7 +376,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to nth line from top', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(1, 1, 10, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(1, 1, 10, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -391,7 +387,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to last line if n is greater than last visible line number', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(1, 1, 3, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(1, 1, 3, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -402,7 +398,7 @@ suite('Cursor move command test', () => {
test('move to view center line moves to the center line', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(3, 1, 3, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(3, 1, 3, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -413,7 +409,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to last visible line if it is last line', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(1, 1, 5, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(1, 1, 5, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -424,7 +420,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to last visible line when last line is not visible', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(2, 1, 3, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(2, 1, 3, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -435,7 +431,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to nth line from bottom', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(1, 1, 5, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(1, 1, 5, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -446,7 +442,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to first line if n is lesser than first visible line number', () => {
let viewModelHelper = aViewModelHelper(thisModel);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport = () => new Range(2, 1, 5, 1);
viewModelHelper.getCompletelyVisibleViewRange = () => new Range(2, 1, 5, 1);
thisCursor = aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......
......@@ -9,6 +9,7 @@ import { IViewModelHelper } from 'vs/editor/common/controller/oneCursor';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { IModel } from 'vs/editor/common/editorCommon';
export function withEditorModel(text: string[], callback: (model: Model) => void): void {
var model = Model.createFromString(text.join('\n'));
......@@ -16,9 +17,10 @@ export function withEditorModel(text: string[], callback: (model: Model) => void
model.dispose();
}
export function viewModelHelper(model): IViewModelHelper {
export function viewModelHelper(model: IModel): IViewModelHelper {
return {
viewModel: model,
coordinatesConverter: {
convertViewPositionToModelPosition: (viewPosition: Position): Position => {
return viewPosition;
......@@ -48,7 +50,7 @@ export function viewModelHelper(model): IViewModelHelper {
return true;
},
},
getCurrentCompletelyVisibleViewLinesRangeInViewport: () => { return null; },
getCurrentCompletelyVisibleModelLinesRangeInViewport: () => { return null; },
getCompletelyVisibleViewRange: () => null,
};
}
......@@ -22,7 +22,7 @@ export class MockCodeEditor extends CommonCodeEditor {
return new TestConfiguration(options);
}
public getCenteredRangeInViewport(): Range { return null; }
public getCompletelyVisibleLinesRangeInViewport(): Range { return null; }
protected _getCompletelyVisibleViewRange(): Range { return null; }
public getScrollWidth(): number { return 0; }
public getScrollLeft(): number { return 0; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册