mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-27 13:16:59 +00:00
Simplify cursor code
This commit is contained in:
@@ -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]);
|
||||
});
|
||||
this._onHandler('recoverSelectionFromMarkers', (ctx: IMultipleCursorOperationContext) => {
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user