mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-23 08:39:54 +01:00
Simplify cursor handlers
This commit is contained in:
@@ -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[] => {
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user