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

Simplify cursor code

上级 355ed3ca
......@@ -10,12 +10,11 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { EventEmitter, BulkListenerCallback } from 'vs/base/common/eventEmitter';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { CursorCollection } from 'vs/editor/common/controller/cursorCollection';
import { OneCursor } from 'vs/editor/common/controller/oneCursor';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection, SelectionDirection, ISelection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { CursorColumns, CursorConfiguration, EditOperationResult, SingleCursorState, IViewModelHelper, CursorContext } from 'vs/editor/common/controller/cursorCommon';
import { CursorColumns, CursorConfiguration, EditOperationResult, SingleCursorState, IViewModelHelper, CursorContext, CursorState } from 'vs/editor/common/controller/cursorCommon';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { ColumnSelection, IColumnSelectResult } from 'vs/editor/common/controller/cursorColumnSelection';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
......@@ -32,15 +31,6 @@ const enum RevealTarget {
BottomMost = 2
}
interface ICursorMoveCommandserationContext {
shouldReveal: boolean;
shouldRevealHorizontal: boolean;
shouldPushStackElementBefore: boolean;
shouldPushStackElementAfter: boolean;
executeCommand: editorCommon.ICommand;
isAutoWhitespaceCommand: boolean;
}
interface IMultipleCursorOperationContext {
cursorPositionChangeReason: CursorChangeReason;
shouldReveal: boolean;
......@@ -52,8 +42,12 @@ interface IMultipleCursorOperationContext {
eventData: any;
executeCommands: editorCommon.ICommand[];
isAutoWhitespaceCommand: boolean[];
setColumnSelectToLineNumber: number;
setColumnSelectToVisualColumn: number;
setColumnSelectData: IColumnSelectData;
}
interface IColumnSelectData {
toViewLineNumber: number;
toViewVisualColumn: number;
}
interface IExecContext {
......@@ -95,6 +89,7 @@ export class Cursor extends Disposable {
private _isHandling: boolean;
private _isDoingComposition: boolean;
private _columnSelectData: IColumnSelectData;
private enableEmptySelectionClipboard: boolean;
......@@ -132,6 +127,7 @@ export class Cursor extends Disposable {
this._isHandling = false;
this._isDoingComposition = false;
this._columnSelectData = null;
this._register(this.model.addBulkListener((events) => {
if (this._isHandling) {
......@@ -273,23 +269,19 @@ export class Cursor extends Disposable {
if (!this._isHandling) {
// Read the markers before entering `_onHandler`, since that would validate
// the position and ruin the markers
let selections: Selection[] = this.cursors.getAll().map((cursor) => {
return cursor.beginRecoverSelectionFromMarkers(this.context);
const cursors = this.cursors.getAll();
const selectionsFromMarkers: Selection[] = cursors.map((cursor) => {
return cursor.readSelectionFromMarkers(this.context);
});
this._onHandler('recoverSelectionFromMarkers', (ctx: IMultipleCursorOperationContext) => {
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
var result = this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: ICursorMoveCommandserationContext) => {
ctx.cursorPositionChangeReason = CursorChangeReason.RecoverFromMarkers;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
ctx.shouldReveal = false;
return oneCursor.endRecoverSelectionFromMarkers(this.context, selections[cursorIndex]);
});
for (let i = 0, len = cursors.length; i < len; i++) {
cursors[i].setSelection(this.context, selectionsFromMarkers[i]);
}
ctx.cursorPositionChangeReason = CursorChangeReason.RecoverFromMarkers;
ctx.shouldReveal = false;
ctx.shouldPushStackElementBefore = false;
ctx.shouldPushStackElementAfter = false;
return result;
}, 'modelChange', null);
}
}
......@@ -298,7 +290,7 @@ export class Cursor extends Disposable {
// ------ some getters/setters
public getSelection(): Selection {
return this.cursors.getSelection(0);
return this.cursors.getPrimaryCursor().modelState.selection;
}
public getSelections(): Selection[] {
......@@ -306,7 +298,7 @@ export class Cursor extends Disposable {
}
public getPosition(): Position {
return this.cursors.getPosition(0);
return this.cursors.getPrimaryCursor().modelState.position;
}
public setSelections(source: string, selections: ISelection[]): void {
......@@ -321,7 +313,7 @@ export class Cursor extends Disposable {
private _createAndInterpretHandlerCtx(eventSource: string, eventData: any, callback: (currentHandlerCtx: IMultipleCursorOperationContext) => void): void {
var currentHandlerCtx: IMultipleCursorOperationContext = {
var ctx: IMultipleCursorOperationContext = {
cursorPositionChangeReason: CursorChangeReason.NotSet,
shouldReveal: true,
shouldRevealHorizontal: true,
......@@ -332,13 +324,12 @@ export class Cursor extends Disposable {
isAutoWhitespaceCommand: [],
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: false,
setColumnSelectToLineNumber: 0,
setColumnSelectToVisualColumn: 0
setColumnSelectData: null
};
callback(currentHandlerCtx);
callback(ctx);
this._interpretHandlerContext(currentHandlerCtx);
this._interpretHandlerContext(ctx);
this.cursors.normalize();
}
......@@ -347,19 +338,18 @@ export class Cursor extends Disposable {
this._isHandling = true;
try {
var oldSelections = this.cursors.getSelections();
var oldViewSelections = this.cursors.getViewSelections();
const oldSelections = this.cursors.getSelections();
const oldViewSelections = this.cursors.getViewSelections();
// ensure valid state on all cursors
this.cursors.ensureValidState();
var eventSource = source;
var cursorPositionChangeReason: CursorChangeReason;
var shouldReveal: boolean;
var shouldRevealHorizontal: boolean;
var shouldRevealTarget: RevealTarget;
let cursorPositionChangeReason: CursorChangeReason;
let shouldReveal: boolean;
let shouldRevealHorizontal: boolean;
let shouldRevealTarget: RevealTarget;
this._createAndInterpretHandlerCtx(eventSource, data, (currentHandlerCtx: IMultipleCursorOperationContext) => {
this._createAndInterpretHandlerCtx(source, data, (currentHandlerCtx: IMultipleCursorOperationContext) => {
handler(currentHandlerCtx);
cursorPositionChangeReason = currentHandlerCtx.cursorPositionChangeReason;
......@@ -368,33 +358,32 @@ export class Cursor extends Disposable {
shouldRevealHorizontal = currentHandlerCtx.shouldRevealHorizontal;
});
var newSelections = this.cursors.getSelections();
var newViewSelections = this.cursors.getViewSelections();
const newSelections = this.cursors.getSelections();
const newViewSelections = this.cursors.getViewSelections();
var somethingChanged = false;
let somethingChanged = false;
if (oldSelections.length !== newSelections.length) {
somethingChanged = true;
} else {
for (var i = 0, len = oldSelections.length; !somethingChanged && i < len; i++) {
for (let i = 0, len = oldSelections.length; !somethingChanged && i < len; i++) {
if (!oldSelections[i].equalsSelection(newSelections[i])) {
somethingChanged = true;
}
}
for (var i = 0, len = oldViewSelections.length; !somethingChanged && i < len; i++) {
for (let i = 0, len = oldViewSelections.length; !somethingChanged && i < len; i++) {
if (!oldViewSelections[i].equalsSelection(newViewSelections[i])) {
somethingChanged = true;
}
}
}
if (somethingChanged) {
this.emitCursorPositionChanged(eventSource, cursorPositionChangeReason);
this.emitCursorPositionChanged(source, cursorPositionChangeReason);
if (shouldReveal) {
this.revealRange(shouldRevealTarget, VerticalRevealType.Simple, shouldRevealHorizontal);
}
this.emitCursorSelectionChanged(eventSource, cursorPositionChangeReason);
this.emitCursorSelectionChanged(source, cursorPositionChangeReason);
}
} catch (err) {
......@@ -410,8 +399,7 @@ export class Cursor extends Disposable {
ctx.shouldPushStackElementBefore = false;
}
this._columnSelectToLineNumber = ctx.setColumnSelectToLineNumber;
this._columnSelectToVisualColumn = ctx.setColumnSelectToVisualColumn;
this._columnSelectData = ctx.setColumnSelectData;
this._internalExecuteCommands(ctx.executeCommands, ctx.isAutoWhitespaceCommand);
ctx.executeCommands = [];
......@@ -591,12 +579,11 @@ export class Cursor extends Disposable {
positionMarkers: []
};
var r = this._innerExecuteCommands(ctx, commands, isAutoWhitespaceCommand);
this._innerExecuteCommands(ctx, commands, isAutoWhitespaceCommand);
for (var i = 0; i < ctx.selectionStartMarkers.length; i++) {
this.model._removeMarker(ctx.selectionStartMarkers[i]);
this.model._removeMarker(ctx.positionMarkers[i]);
}
return r;
}
private _arrayIsEmpty(commands: editorCommon.ICommand[]): boolean {
......@@ -920,34 +907,6 @@ export class Cursor extends Disposable {
this._handlers[H.RevealLine] = (ctx) => this._revealLine(ctx);
}
private _invokeForAll(ctx: IMultipleCursorOperationContext, callable: (cursorIndex: number, cursor: OneCursor, ctx: ICursorMoveCommandserationContext) => void): void {
let cursors = this.cursors.getAll();
for (let i = 0; i < cursors.length; i++) {
let context = {
shouldReveal: true,
shouldRevealHorizontal: true,
executeCommand: null,
isAutoWhitespaceCommand: false,
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: false
};
callable(i, cursors[i], context);
if (i === 0) {
ctx.shouldRevealHorizontal = context.shouldRevealHorizontal;
ctx.shouldReveal = context.shouldReveal;
}
ctx.shouldPushStackElementBefore = ctx.shouldPushStackElementBefore || context.shouldPushStackElementBefore;
ctx.shouldPushStackElementAfter = ctx.shouldPushStackElementAfter || context.shouldPushStackElementAfter;
ctx.executeCommands[i] = context.executeCommand;
ctx.isAutoWhitespaceCommand[i] = context.isAutoWhitespaceCommand;
}
}
private _moveTo(inSelectionMode: boolean, ctx: IMultipleCursorOperationContext): void {
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
......@@ -976,24 +935,26 @@ export class Cursor extends Disposable {
this.cursors.setStates(CursorMoveCommands.move(this.context, this.cursors.getAll(), args), true);
}
private _columnSelectToLineNumber: number = 0;
private _getColumnSelectToLineNumber(): number {
if (!this._columnSelectToLineNumber) {
let primaryCursor = this.cursors.getPrimaryCursor();
let primaryPos = primaryCursor.viewState.position;
return primaryPos.lineNumber;
private _getColumnSelectData(): IColumnSelectData {
if (this._columnSelectData) {
return this._columnSelectData;
}
return this._columnSelectToLineNumber;
const primaryCursor = this.cursors.getPrimaryCursor();
const primaryPos = primaryCursor.viewState.position;
return {
toViewLineNumber: primaryPos.lineNumber,
toViewVisualColumn: CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, primaryPos)
};
}
private _columnSelectToVisualColumn: number = 0;
private _getColumnSelectToVisualColumn(): number {
if (!this._columnSelectToVisualColumn) {
let primaryCursor = this.cursors.getPrimaryCursor();
let primaryPos = primaryCursor.viewState.position;
return CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, primaryPos);
}
return this._columnSelectToVisualColumn;
private _applyColumnSelect(ctx: IMultipleCursorOperationContext, result: IColumnSelectResult): void {
ctx.shouldRevealTarget = (result.reversed ? RevealTarget.TopMost : RevealTarget.BottomMost);
ctx.shouldReveal = true;
ctx.setColumnSelectData = {
toViewLineNumber: result.toLineNumber,
toViewVisualColumn: result.toVisualColumn
};
this.cursors.setStates(result.viewStates.map((viewState) => CursorState.fromViewState(viewState)), false);
}
private _columnSelectMouse(ctx: IMultipleCursorOperationContext): void {
......@@ -1009,43 +970,39 @@ export class Cursor extends Disposable {
}
let result = ColumnSelection.columnSelect(this.context.config, this.context.viewModel, primary.viewState.selection, validatedViewPosition.lineNumber, ctx.eventData.mouseColumn - 1);
let selections = result.viewSelections.map(viewSel => this.context.convertViewSelectionToModelSelection(viewSel));
ctx.shouldRevealTarget = (result.reversed ? RevealTarget.TopMost : RevealTarget.BottomMost);
ctx.shouldReveal = true;
ctx.setColumnSelectToLineNumber = result.toLineNumber;
ctx.setColumnSelectToVisualColumn = result.toVisualColumn;
this.cursors.setSelections(selections, result.viewSelections);
}
private _columnSelectOp(ctx: IMultipleCursorOperationContext, op: (cursor: OneCursor, toViewLineNumber: number, toViewVisualColumn: number) => IColumnSelectResult): void {
let primary = this.cursors.getPrimaryCursor();
let result = op(primary, this._getColumnSelectToLineNumber(), this._getColumnSelectToVisualColumn());
let selections = result.viewSelections.map(viewSel => this.context.convertViewSelectionToModelSelection(viewSel));
ctx.shouldRevealTarget = (result.reversed ? RevealTarget.TopMost : RevealTarget.BottomMost);
ctx.shouldReveal = true;
ctx.setColumnSelectToLineNumber = result.toLineNumber;
ctx.setColumnSelectToVisualColumn = result.toVisualColumn;
this.cursors.setSelections(selections, result.viewSelections);
this._applyColumnSelect(ctx, result);
}
private _columnSelectLeft(ctx: IMultipleCursorOperationContext): void {
this._columnSelectOp(ctx, (cursor, toViewLineNumber, toViewVisualColumn) => ColumnSelection.columnSelectLeft(this.context.config, this.context.viewModel, cursor.viewState, toViewLineNumber, toViewVisualColumn));
const primary = this.cursors.getPrimaryCursor();
const prevColumnSelectData = this._getColumnSelectData();
this._applyColumnSelect(ctx,
ColumnSelection.columnSelectLeft(this.context.config, this.context.viewModel, primary.viewState, prevColumnSelectData.toViewLineNumber, prevColumnSelectData.toViewVisualColumn)
);
}
private _columnSelectRight(ctx: IMultipleCursorOperationContext): void {
this._columnSelectOp(ctx, (cursor, toViewLineNumber, toViewVisualColumn) => ColumnSelection.columnSelectRight(this.context.config, this.context.viewModel, cursor.viewState, toViewLineNumber, toViewVisualColumn));
const primary = this.cursors.getPrimaryCursor();
const prevColumnSelectData = this._getColumnSelectData();
this._applyColumnSelect(ctx,
ColumnSelection.columnSelectRight(this.context.config, this.context.viewModel, primary.viewState, prevColumnSelectData.toViewLineNumber, prevColumnSelectData.toViewVisualColumn)
);
}
private _columnSelectUp(isPaged: boolean, ctx: IMultipleCursorOperationContext): void {
this._columnSelectOp(ctx, (cursor, toViewLineNumber, toViewVisualColumn) => ColumnSelection.columnSelectUp(this.context.config, this.context.viewModel, cursor.viewState, isPaged, toViewLineNumber, toViewVisualColumn));
const primary = this.cursors.getPrimaryCursor();
const prevColumnSelectData = this._getColumnSelectData();
this._applyColumnSelect(ctx,
ColumnSelection.columnSelectUp(this.context.config, this.context.viewModel, primary.viewState, isPaged, prevColumnSelectData.toViewLineNumber, prevColumnSelectData.toViewVisualColumn)
);
}
private _columnSelectDown(isPaged: boolean, ctx: IMultipleCursorOperationContext): void {
this._columnSelectOp(ctx, (cursor, toViewLineNumber, toViewVisualColumn) => ColumnSelection.columnSelectDown(this.context.config, this.context.viewModel, cursor.viewState, isPaged, toViewLineNumber, toViewVisualColumn));
const primary = this.cursors.getPrimaryCursor();
const prevColumnSelectData = this._getColumnSelectData();
this._applyColumnSelect(ctx,
ColumnSelection.columnSelectDown(this.context.config, this.context.viewModel, primary.viewState, isPaged, prevColumnSelectData.toViewLineNumber, prevColumnSelectData.toViewVisualColumn)
);
}
private _createCursor(ctx: IMultipleCursorOperationContext): void {
......@@ -1548,13 +1505,19 @@ export class Cursor extends Disposable {
}
private _externalExecuteCommands(ctx: IMultipleCursorOperationContext): void {
const commands = <editorCommon.ICommand[]>ctx.eventData;
ctx.shouldReveal = true;
ctx.shouldRevealHorizontal = true;
ctx.shouldPushStackElementBefore = true;
ctx.shouldPushStackElementAfter = true;
this._invokeForAll(ctx, (cursorIndex: number, oneCursor: OneCursor, oneCtx: ICursorMoveCommandserationContext) => {
oneCtx.shouldPushStackElementBefore = true;
oneCtx.shouldPushStackElementAfter = true;
oneCtx.executeCommand = ctx.eventData[cursorIndex];
});
const cursors = this.cursors.getAll();
for (let i = 0; i < cursors.length; i++) {
ctx.executeCommands[i] = commands[i];
ctx.isAutoWhitespaceCommand[i] = false;
}
}
}
......
......@@ -4,16 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IOneCursorState, OneCursor } from 'vs/editor/common/controller/oneCursor';
import { OneCursor } from 'vs/editor/common/controller/oneCursor';
import { Selection, ISelection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { CursorState, CursorContext } from 'vs/editor/common/controller/cursorCommon';
export interface ICursorCollectionState {
primary: IOneCursorState;
secondary: IOneCursorState[];
}
export class CursorCollection {
private context: CursorContext;
......@@ -47,22 +42,6 @@ export class CursorCollection {
}
}
public saveState(): ICursorCollectionState {
return {
primary: this.primaryCursor.saveState(),
secondary: this.secondaryCursors.map(c => c.saveState())
};
}
public restoreState(state: ICursorCollectionState): void {
this.primaryCursor.restoreState(this.context, state.primary);
this.killSecondaryCursors();
for (var i = 0; i < state.secondary.length; i++) {
this.addSecondaryCursor(null);
this.secondaryCursors[i].restoreState(this.context, state.secondary[i]);
}
}
public getAll(): OneCursor[] {
var result: OneCursor[] = [];
result.push(this.primaryCursor);
......@@ -70,22 +49,6 @@ export class CursorCollection {
return result;
}
public getPosition(index: number): Position {
if (index === 0) {
return this.primaryCursor.modelState.position;
} else {
return this.secondaryCursors[index - 1].modelState.position;
}
}
public getViewPosition(index: number): Position {
if (index === 0) {
return this.primaryCursor.viewState.position;
} else {
return this.secondaryCursors[index - 1].viewState.position;
}
}
public getPositions(): Position[] {
var result: Position[] = [];
result.push(this.primaryCursor.modelState.position);
......@@ -104,14 +67,6 @@ export class CursorCollection {
return result;
}
public getSelection(index: number): Selection {
if (index === 0) {
return this.primaryCursor.modelState.selection;
} else {
return this.secondaryCursors[index - 1].modelState.selection;
}
}
public getSelections(): Selection[] {
var result: Selection[] = [];
result.push(this.primaryCursor.modelState.selection);
......@@ -130,9 +85,9 @@ export class CursorCollection {
return result;
}
public setSelections(selections: ISelection[], viewSelections?: ISelection[]): void {
this.primaryCursor.setSelection(this.context, selections[0], viewSelections ? viewSelections[0] : null);
this._setSecondarySelections(selections.slice(1), viewSelections ? viewSelections.slice(1) : null);
public setSelections(selections: ISelection[]): void {
this.primaryCursor.setSelection(this.context, selections[0]);
this._setSecondarySelections(selections.slice(1));
}
public getPrimaryCursor(): OneCursor {
......@@ -172,7 +127,7 @@ export class CursorCollection {
}
public killSecondaryCursors(): boolean {
return (this._setSecondarySelections([], []) > 0);
return (this._setSecondarySelections([]) > 0);
}
public normalize(): void {
......@@ -202,7 +157,7 @@ export class CursorCollection {
* - a negative number indicates the number of secondary cursors removed
* - 0 indicates that no changes have been done to the secondary cursors list
*/
private _setSecondarySelections(secondarySelections: ISelection[], viewSelections: ISelection[]): number {
private _setSecondarySelections(secondarySelections: ISelection[]): number {
var secondaryCursorsLength = this.secondaryCursors.length;
var secondarySelectionsLength = secondarySelections.length;
var returnValue = secondarySelectionsLength - secondaryCursorsLength;
......@@ -221,7 +176,7 @@ export class CursorCollection {
for (var i = 0; i < secondarySelectionsLength; i++) {
if (secondarySelections[i]) {
this.secondaryCursors[i].setSelection(this.context, secondarySelections[i], viewSelections ? viewSelections[i] : null);
this.secondaryCursors[i].setSelection(this.context, secondarySelections[i]);
}
}
......
......@@ -6,10 +6,11 @@
import { Selection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { SingleCursorState, CursorColumns, CursorConfiguration, ICursorSimpleModel } from 'vs/editor/common/controller/cursorCommon';
export interface IColumnSelectResult {
viewSelections: Selection[];
viewStates: SingleCursorState[];
reversed: boolean;
toLineNumber: number;
toVisualColumn: number;
......@@ -23,7 +24,7 @@ export class ColumnSelection {
let isRTL = (fromVisibleColumn > toVisibleColumn);
let isLTR = (fromVisibleColumn < toVisibleColumn);
let result: Selection[] = [];
let result: SingleCursorState[] = [];
// console.log(`fromVisibleColumn: ${fromVisibleColumn}, toVisibleColumn: ${toVisibleColumn}`);
......@@ -55,11 +56,14 @@ export class ColumnSelection {
}
}
result.push(new Selection(lineNumber, startColumn, lineNumber, endColumn));
result.push(new SingleCursorState(
new Range(lineNumber, startColumn, lineNumber, startColumn), 0,
new Position(lineNumber, endColumn), 0
));
}
return {
viewSelections: result,
viewStates: result,
reversed: reversed,
toLineNumber: toLineNumber,
toVisualColumn: toVisibleColumn
......
......@@ -266,10 +266,6 @@ export class CursorContext {
return this._coordinatesConverter.validateViewRange(viewRange, expectedModelRange);
}
public convertViewSelectionToModelSelection(viewSelection: Selection): Selection {
return this._coordinatesConverter.convertViewSelectionToModelSelection(viewSelection);
}
public convertViewRangeToModelRange(viewRange: Range): Range {
return this._coordinatesConverter.convertViewRangeToModelRange(viewRange);
}
......
......@@ -9,15 +9,6 @@ import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection, SelectionDirection, ISelection } from 'vs/editor/common/core/selection';
export interface IOneCursorState {
selectionStart: Range;
viewSelectionStart: Range;
position: Position;
viewPosition: Position;
leftoverVisibleColumns: number;
selectionStartLeftoverVisibleColumns: number;
}
export interface ICursor {
readonly modelState: SingleCursorState;
readonly viewState: SingleCursorState;
......@@ -45,15 +36,44 @@ export class OneCursor implements ICursor {
context.model._removeMarker(this._selEndMarker);
}
/**
* Sometimes, the line mapping changes and the stored view position is stale.
*/
public readSelectionFromMarkers(context: CursorContext): Selection {
const start = context.model._getMarker(this._selStartMarker);
const end = context.model._getMarker(this._selEndMarker);
if (this.modelState.selection.getDirection() === SelectionDirection.LTR) {
return new Selection(start.lineNumber, start.column, end.lineNumber, end.column);
}
return new Selection(end.lineNumber, end.column, start.lineNumber, start.column);
}
public ensureValidState(context: CursorContext): void {
this._setState(context, this.modelState, this.viewState, false);
}
public setSelection(context: CursorContext, selection: ISelection): void {
const selectionStartLineNumber = selection.selectionStartLineNumber;
const selectionStartColumn = selection.selectionStartColumn;
const positionLineNumber = selection.positionLineNumber;
const positionColumn = selection.positionColumn;
const modelState = new SingleCursorState(
new Range(selectionStartLineNumber, selectionStartColumn, selectionStartLineNumber, selectionStartColumn), 0,
new Position(positionLineNumber, positionColumn), 0
);
this._setState(
context,
modelState,
null,
false
);
}
public setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState, ensureInEditableRange: boolean): void {
this._setState(context, modelState, viewState, ensureInEditableRange);
}
private _ensureInEditableRange(context: CursorContext, position: Position): Position {
let editableRange = context.model.getEditableRange();
const editableRange = context.model.getEditableRange();
if (position.lineNumber < editableRange.startLineNumber || (position.lineNumber === editableRange.startLineNumber && position.column < editableRange.startColumn)) {
return new Position(editableRange.startLineNumber, editableRange.startColumn);
......@@ -63,6 +83,11 @@ export class OneCursor implements ICursor {
return position;
}
private _validatePosition(context: CursorContext, _position: Position, ensureInEditableRange: boolean): Position {
const position = context.model.validatePosition(_position);
return (ensureInEditableRange ? this._ensureInEditableRange(context, position) : position);
}
private _setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState, ensureInEditableRange: boolean): void {
if (!modelState) {
// We only have the view state => compute the model state
......@@ -70,12 +95,11 @@ export class OneCursor implements ICursor {
context.convertViewRangeToModelRange(viewState.selectionStart)
);
let position = context.model.validatePosition(
context.convertViewPositionToModelPosition(viewState.position.lineNumber, viewState.position.column)
const position = this._validatePosition(
context,
context.convertViewPositionToModelPosition(viewState.position.lineNumber, viewState.position.column),
ensureInEditableRange
);
if (ensureInEditableRange) {
position = this._ensureInEditableRange(context, position);
}
modelState = new SingleCursorState(selectionStart, viewState.selectionStartLeftoverVisibleColumns, position, viewState.leftoverVisibleColumns);
} else {
......@@ -83,11 +107,11 @@ export class OneCursor implements ICursor {
const selectionStart = context.model.validateRange(modelState.selectionStart);
const selectionStartLeftoverVisibleColumns = modelState.selectionStart.equalsRange(selectionStart) ? modelState.selectionStartLeftoverVisibleColumns : 0;
let position = context.model.validatePosition(modelState.position);
if (ensureInEditableRange) {
position = this._ensureInEditableRange(context, position);
}
const position = this._validatePosition(
context,
modelState.position,
ensureInEditableRange
);
const leftoverVisibleColumns = modelState.position.equals(position) ? modelState.leftoverVisibleColumns : 0;
modelState = new SingleCursorState(selectionStart, selectionStartLeftoverVisibleColumns, position, leftoverVisibleColumns);
......@@ -128,104 +152,4 @@ export class OneCursor implements ICursor {
return markerId;
}
}
public saveState(): IOneCursorState {
return {
selectionStart: this.modelState.selectionStart,
viewSelectionStart: this.viewState.selectionStart,
position: this.modelState.position,
viewPosition: this.viewState.position,
leftoverVisibleColumns: this.modelState.leftoverVisibleColumns,
selectionStartLeftoverVisibleColumns: this.modelState.selectionStartLeftoverVisibleColumns
};
}
public restoreState(context: CursorContext, state: IOneCursorState): void {
let position = context.model.validatePosition(state.position);
let selectionStart: Range;
if (state.selectionStart) {
selectionStart = context.model.validateRange(state.selectionStart);
} else {
selectionStart = new Range(position.lineNumber, position.column, position.lineNumber, position.column);
}
let viewPosition = context.validateViewPosition(new Position(state.viewPosition.lineNumber, state.viewPosition.column), position);
let viewSelectionStart: Range;
if (state.viewSelectionStart) {
viewSelectionStart = context.validateViewRange(new Range(state.viewSelectionStart.startLineNumber, state.viewSelectionStart.startColumn, state.viewSelectionStart.endLineNumber, state.viewSelectionStart.endColumn), selectionStart);
} else {
viewSelectionStart = context.convertModelRangeToViewRange(selectionStart);
}
this._setState(
context,
new SingleCursorState(selectionStart, state.selectionStartLeftoverVisibleColumns, position, state.leftoverVisibleColumns),
new SingleCursorState(viewSelectionStart, state.selectionStartLeftoverVisibleColumns, viewPosition, state.leftoverVisibleColumns),
false
);
}
public setSelection(context: CursorContext, selection: ISelection, viewSelection: ISelection = null): void {
let position = context.model.validatePosition({
lineNumber: selection.positionLineNumber,
column: selection.positionColumn
});
let selectionStart = context.model.validatePosition({
lineNumber: selection.selectionStartLineNumber,
column: selection.selectionStartColumn
});
let viewPosition: Position;
let viewSelectionStart: Position;
if (viewSelection) {
viewPosition = context.validateViewPosition(new Position(viewSelection.positionLineNumber, viewSelection.positionColumn), position);
viewSelectionStart = context.validateViewPosition(new Position(viewSelection.selectionStartLineNumber, viewSelection.selectionStartColumn), selectionStart);
} else {
viewPosition = context.convertModelPositionToViewPosition(position);
viewSelectionStart = context.convertModelPositionToViewPosition(selectionStart);
}
this._setState(
context,
new SingleCursorState(new Range(selectionStart.lineNumber, selectionStart.column, selectionStart.lineNumber, selectionStart.column), 0, position, 0),
new SingleCursorState(new Range(viewSelectionStart.lineNumber, viewSelectionStart.column, viewSelectionStart.lineNumber, viewSelectionStart.column), 0, viewPosition, 0),
false
);
}
public setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState, ensureInEditableRange: boolean): void {
this._setState(context, modelState, viewState, ensureInEditableRange);
}
public beginRecoverSelectionFromMarkers(context: CursorContext): Selection {
const start = context.model._getMarker(this._selStartMarker);
const end = context.model._getMarker(this._selEndMarker);
if (this.modelState.selection.getDirection() === SelectionDirection.LTR) {
return new Selection(start.lineNumber, start.column, end.lineNumber, end.column);
}
return new Selection(end.lineNumber, end.column, start.lineNumber, start.column);
}
public endRecoverSelectionFromMarkers(context: CursorContext, recoveredSelection: Selection): boolean {
const selectionStart = new Range(recoveredSelection.selectionStartLineNumber, recoveredSelection.selectionStartColumn, recoveredSelection.selectionStartLineNumber, recoveredSelection.selectionStartColumn);
const position = new Position(recoveredSelection.positionLineNumber, recoveredSelection.positionColumn);
const viewSelectionStart = context.convertModelRangeToViewRange(selectionStart);
const viewPosition = context.convertModelPositionToViewPosition(position);
this._setState(
context,
new SingleCursorState(selectionStart, 0, position, 0),
new SingleCursorState(viewSelectionStart, 0, viewPosition, 0),
false
);
return true;
}
// -------------------- END modifications
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册