mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode e6a45f4242ebddb7aa9a229f85555e8a3bd987e2 (#9253)
* Merge from vscode e6a45f4242ebddb7aa9a229f85555e8a3bd987e2 * skip failing tests * remove github-authentication extensions * ignore github compile steps * ignore github compile steps * check in compiled files
This commit is contained in:
@@ -287,7 +287,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
public options!: ComputedEditorOptions;
|
||||
|
||||
private _isDominatedByLongLines: boolean;
|
||||
private _maxLineNumber: number;
|
||||
private _viewLineCount: number;
|
||||
private _lineNumbersDigitCount: number;
|
||||
|
||||
private _rawOptions: IEditorOptions;
|
||||
@@ -299,7 +299,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
this.isSimpleWidget = isSimpleWidget;
|
||||
|
||||
this._isDominatedByLongLines = false;
|
||||
this._maxLineNumber = 1;
|
||||
this._viewLineCount = 1;
|
||||
this._lineNumbersDigitCount = 1;
|
||||
|
||||
this._rawOptions = deepCloneAndMigrateOptions(_options);
|
||||
@@ -349,7 +349,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
fontInfo: this.readConfiguration(bareFontInfo),
|
||||
extraEditorClassName: partialEnv.extraEditorClassName,
|
||||
isDominatedByLongLines: this._isDominatedByLongLines,
|
||||
maxLineNumber: this._maxLineNumber,
|
||||
viewLineCount: this._viewLineCount,
|
||||
lineNumbersDigitCount: this._lineNumbersDigitCount,
|
||||
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
|
||||
pixelRatio: partialEnv.pixelRatio,
|
||||
@@ -408,11 +408,19 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
}
|
||||
|
||||
public setMaxLineNumber(maxLineNumber: number): void {
|
||||
if (this._maxLineNumber === maxLineNumber) {
|
||||
const lineNumbersDigitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
|
||||
if (this._lineNumbersDigitCount === lineNumbersDigitCount) {
|
||||
return;
|
||||
}
|
||||
this._maxLineNumber = maxLineNumber;
|
||||
this._lineNumbersDigitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
|
||||
this._lineNumbersDigitCount = lineNumbersDigitCount;
|
||||
this._recomputeOptions();
|
||||
}
|
||||
|
||||
public setViewLineCount(viewLineCount: number): void {
|
||||
if (this._viewLineCount === viewLineCount) {
|
||||
return;
|
||||
}
|
||||
this._viewLineCount = viewLineCount;
|
||||
this._recomputeOptions();
|
||||
}
|
||||
|
||||
|
||||
@@ -678,7 +678,7 @@ export interface IEnvironmentalOptions {
|
||||
readonly fontInfo: FontInfo;
|
||||
readonly extraEditorClassName: string;
|
||||
readonly isDominatedByLongLines: boolean;
|
||||
readonly maxLineNumber: number;
|
||||
readonly viewLineCount: number;
|
||||
readonly lineNumbersDigitCount: number;
|
||||
readonly emptySelectionClipboard: boolean;
|
||||
readonly pixelRatio: number;
|
||||
@@ -1733,7 +1733,7 @@ export interface EditorLayoutInfoComputerEnv {
|
||||
outerWidth: number;
|
||||
outerHeight: number;
|
||||
lineHeight: number;
|
||||
maxLineNumber: number;
|
||||
viewLineCount: number;
|
||||
lineNumbersDigitCount: number;
|
||||
typicalHalfwidthCharacterWidth: number;
|
||||
maxDigitWidth: number;
|
||||
@@ -1757,7 +1757,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
outerWidth: env.outerWidth,
|
||||
outerHeight: env.outerHeight,
|
||||
lineHeight: env.fontInfo.lineHeight,
|
||||
maxLineNumber: env.maxLineNumber,
|
||||
viewLineCount: env.viewLineCount,
|
||||
lineNumbersDigitCount: env.lineNumbersDigitCount,
|
||||
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
|
||||
maxDigitWidth: env.fontInfo.maxDigitWidth,
|
||||
@@ -1766,7 +1766,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
}
|
||||
|
||||
public static computeContainedMinimapLineCount(input: {
|
||||
modelLineCount: number;
|
||||
viewLineCount: number;
|
||||
scrollBeyondLastLine: boolean;
|
||||
height: number;
|
||||
lineHeight: number;
|
||||
@@ -1774,8 +1774,8 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
}): { typicalViewportLineCount: number; extraLinesBeyondLastLine: number; desiredRatio: number; minimapLineCount: number; } {
|
||||
const typicalViewportLineCount = input.height / input.lineHeight;
|
||||
const extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;
|
||||
const desiredRatio = (input.modelLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);
|
||||
const minimapLineCount = Math.floor(input.modelLineCount / desiredRatio);
|
||||
const desiredRatio = (input.viewLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);
|
||||
const minimapLineCount = Math.floor(input.viewLineCount / desiredRatio);
|
||||
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
|
||||
}
|
||||
|
||||
@@ -1863,9 +1863,9 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
let minimapWidthMultiplier: number = 1;
|
||||
|
||||
if (minimapMode === 'cover' || minimapMode === 'contain') {
|
||||
const modelLineCount = env.maxLineNumber;
|
||||
const viewLineCount = env.viewLineCount;
|
||||
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
||||
modelLineCount: modelLineCount,
|
||||
viewLineCount: viewLineCount,
|
||||
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||
height: outerHeight,
|
||||
lineHeight: lineHeight,
|
||||
@@ -1873,7 +1873,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
});
|
||||
// ratio is intentionally not part of the layout to avoid the layout changing all the time
|
||||
// when doing sampling
|
||||
const ratio = modelLineCount / minimapLineCount;
|
||||
const ratio = viewLineCount / minimapLineCount;
|
||||
|
||||
if (ratio > 1) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
@@ -1882,7 +1882,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
minimapLineHeight = 1;
|
||||
minimapCharWidth = minimapScale / pixelRatio;
|
||||
} else {
|
||||
const effectiveMinimapHeight = Math.ceil((modelLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||
if (minimapMode === 'cover' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
const configuredFontScale = minimapScale;
|
||||
@@ -1892,7 +1892,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
minimapWidthMultiplier = Math.min(2, minimapScale / configuredFontScale);
|
||||
}
|
||||
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
|
||||
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, modelLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
|
||||
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { Range, IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection, SelectionDirection } from 'vs/editor/common/core/selection';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { RawContentChangedType } from 'vs/editor/common/model/textModelEvents';
|
||||
import { RawContentChangedType, ModelRawContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -186,6 +186,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
public context: CursorContext;
|
||||
private _cursors: CursorCollection;
|
||||
|
||||
private _hasFocus: boolean;
|
||||
private _isHandling: boolean;
|
||||
private _isDoingComposition: boolean;
|
||||
private _selectionsWhenCompositionStarted: Selection[] | null;
|
||||
@@ -202,6 +203,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
this.context = new CursorContext(this._configuration, this._model, this._viewModel);
|
||||
this._cursors = new CursorCollection(this.context);
|
||||
|
||||
this._hasFocus = false;
|
||||
this._isHandling = false;
|
||||
this._isDoingComposition = false;
|
||||
this._selectionsWhenCompositionStarted = null;
|
||||
@@ -215,8 +217,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
return;
|
||||
}
|
||||
|
||||
let hadFlushEvent = e.containsEvent(RawContentChangedType.Flush);
|
||||
this._onModelContentChanged(hadFlushEvent);
|
||||
this._onModelContentChanged(e);
|
||||
}));
|
||||
|
||||
this._register(viewModel.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
@@ -264,6 +265,10 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public setHasFocus(hasFocus: boolean): void {
|
||||
this._hasFocus = hasFocus;
|
||||
}
|
||||
|
||||
private _validateAutoClosedActions(): void {
|
||||
if (this._autoClosedActions.length > 0) {
|
||||
let selections: Range[] = this._cursors.getSelections();
|
||||
@@ -392,8 +397,9 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
this.reveal('restoreState', true, RevealTarget.Primary, editorCommon.ScrollType.Immediate);
|
||||
}
|
||||
|
||||
private _onModelContentChanged(hadFlushEvent: boolean): void {
|
||||
private _onModelContentChanged(e: ModelRawContentChangedEvent): void {
|
||||
|
||||
const hadFlushEvent = e.containsEvent(RawContentChangedType.Flush);
|
||||
this._prevEditOperationType = EditOperationType.Other;
|
||||
|
||||
if (hadFlushEvent) {
|
||||
@@ -403,8 +409,13 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
this._validateAutoClosedActions();
|
||||
this._emitStateChangedIfNecessary('model', CursorChangeReason.ContentFlush, null);
|
||||
} else {
|
||||
const selectionsFromMarkers = this._cursors.readSelectionFromMarkers();
|
||||
this.setStates('modelChange', CursorChangeReason.RecoverFromMarkers, CursorState.fromModelSelections(selectionsFromMarkers));
|
||||
if (this._hasFocus && e.resultingSelection && e.resultingSelection.length > 0) {
|
||||
const cursorState = CursorState.fromModelSelections(e.resultingSelection);
|
||||
this.setStates('modelChange', e.isUndoing ? CursorChangeReason.Undo : e.isRedoing ? CursorChangeReason.Redo : CursorChangeReason.RecoverFromMarkers, cursorState);
|
||||
} else {
|
||||
const selectionsFromMarkers = this._cursors.readSelectionFromMarkers();
|
||||
this.setStates('modelChange', CursorChangeReason.RecoverFromMarkers, CursorState.fromModelSelections(selectionsFromMarkers));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,11 +715,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
const oldState = new CursorModelState(this._model, this);
|
||||
let cursorChangeReason = CursorChangeReason.NotSet;
|
||||
|
||||
if (handlerId !== H.Undo && handlerId !== H.Redo) {
|
||||
// TODO@Alex: if the undo/redo stack contains non-null selections
|
||||
// it would also be OK to stop tracking selections here
|
||||
this._cursors.stopTrackingSelections();
|
||||
}
|
||||
this._cursors.stopTrackingSelections();
|
||||
|
||||
// ensure valid state on all cursors
|
||||
this._cursors.ensureValidState();
|
||||
@@ -734,16 +741,6 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
this._cut();
|
||||
break;
|
||||
|
||||
case H.Undo:
|
||||
cursorChangeReason = CursorChangeReason.Undo;
|
||||
this._interpretCommandResult(this._model.undo());
|
||||
break;
|
||||
|
||||
case H.Redo:
|
||||
cursorChangeReason = CursorChangeReason.Redo;
|
||||
this._interpretCommandResult(this._model.redo());
|
||||
break;
|
||||
|
||||
case H.ExecuteCommand:
|
||||
this._externalExecuteCommand(<editorCommon.ICommand>payload);
|
||||
break;
|
||||
@@ -762,9 +759,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
|
||||
this._isHandling = false;
|
||||
|
||||
if (handlerId !== H.Undo && handlerId !== H.Redo) {
|
||||
this._cursors.startTrackingSelections();
|
||||
}
|
||||
this._cursors.startTrackingSelections();
|
||||
|
||||
this._validateAutoClosedActions();
|
||||
|
||||
|
||||
@@ -154,6 +154,7 @@ export interface IConfiguration extends IDisposable {
|
||||
readonly options: IComputedEditorOptions;
|
||||
|
||||
setMaxLineNumber(maxLineNumber: number): void;
|
||||
setViewLineCount(viewLineCount: number): void;
|
||||
updateOptions(newOptions: IEditorOptions): void;
|
||||
getRawOptions(): IEditorOptions;
|
||||
observeReferenceElement(dimension?: IDimension): void;
|
||||
@@ -466,6 +467,12 @@ export interface IEditor {
|
||||
*/
|
||||
revealRangeNearTop(range: IRange, scrollType?: ScrollType): void;
|
||||
|
||||
/**
|
||||
* Scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport,
|
||||
* optimized for viewing a code definition. Only if it lies outside the viewport.
|
||||
*/
|
||||
revealRangeNearTopIfOutsideViewport(range: IRange, scrollType?: ScrollType): void;
|
||||
|
||||
/**
|
||||
* Directly trigger a handler or an editor action.
|
||||
* @param source The source of the call.
|
||||
@@ -671,9 +678,5 @@ export const Handler = {
|
||||
CompositionStart: 'compositionStart',
|
||||
CompositionEnd: 'compositionEnd',
|
||||
Paste: 'paste',
|
||||
|
||||
Cut: 'cut',
|
||||
|
||||
Undo: 'undo',
|
||||
Redo: 'redo',
|
||||
};
|
||||
|
||||
@@ -379,6 +379,13 @@ export interface IValidEditOperation {
|
||||
forceMoveMarkers: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IValidEditOperations {
|
||||
operations: IValidEditOperation[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback that can compute the cursor state after applying a series of edit operations.
|
||||
*/
|
||||
@@ -1086,18 +1093,28 @@ export interface ITextModel {
|
||||
*/
|
||||
applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[];
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_applyEdits(edits: IValidEditOperations[], isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): IValidEditOperations[];
|
||||
|
||||
/**
|
||||
* Change the end of line sequence without recording in the undo stack.
|
||||
* This can have dire consequences on the undo stack! See @pushEOL for the preferred way.
|
||||
*/
|
||||
setEOL(eol: EndOfLineSequence): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_setEOL(eol: EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void;
|
||||
|
||||
/**
|
||||
* Undo edit operations until the first previous stop point created by `pushStackElement`.
|
||||
* The inverse edit operations will be pushed on the redo stack.
|
||||
* @internal
|
||||
*/
|
||||
undo(): Selection[] | null;
|
||||
undo(): void;
|
||||
|
||||
/**
|
||||
* Is there anything in the undo stack?
|
||||
@@ -1110,7 +1127,7 @@ export interface ITextModel {
|
||||
* The inverse edit operations will be pushed on the undo stack.
|
||||
* @internal
|
||||
*/
|
||||
redo(): Selection[] | null;
|
||||
redo(): void;
|
||||
|
||||
/**
|
||||
* Is there anything in the redo stack?
|
||||
|
||||
@@ -3,61 +3,72 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation } from 'vs/editor/common/model';
|
||||
import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel, IValidEditOperations } from 'vs/editor/common/model';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IUndoRedoService, IUndoRedoElement, IUndoRedoContext } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
interface IEditOperation {
|
||||
operations: IValidEditOperation[];
|
||||
}
|
||||
class EditStackElement implements IUndoRedoElement {
|
||||
|
||||
interface IStackElement {
|
||||
readonly beforeVersionId: number;
|
||||
readonly beforeCursorState: Selection[] | null;
|
||||
readonly afterCursorState: Selection[] | null;
|
||||
readonly afterVersionId: number;
|
||||
public readonly label: string;
|
||||
private _isOpen: boolean;
|
||||
private readonly _model: TextModel;
|
||||
private readonly _beforeVersionId: number;
|
||||
private readonly _beforeCursorState: Selection[];
|
||||
private _afterVersionId: number;
|
||||
private _afterCursorState: Selection[] | null;
|
||||
private _edits: IValidEditOperations[];
|
||||
|
||||
undo(model: TextModel): void;
|
||||
redo(model: TextModel): void;
|
||||
}
|
||||
|
||||
class EditStackElement implements IStackElement {
|
||||
public readonly beforeVersionId: number;
|
||||
public readonly beforeCursorState: Selection[];
|
||||
public afterCursorState: Selection[] | null;
|
||||
public afterVersionId: number;
|
||||
|
||||
public editOperations: IEditOperation[];
|
||||
|
||||
constructor(beforeVersionId: number, beforeCursorState: Selection[]) {
|
||||
this.beforeVersionId = beforeVersionId;
|
||||
this.beforeCursorState = beforeCursorState;
|
||||
this.afterCursorState = null;
|
||||
this.afterVersionId = -1;
|
||||
this.editOperations = [];
|
||||
public get resources(): readonly URI[] {
|
||||
return [this._model.uri];
|
||||
}
|
||||
|
||||
public undo(model: TextModel): void {
|
||||
// Apply all operations in reverse order
|
||||
for (let i = this.editOperations.length - 1; i >= 0; i--) {
|
||||
this.editOperations[i] = {
|
||||
operations: model.applyEdits(this.editOperations[i].operations)
|
||||
};
|
||||
}
|
||||
constructor(model: TextModel, beforeVersionId: number, beforeCursorState: Selection[], afterVersionId: number, afterCursorState: Selection[] | null, operations: IValidEditOperation[]) {
|
||||
this.label = nls.localize('edit', "Typing");
|
||||
this._isOpen = true;
|
||||
this._model = model;
|
||||
this._beforeVersionId = beforeVersionId;
|
||||
this._beforeCursorState = beforeCursorState;
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._afterCursorState = afterCursorState;
|
||||
this._edits = [{ operations: operations }];
|
||||
}
|
||||
|
||||
public redo(model: TextModel): void {
|
||||
// Apply all operations
|
||||
for (let i = 0; i < this.editOperations.length; i++) {
|
||||
this.editOperations[i] = {
|
||||
operations: model.applyEdits(this.editOperations[i].operations)
|
||||
};
|
||||
}
|
||||
public isOpen(): boolean {
|
||||
return this._isOpen;
|
||||
}
|
||||
|
||||
public append(operations: IValidEditOperation[], afterVersionId: number, afterCursorState: Selection[] | null): void {
|
||||
this._edits.push({ operations: operations });
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._afterCursorState = afterCursorState;
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
undo(ctx: IUndoRedoContext): void {
|
||||
this._isOpen = false;
|
||||
this._edits.reverse();
|
||||
this._edits = this._model._applyEdits(this._edits, true, false, this._beforeVersionId, this._beforeCursorState);
|
||||
}
|
||||
|
||||
redo(ctx: IUndoRedoContext): void {
|
||||
this._isOpen = false;
|
||||
this._edits.reverse();
|
||||
this._edits = this._model._applyEdits(this._edits, false, true, this._afterVersionId, this._afterCursorState);
|
||||
}
|
||||
|
||||
invalidate(resource: URI): void {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
function getModelEOL(model: TextModel): EndOfLineSequence {
|
||||
function getModelEOL(model: ITextModel): EndOfLineSequence {
|
||||
const eol = model.getEOL();
|
||||
if (eol === '\n') {
|
||||
return EndOfLineSequence.LF;
|
||||
@@ -66,32 +77,40 @@ function getModelEOL(model: TextModel): EndOfLineSequence {
|
||||
}
|
||||
}
|
||||
|
||||
class EOLStackElement implements IStackElement {
|
||||
public readonly beforeVersionId: number;
|
||||
public readonly beforeCursorState: Selection[] | null;
|
||||
public readonly afterCursorState: Selection[] | null;
|
||||
public afterVersionId: number;
|
||||
class EOLStackElement implements IUndoRedoElement {
|
||||
|
||||
public eol: EndOfLineSequence;
|
||||
public readonly label: string;
|
||||
private readonly _model: TextModel;
|
||||
private readonly _beforeVersionId: number;
|
||||
private readonly _afterVersionId: number;
|
||||
private _eol: EndOfLineSequence;
|
||||
|
||||
constructor(beforeVersionId: number, setEOL: EndOfLineSequence) {
|
||||
this.beforeVersionId = beforeVersionId;
|
||||
this.beforeCursorState = null;
|
||||
this.afterCursorState = null;
|
||||
this.afterVersionId = -1;
|
||||
this.eol = setEOL;
|
||||
public get resources(): readonly URI[] {
|
||||
return [this._model.uri];
|
||||
}
|
||||
|
||||
public undo(model: TextModel): void {
|
||||
let redoEOL = getModelEOL(model);
|
||||
model.setEOL(this.eol);
|
||||
this.eol = redoEOL;
|
||||
constructor(model: TextModel, beforeVersionId: number, afterVersionId: number, eol: EndOfLineSequence) {
|
||||
this.label = nls.localize('eol', "Change End Of Line Sequence");
|
||||
this._model = model;
|
||||
this._beforeVersionId = beforeVersionId;
|
||||
this._afterVersionId = afterVersionId;
|
||||
this._eol = eol;
|
||||
}
|
||||
|
||||
public redo(model: TextModel): void {
|
||||
let undoEOL = getModelEOL(model);
|
||||
model.setEOL(this.eol);
|
||||
this.eol = undoEOL;
|
||||
undo(ctx: IUndoRedoContext): void {
|
||||
const redoEOL = getModelEOL(this._model);
|
||||
this._model._setEOL(this._eol, true, false, this._beforeVersionId, null);
|
||||
this._eol = redoEOL;
|
||||
}
|
||||
|
||||
redo(ctx: IUndoRedoContext): void {
|
||||
const undoEOL = getModelEOL(this._model);
|
||||
this._model._setEOL(this._eol, false, true, this._afterVersionId, null);
|
||||
this._eol = undoEOL;
|
||||
}
|
||||
|
||||
invalidate(resource: URI): void {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,76 +121,52 @@ export interface IUndoRedoResult {
|
||||
|
||||
export class EditStack {
|
||||
|
||||
private readonly model: TextModel;
|
||||
private currentOpenStackElement: IStackElement | null;
|
||||
private past: IStackElement[];
|
||||
private future: IStackElement[];
|
||||
private readonly _model: TextModel;
|
||||
private readonly _undoRedoService: IUndoRedoService;
|
||||
|
||||
constructor(model: TextModel) {
|
||||
this.model = model;
|
||||
this.currentOpenStackElement = null;
|
||||
this.past = [];
|
||||
this.future = [];
|
||||
constructor(model: TextModel, undoRedoService: IUndoRedoService) {
|
||||
this._model = model;
|
||||
this._undoRedoService = undoRedoService;
|
||||
}
|
||||
|
||||
public pushStackElement(): void {
|
||||
if (this.currentOpenStackElement !== null) {
|
||||
this.past.push(this.currentOpenStackElement);
|
||||
this.currentOpenStackElement = null;
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement) {
|
||||
lastElement.close();
|
||||
}
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this.currentOpenStackElement = null;
|
||||
this.past = [];
|
||||
this.future = [];
|
||||
this._undoRedoService.removeElements(this._model.uri);
|
||||
}
|
||||
|
||||
public pushEOL(eol: EndOfLineSequence): void {
|
||||
// No support for parallel universes :(
|
||||
this.future = [];
|
||||
const beforeVersionId = this._model.getAlternativeVersionId();
|
||||
const inverseEOL = getModelEOL(this._model);
|
||||
this._model.setEOL(eol);
|
||||
const afterVersionId = this._model.getAlternativeVersionId();
|
||||
|
||||
if (this.currentOpenStackElement) {
|
||||
this.pushStackElement();
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement) {
|
||||
lastElement.close();
|
||||
}
|
||||
|
||||
const prevEOL = getModelEOL(this.model);
|
||||
let stackElement = new EOLStackElement(this.model.getAlternativeVersionId(), prevEOL);
|
||||
|
||||
this.model.setEOL(eol);
|
||||
|
||||
stackElement.afterVersionId = this.model.getVersionId();
|
||||
this.currentOpenStackElement = stackElement;
|
||||
this.pushStackElement();
|
||||
this._undoRedoService.pushElement(new EOLStackElement(this._model, inverseEOL, beforeVersionId, afterVersionId));
|
||||
}
|
||||
|
||||
public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
|
||||
// No support for parallel universes :(
|
||||
this.future = [];
|
||||
const beforeVersionId = this._model.getAlternativeVersionId();
|
||||
const inverseEditOperations = this._model.applyEdits(editOperations);
|
||||
const afterVersionId = this._model.getAlternativeVersionId();
|
||||
const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations);
|
||||
|
||||
let stackElement: EditStackElement | null = null;
|
||||
|
||||
if (this.currentOpenStackElement) {
|
||||
if (this.currentOpenStackElement instanceof EditStackElement) {
|
||||
stackElement = this.currentOpenStackElement;
|
||||
} else {
|
||||
this.pushStackElement();
|
||||
}
|
||||
const lastElement = this._undoRedoService.getLastElement(this._model.uri);
|
||||
if (lastElement && lastElement instanceof EditStackElement && lastElement.isOpen()) {
|
||||
lastElement.append(inverseEditOperations, afterVersionId, afterCursorState);
|
||||
} else {
|
||||
this._undoRedoService.pushElement(new EditStackElement(this._model, beforeVersionId, beforeCursorState, afterVersionId, afterCursorState, inverseEditOperations));
|
||||
}
|
||||
|
||||
if (!this.currentOpenStackElement) {
|
||||
stackElement = new EditStackElement(this.model.getAlternativeVersionId(), beforeCursorState);
|
||||
this.currentOpenStackElement = stackElement;
|
||||
}
|
||||
|
||||
const inverseEditOperation: IEditOperation = {
|
||||
operations: this.model.applyEdits(editOperations)
|
||||
};
|
||||
|
||||
stackElement!.editOperations.push(inverseEditOperation);
|
||||
stackElement!.afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperation.operations);
|
||||
stackElement!.afterVersionId = this.model.getVersionId();
|
||||
return stackElement!.afterCursorState;
|
||||
return afterCursorState;
|
||||
}
|
||||
|
||||
private static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IValidEditOperation[]): Selection[] | null {
|
||||
@@ -182,62 +177,4 @@ export class EditStack {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public undo(): IUndoRedoResult | null {
|
||||
|
||||
this.pushStackElement();
|
||||
|
||||
if (this.past.length > 0) {
|
||||
const pastStackElement = this.past.pop()!;
|
||||
|
||||
try {
|
||||
pastStackElement.undo(this.model);
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
this.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
this.future.push(pastStackElement);
|
||||
|
||||
return {
|
||||
selections: pastStackElement.beforeCursorState,
|
||||
recordedVersionId: pastStackElement.beforeVersionId
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public canUndo(): boolean {
|
||||
return (this.past.length > 0) || this.currentOpenStackElement !== null;
|
||||
}
|
||||
|
||||
public redo(): IUndoRedoResult | null {
|
||||
|
||||
if (this.future.length > 0) {
|
||||
const futureStackElement = this.future.pop()!;
|
||||
|
||||
try {
|
||||
futureStackElement.redo(this.model);
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
this.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
this.past.push(futureStackElement);
|
||||
|
||||
return {
|
||||
selections: futureStackElement.afterCursorState,
|
||||
recordedVersionId: futureStackElement.afterVersionId
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public canRedo(): boolean {
|
||||
return (this.future.length > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
import { EditorTheme } from 'vs/editor/common/view/viewContext';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
|
||||
|
||||
function createTextBufferBuilder() {
|
||||
return new PieceTreeTextBufferBuilder();
|
||||
@@ -188,7 +190,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
};
|
||||
|
||||
public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel {
|
||||
return new TextModel(text, options, languageIdentifier, uri);
|
||||
return new TextModel(text, options, languageIdentifier, uri, new UndoRedoService());
|
||||
}
|
||||
|
||||
public static resolveOptions(textBuffer: model.ITextBuffer, options: model.ITextModelCreationOptions): model.TextModelResolvedOptions {
|
||||
@@ -253,6 +255,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
public readonly id: string;
|
||||
public readonly isForSimpleWidget: boolean;
|
||||
private readonly _associatedResource: URI;
|
||||
private readonly _undoRedoService: IUndoRedoService;
|
||||
private _attachedEditorCount: number;
|
||||
private _buffer: model.ITextBuffer;
|
||||
private _options: model.TextModelResolvedOptions;
|
||||
@@ -268,7 +271,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
private readonly _isTooLargeForTokenization: boolean;
|
||||
|
||||
//#region Editing
|
||||
private _commandManager: EditStack;
|
||||
private readonly _commandManager: EditStack;
|
||||
private _isUndoing: boolean;
|
||||
private _isRedoing: boolean;
|
||||
private _trimAutoWhitespaceLines: number[] | null;
|
||||
@@ -293,7 +296,13 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
private readonly _tokenization: TextModelTokenization;
|
||||
//#endregion
|
||||
|
||||
constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier | null, associatedResource: URI | null = null) {
|
||||
constructor(
|
||||
source: string | model.ITextBufferFactory,
|
||||
creationOptions: model.ITextModelCreationOptions,
|
||||
languageIdentifier: LanguageIdentifier | null,
|
||||
associatedResource: URI | null = null,
|
||||
undoRedoService: IUndoRedoService
|
||||
) {
|
||||
super();
|
||||
|
||||
// Generate a new unique model id
|
||||
@@ -305,6 +314,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
} else {
|
||||
this._associatedResource = associatedResource;
|
||||
}
|
||||
this._undoRedoService = undoRedoService;
|
||||
this._attachedEditorCount = 0;
|
||||
|
||||
this._buffer = createTextBuffer(source, creationOptions.defaultEOL);
|
||||
@@ -347,7 +357,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
this._decorations = Object.create(null);
|
||||
this._decorationsTree = new DecorationsTrees();
|
||||
|
||||
this._commandManager = new EditStack(this);
|
||||
this._commandManager = new EditStack(this, undoRedoService);
|
||||
this._isUndoing = false;
|
||||
this._isRedoing = false;
|
||||
this._trimAutoWhitespaceLines = null;
|
||||
@@ -362,6 +372,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
this._onWillDispose.fire();
|
||||
this._languageRegistryListener.dispose();
|
||||
this._tokenization.dispose();
|
||||
this._undoRedoService.removeElements(this.uri);
|
||||
this._isDisposed = true;
|
||||
super.dispose();
|
||||
this._isDisposing = false;
|
||||
@@ -436,7 +447,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
this._decorationsTree = new DecorationsTrees();
|
||||
|
||||
// Destroy my edit history and settings
|
||||
this._commandManager = new EditStack(this);
|
||||
this._commandManager.clear();
|
||||
this._trimAutoWhitespaceLines = null;
|
||||
|
||||
this._emitContentChangedEvent(
|
||||
@@ -483,6 +494,21 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
);
|
||||
}
|
||||
|
||||
_setEOL(eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
this._isUndoing = isUndoing;
|
||||
this._isRedoing = isRedoing;
|
||||
this.setEOL(eol);
|
||||
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
|
||||
} finally {
|
||||
this._isUndoing = false;
|
||||
this._eventEmitter.endDeferredEmit(resultingSelection);
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
private _onBeforeEOLChange(): void {
|
||||
// Ensure all decorations get their `range` set.
|
||||
const versionId = this.getVersionId();
|
||||
@@ -1272,18 +1298,37 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer);
|
||||
}
|
||||
|
||||
_applyEdits(edits: model.IValidEditOperations[], isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): model.IValidEditOperations[] {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
this._isUndoing = isUndoing;
|
||||
this._isRedoing = isRedoing;
|
||||
let reverseEdits: model.IValidEditOperations[] = [];
|
||||
for (let i = 0, len = edits.length; i < len; i++) {
|
||||
reverseEdits[i] = { operations: this.applyEdits(edits[i].operations) };
|
||||
}
|
||||
this._overwriteAlternativeVersionId(resultingAlternativeVersionId);
|
||||
return reverseEdits;
|
||||
} finally {
|
||||
this._isUndoing = false;
|
||||
this._eventEmitter.endDeferredEmit(resultingSelection);
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IValidEditOperation[] {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
return this._applyEdits(this._validateEditOperations(rawOperations));
|
||||
return this._doApplyEdits(this._validateEditOperations(rawOperations));
|
||||
} finally {
|
||||
this._eventEmitter.endDeferredEmit();
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
}
|
||||
|
||||
private _applyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] {
|
||||
private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] {
|
||||
|
||||
const oldLineCount = this._buffer.getLineCount();
|
||||
const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace);
|
||||
@@ -1364,62 +1409,20 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return result.reverseEdits;
|
||||
}
|
||||
|
||||
private _undo(): Selection[] | null {
|
||||
this._isUndoing = true;
|
||||
let r = this._commandManager.undo();
|
||||
this._isUndoing = false;
|
||||
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this._overwriteAlternativeVersionId(r.recordedVersionId);
|
||||
|
||||
return r.selections;
|
||||
}
|
||||
|
||||
public undo(): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
return this._undo();
|
||||
} finally {
|
||||
this._eventEmitter.endDeferredEmit();
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
public undo(): void {
|
||||
this._undoRedoService.undo(this.uri);
|
||||
}
|
||||
|
||||
public canUndo(): boolean {
|
||||
return this._commandManager.canUndo();
|
||||
return this._undoRedoService.canUndo(this.uri);
|
||||
}
|
||||
|
||||
private _redo(): Selection[] | null {
|
||||
this._isRedoing = true;
|
||||
let r = this._commandManager.redo();
|
||||
this._isRedoing = false;
|
||||
|
||||
if (!r) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this._overwriteAlternativeVersionId(r.recordedVersionId);
|
||||
|
||||
return r.selections;
|
||||
}
|
||||
|
||||
public redo(): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
return this._redo();
|
||||
} finally {
|
||||
this._eventEmitter.endDeferredEmit();
|
||||
this._onDidChangeDecorations.endDeferredEmit();
|
||||
}
|
||||
public redo(): void {
|
||||
this._undoRedoService.redo(this.uri);
|
||||
}
|
||||
|
||||
public canRedo(): boolean {
|
||||
return this._commandManager.canRedo();
|
||||
return this._undoRedoService.canRedo(this.uri);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -3191,10 +3194,11 @@ export class DidChangeContentEmitter extends Disposable {
|
||||
this._deferredCnt++;
|
||||
}
|
||||
|
||||
public endDeferredEmit(): void {
|
||||
public endDeferredEmit(resultingSelection: Selection[] | null = null): void {
|
||||
this._deferredCnt--;
|
||||
if (this._deferredCnt === 0) {
|
||||
if (this._deferredEvent !== null) {
|
||||
this._deferredEvent.rawContentChangedEvent.resultingSelection = resultingSelection;
|
||||
const e = this._deferredEvent;
|
||||
this._deferredEvent = null;
|
||||
this._fastEmitter.fire(e);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
|
||||
/**
|
||||
* An event describing that the current mode associated with a model has changed.
|
||||
@@ -225,11 +226,14 @@ export class ModelRawContentChangedEvent {
|
||||
*/
|
||||
public readonly isRedoing: boolean;
|
||||
|
||||
public resultingSelection: Selection[] | null;
|
||||
|
||||
constructor(changes: ModelRawChange[], versionId: number, isUndoing: boolean, isRedoing: boolean) {
|
||||
this.changes = changes;
|
||||
this.versionId = versionId;
|
||||
this.isUndoing = isUndoing;
|
||||
this.isRedoing = isRedoing;
|
||||
this.resultingSelection = null;
|
||||
}
|
||||
|
||||
public containsEvent(type: RawContentChangedType): boolean {
|
||||
|
||||
@@ -25,6 +25,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { SparseEncodedTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
|
||||
export interface IEditorSemanticHighlightingOptions {
|
||||
enabled?: boolean;
|
||||
@@ -103,6 +104,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
private readonly _configurationService: IConfigurationService;
|
||||
private readonly _configurationServiceSubscription: IDisposable;
|
||||
private readonly _resourcePropertiesService: ITextResourcePropertiesService;
|
||||
private readonly _undoRedoService: IUndoRedoService;
|
||||
|
||||
private readonly _onModelAdded: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
|
||||
public readonly onModelAdded: Event<ITextModel> = this._onModelAdded.event;
|
||||
@@ -126,11 +128,13 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@ILogService logService: ILogService
|
||||
@ILogService logService: ILogService,
|
||||
@IUndoRedoService undoRedoService: IUndoRedoService
|
||||
) {
|
||||
super();
|
||||
this._configurationService = configurationService;
|
||||
this._resourcePropertiesService = resourcePropertiesService;
|
||||
this._undoRedoService = undoRedoService;
|
||||
this._models = {};
|
||||
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
|
||||
|
||||
@@ -272,7 +276,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI | undefined, isForSimpleWidget: boolean): ModelData {
|
||||
// create & save the model
|
||||
const options = this.getCreationOptions(languageIdentifier.language, resource, isForSimpleWidget);
|
||||
const model: TextModel = new TextModel(value, options, languageIdentifier, resource);
|
||||
const model: TextModel = new TextModel(value, options, languageIdentifier, resource, this._undoRedoService);
|
||||
const modelId = MODEL_ID(model.uri);
|
||||
|
||||
if (this._models[modelId]) {
|
||||
|
||||
@@ -195,6 +195,7 @@ export const enum VerticalRevealType {
|
||||
Top = 3,
|
||||
Bottom = 4,
|
||||
NearTop = 5,
|
||||
NearTopIfOutsideViewport = 6,
|
||||
}
|
||||
|
||||
export class ViewRevealRangeRequestEvent {
|
||||
|
||||
@@ -33,6 +33,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
private readonly configuration: IConfiguration;
|
||||
private readonly model: ITextModel;
|
||||
private readonly _tokenizeViewportSoon: RunOnceScheduler;
|
||||
private readonly _updateConfigurationViewLineCount: RunOnceScheduler;
|
||||
private hasFocus: boolean;
|
||||
private viewportStartLine: number;
|
||||
private viewportStartLineTrackedRange: string | null;
|
||||
@@ -56,6 +57,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this.configuration = configuration;
|
||||
this.model = model;
|
||||
this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50));
|
||||
this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0));
|
||||
this.hasFocus = false;
|
||||
this.viewportStartLine = -1;
|
||||
this.viewportStartLineTrackedRange = null;
|
||||
@@ -130,6 +132,8 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this._endEmit();
|
||||
}
|
||||
}));
|
||||
|
||||
this._updateConfigurationViewLineCountNow();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -142,6 +146,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges);
|
||||
}
|
||||
|
||||
private _updateConfigurationViewLineCountNow(): void {
|
||||
this.configuration.setViewLineCount(this.lines.getViewLineCount());
|
||||
}
|
||||
|
||||
public tokenizeViewport(): void {
|
||||
const linesViewportData = this.viewLayout.getLinesViewportData();
|
||||
const startPosition = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(linesViewportData.startLineNumber, 1));
|
||||
@@ -180,6 +188,8 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
// Never change the scroll position from 0 to something else...
|
||||
restorePreviousViewportStart = true;
|
||||
}
|
||||
|
||||
this._updateConfigurationViewLineCount.schedule();
|
||||
}
|
||||
|
||||
if (e.hasChanged(EditorOption.readOnly)) {
|
||||
@@ -301,6 +311,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
// Update the configuration and reset the centered view line
|
||||
this.viewportStartLine = -1;
|
||||
this.configuration.setMaxLineNumber(this.model.getLineCount());
|
||||
this._updateConfigurationViewLineCountNow();
|
||||
|
||||
// Recover viewport
|
||||
if (!this.hasFocus && this.model.getAttachedEditorCount() >= 2 && this.viewportStartLineTrackedRange) {
|
||||
@@ -358,6 +369,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
} finally {
|
||||
this._endEmit();
|
||||
}
|
||||
this._updateConfigurationViewLineCount.schedule();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -387,6 +399,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
} finally {
|
||||
this._endEmit();
|
||||
}
|
||||
this._updateConfigurationViewLineCount.schedule();
|
||||
}
|
||||
|
||||
public getVisibleRanges(): Range[] {
|
||||
|
||||
Reference in New Issue
Block a user