diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 1deda2cb2096e96a73f6d348b569c9958f8ea921..97d7fb0ecf31bb63757c2a543cc808487d61a8fc 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -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 = 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; + } } } diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index 999e7244263780f443e99b1df9560fcc8ed69d85..245d2491a0cf00979bf70a488d4dffe58a5b429c 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -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]); } } diff --git a/src/vs/editor/common/controller/cursorColumnSelection.ts b/src/vs/editor/common/controller/cursorColumnSelection.ts index ad54aad22c004c0fe33690083c99fa178bbfcb7f..972b5e0314a6503d9982ae3100ccbe8cedfe2f27 100644 --- a/src/vs/editor/common/controller/cursorColumnSelection.ts +++ b/src/vs/editor/common/controller/cursorColumnSelection.ts @@ -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 diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 0b97da9a0f5f7114ace56213ae0b4334412298ed..27b9ad5f4816d4167667544bc0b802b99cd56d7d 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -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); } diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 8ace2896a42cc03822974fba2d173fd35c50f065..b8de80ace83eb848cbde84575e90081ca4f16733 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -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 }