From 121a4bca1d00a82305abc4435cec4d12be02c504 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 18 May 2017 14:26:03 +0200 Subject: [PATCH] Simplify cursor handlers --- src/vs/editor/common/controller/cursor.ts | 91 ++++++++----------- .../common/controller/cursorCollection.ts | 50 ++-------- .../editor/common/controller/cursorCommon.ts | 22 ++++- src/vs/editor/common/controller/oneCursor.ts | 18 +--- 4 files changed, 66 insertions(+), 115 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 0388e5bc489..1f4e91e86e3 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -46,7 +46,7 @@ interface ICommandData { interface ICommandsData { operations: editorCommon.IIdentifiedSingleEditOperation[]; - anyoneHadTrackedEditOperation: boolean; + hadTrackedEditOperation: boolean; } export class Cursor extends Disposable implements ICursors { @@ -293,10 +293,8 @@ export class Cursor extends Disposable implements ICursors { }); } - this._onHandler('restoreState', (ctx: IMultipleCursorOperationContext) => { - this._cursors.setSelections(desiredSelections); - return false; - }, 'restoreState', null); + this.setStates('restoreState', CursorChangeReason.NotSet, CursorState.fromModelSelections(desiredSelections)); + this.reveal(true, RevealTarget.Primary); } private _onModelContentChanged(hadFlushEvent: boolean): void { @@ -313,13 +311,7 @@ export class Cursor extends Disposable implements ICursors { // Read the markers before entering `_onHandler`, since that would validate // the position and ruin the markers const selectionsFromMarkers = this._cursors.readSelectionFromMarkers(); - this._onHandler('recoverSelectionFromMarkers', (ctx: IMultipleCursorOperationContext) => { - ctx.cursorPositionChangeReason = CursorChangeReason.RecoverFromMarkers; - ctx.shouldReveal = false; - ctx.shouldPushStackElementBefore = false; - ctx.shouldPushStackElementAfter = false; - this._cursors.setSelections(selectionsFromMarkers); - }, 'modelChange', null); + this.setStates('modelChange', CursorChangeReason.RecoverFromMarkers, CursorState.fromModelSelections(selectionsFromMarkers)); } } } @@ -339,11 +331,7 @@ export class Cursor extends Disposable implements ICursors { } public setSelections(source: string, selections: ISelection[]): void { - this._onHandler('setSelections', (ctx: IMultipleCursorOperationContext) => { - ctx.shouldReveal = false; - this._cursors.setSelections(selections); - return false; - }, source, null); + this.setStates(source, CursorChangeReason.NotSet, CursorState.fromModelSelections(selections)); } // ------ auxiliary handling logic @@ -363,7 +351,32 @@ export class Cursor extends Disposable implements ICursors { callback(ctx); - this._interpretHandlerContext(ctx); + if (ctx.shouldPushStackElementBefore) { + this._model.pushStackElement(); + ctx.shouldPushStackElementBefore = false; + } + + this._columnSelectData = null; + + const execCtx: IExecContext = { + selectionStartMarkers: [], + positionMarkers: [] + }; + + this._innerExecuteCommands(execCtx, ctx.executeCommands, ctx.isAutoWhitespaceCommand); + + for (let i = 0; i < execCtx.selectionStartMarkers.length; i++) { + this._model._removeMarker(execCtx.selectionStartMarkers[i]); + this._model._removeMarker(execCtx.positionMarkers[i]); + } + + ctx.executeCommands = []; + + if (ctx.shouldPushStackElementAfter) { + this._model.pushStackElement(); + ctx.shouldPushStackElementAfter = false; + } + this._cursors.normalize(); } @@ -423,23 +436,6 @@ export class Cursor extends Disposable implements ICursors { this._isHandling = false; } - private _interpretHandlerContext(ctx: IMultipleCursorOperationContext): void { - if (ctx.shouldPushStackElementBefore) { - this._model.pushStackElement(); - ctx.shouldPushStackElementBefore = false; - } - - this._columnSelectData = null; - - this._internalExecuteCommands(ctx.executeCommands, ctx.isAutoWhitespaceCommand); - ctx.executeCommands = []; - - if (ctx.shouldPushStackElementAfter) { - this._model.pushStackElement(); - ctx.shouldPushStackElementAfter = false; - } - } - private _interpretCommandResult(cursorState: Selection[]): void { if (!cursorState || cursorState.length === 0) { return; @@ -537,18 +533,18 @@ export class Cursor extends Disposable implements ICursors { private _getEditOperations(ctx: IExecContext, commands: editorCommon.ICommand[], isAutoWhitespaceCommand: boolean[]): ICommandsData { let operations: editorCommon.IIdentifiedSingleEditOperation[] = []; - let anyoneHadTrackedEditOperation: boolean = false; + let hadTrackedEditOperation: boolean = false; for (let i = 0, len = commands.length; i < len; i++) { if (commands[i]) { - const oneResult = this._getEditOperationsFromCommand(ctx, i, commands[i], isAutoWhitespaceCommand[i]); - operations = operations.concat(oneResult.operations); - anyoneHadTrackedEditOperation = anyoneHadTrackedEditOperation || oneResult.hadTrackedEditOperation; + const r = this._getEditOperationsFromCommand(ctx, i, commands[i], isAutoWhitespaceCommand[i]); + operations = operations.concat(r.operations); + hadTrackedEditOperation = hadTrackedEditOperation || r.hadTrackedEditOperation; } } return { operations: operations, - anyoneHadTrackedEditOperation: anyoneHadTrackedEditOperation + hadTrackedEditOperation: hadTrackedEditOperation }; } @@ -601,19 +597,6 @@ export class Cursor extends Disposable implements ICursors { return loserCursorsMap; } - private _internalExecuteCommands(commands: editorCommon.ICommand[], isAutoWhitespaceCommand: boolean[]): void { - const ctx: IExecContext = { - selectionStartMarkers: [], - positionMarkers: [] - }; - - this._innerExecuteCommands(ctx, commands, isAutoWhitespaceCommand); - for (let i = 0; i < ctx.selectionStartMarkers.length; i++) { - this._model._removeMarker(ctx.selectionStartMarkers[i]); - this._model._removeMarker(ctx.positionMarkers[i]); - } - } - private _arrayIsEmpty(commands: editorCommon.ICommand[]): boolean { for (let i = 0, len = commands.length; i < len; i++) { if (commands[i]) { @@ -670,7 +653,7 @@ export class Cursor extends Disposable implements ICursors { // TODO@Alex: find a better way to do this. // give the hint that edit operations are tracked to the model - if (commandsData.anyoneHadTrackedEditOperation && filteredOperations.length > 0) { + if (commandsData.hadTrackedEditOperation && filteredOperations.length > 0) { filteredOperations[0]._isTracked = true; } const selectionsAfter = this._model.pushEditOperations(selectionsBefore, filteredOperations, (inverseEditOperations: editorCommon.IIdentifiedSingleEditOperation[]): Selection[] => { diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index 49633b4b90f..0aa97317662 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -104,8 +104,7 @@ export class CursorCollection { } public setSelections(selections: ISelection[]): void { - this.primaryCursor.setSelection(this.context, selections[0]); - this._setSecondarySelections(selections.slice(1)); + this.setStates(CursorState.fromModelSelections(selections)); } public getPrimaryCursor(): CursorState { @@ -130,7 +129,7 @@ export class CursorCollection { if (secondaryCursorsLength < secondaryStatesLength) { let createCnt = secondaryStatesLength - secondaryCursorsLength; for (let i = 0; i < createCnt; i++) { - this._addSecondaryCursor(null); + this._addSecondaryCursor(); } } else if (secondaryCursorsLength > secondaryStatesLength) { let removeCnt = secondaryCursorsLength - secondaryStatesLength; @@ -144,19 +143,16 @@ export class CursorCollection { } } - public killSecondaryCursors(): boolean { - return (this._setSecondarySelections([]) > 0); + public killSecondaryCursors(): void { + this._setSecondaryStates([]); } public normalize(): void { this._mergeCursorsIfNecessary(); } - private _addSecondaryCursor(selection: ISelection): void { + private _addSecondaryCursor(): void { var newCursor = new OneCursor(this.context); - if (selection) { - newCursor.setSelection(this.context, selection); - } this.secondaryCursors.push(newCursor); this.lastAddedCursorIndex = this.secondaryCursors.length; } @@ -168,39 +164,6 @@ export class CursorCollection { return this.lastAddedCursorIndex; } - /** - * Creates or disposes secondary cursors as necessary to match the number of `secondarySelections`. - * Return value: - * - a positive number indicates the number of secondary cursors added - * - 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[]): number { - var secondaryCursorsLength = this.secondaryCursors.length; - var secondarySelectionsLength = secondarySelections.length; - var returnValue = secondarySelectionsLength - secondaryCursorsLength; - - if (secondaryCursorsLength < secondarySelectionsLength) { - var createCnt = secondarySelectionsLength - secondaryCursorsLength; - for (var i = 0; i < createCnt; i++) { - this._addSecondaryCursor(null); - } - } else if (secondaryCursorsLength > secondarySelectionsLength) { - var removeCnt = secondaryCursorsLength - secondarySelectionsLength; - for (var i = 0; i < removeCnt; i++) { - this._removeSecondaryCursor(this.secondaryCursors.length - 1); - } - } - - for (var i = 0; i < secondarySelectionsLength; i++) { - if (secondarySelections[i]) { - this.secondaryCursors[i].setSelection(this.context, secondarySelections[i]); - } - } - - return returnValue; - } - private _removeSecondaryCursor(removeIndex: number): void { if (this.lastAddedCursorIndex >= removeIndex + 1) { this.lastAddedCursorIndex--; @@ -274,7 +237,8 @@ export class CursorCollection { } sortedCursors[winnerSortedCursorIndex].selection = resultingSelection; - cursors[winnerIndex].setSelection(this.context, resultingSelection); + const resultingState = CursorState.fromModelSelection(resultingSelection); + cursors[winnerIndex].setState(this.context, resultingState.modelState, resultingState.viewState); } for (var j = 0; j < sortedCursors.length; j++) { diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 55e1413e192..81bd4c7a186 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -9,7 +9,7 @@ import { CharCode } from 'vs/base/common/charCode'; import * as strings from 'vs/base/common/strings'; import { ICommand, TextModelResolvedOptions, IConfiguration, IModel } from 'vs/editor/common/editorCommon'; import { TextModel } from 'vs/editor/common/model/textModel'; -import { Selection } from 'vs/editor/common/core/selection'; +import { Selection, ISelection } from 'vs/editor/common/core/selection'; import { Range } from 'vs/editor/common/core/range'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -354,6 +354,26 @@ export class CursorState { return new CursorState(null, viewState); } + public static fromModelSelection(modelSelection: ISelection): CursorState { + const selectionStartLineNumber = modelSelection.selectionStartLineNumber; + const selectionStartColumn = modelSelection.selectionStartColumn; + const positionLineNumber = modelSelection.positionLineNumber; + const positionColumn = modelSelection.positionColumn; + const modelState = new SingleCursorState( + new Range(selectionStartLineNumber, selectionStartColumn, selectionStartLineNumber, selectionStartColumn), 0, + new Position(positionLineNumber, positionColumn), 0 + ); + return CursorState.fromModelState(modelState); + } + + public static fromModelSelections(modelSelections: ISelection[]): CursorState[] { + let states: CursorState[] = []; + for (let i = 0, len = modelSelections.length; i < len; i++) { + states[i] = this.fromModelSelection(modelSelections[i]); + } + return states; + } + public static ensureInEditableRange(context: CursorContext, states: CursorState[]): CursorState[] { const model = context.model; if (!model.hasEditableRange()) { diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 6fde100b0b8..ae9c990ec4a 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -7,7 +7,7 @@ import { SingleCursorState, CursorContext, CursorState } from 'vs/editor/common/controller/cursorCommon'; 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 { Selection, SelectionDirection } from 'vs/editor/common/core/selection'; export class OneCursor { @@ -49,22 +49,6 @@ export class OneCursor { this._setState(context, this.modelState, this.viewState); } - 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 - ); - } - public setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState): void { this._setState(context, modelState, viewState); }