mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
EditorScroll: Get rid of cursor -> view -> cursor recursion
This commit is contained in:
parent
17b8819f9b
commit
39608c5cb2
|
@ -50,7 +50,6 @@ import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'
|
|||
import { EditorScrollbar } from 'vs/editor/browser/viewParts/editorScrollbar/editorScrollbar';
|
||||
import { Minimap } from 'vs/editor/browser/viewParts/minimap/minimap';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { CursorMovePosition } from "vs/editor/common/controller/oneCursor";
|
||||
import { IEditorWhitespace } from "vs/editor/common/viewLayout/whitespaceComputer";
|
||||
|
||||
export interface IContentWidgetData {
|
||||
|
@ -427,21 +426,9 @@ export class View extends ViewEventHandler {
|
|||
return false;
|
||||
}
|
||||
public onScrollRequest(e: viewEvents.ViewScrollRequestEvent): boolean {
|
||||
let currentScrollTop = this.layoutProvider.getScrollTop();
|
||||
let newScrollTop = currentScrollTop + e.deltaLines * this._context.configuration.editor.lineHeight;
|
||||
this.layoutProvider.setScrollPosition({
|
||||
scrollTop: newScrollTop
|
||||
scrollTop: e.desiredScrollTop
|
||||
});
|
||||
return e.revealCursor ? this.revealCursor() : false;
|
||||
}
|
||||
public onScrollRequest2(e: viewEvents.ViewScrollRequestEvent2): boolean {
|
||||
this.layoutProvider.setScrollPosition({
|
||||
scrollTop: e.request.desiredScrollTop
|
||||
});
|
||||
return false;
|
||||
}
|
||||
private revealCursor(): boolean {
|
||||
this.triggerCursorHandler('revealCursor', editorCommon.Handler.CursorMove, { to: CursorMovePosition.ViewPortIfOutside });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,9 +175,6 @@ export class EditorScrollbar extends ViewPart {
|
|||
public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {
|
||||
return true;
|
||||
}
|
||||
public onScrollRequest(e: viewEvents.ViewScrollRequestEvent): boolean {
|
||||
return false;
|
||||
}
|
||||
public onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -778,6 +778,9 @@ export abstract class CommonCodeEditor extends Disposable implements editorCommo
|
|||
let viewModelHelper: IViewModelHelper = {
|
||||
viewModel: this.viewModel,
|
||||
coordinatesConverter: this.viewModel.coordinatesConverter,
|
||||
getScrollTop: (): number => {
|
||||
return this.getScrollTop();
|
||||
},
|
||||
getCompletelyVisibleViewRange: (): Range => {
|
||||
return this._getCompletelyVisibleViewRange();
|
||||
},
|
||||
|
|
|
@ -25,7 +25,7 @@ import { ColumnSelection, IColumnSelectResult } from 'vs/editor/common/controlle
|
|||
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
|
||||
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
|
||||
import { TextModelEventType, ModelRawContentChangedEvent, RawContentChangedType } from 'vs/editor/common/model/textModelEvents';
|
||||
import { CursorEventType, CursorChangeReason, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent, ICursorRevealRangeEvent, ICursorScrollRequestEvent, CursorScrollTopRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { CursorEventType, CursorChangeReason, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent, ICursorRevealRangeEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { ICommandHandlerDescription } from "vs/platform/commands/common/commands";
|
||||
import * as types from 'vs/base/common/types';
|
||||
|
||||
|
@ -1610,6 +1610,25 @@ export class Cursor extends Disposable {
|
|||
|
||||
private _doEditorScroll(args: EditorScroll.ParsedArguments, ctx: IMultipleCursorOperationContext): boolean {
|
||||
|
||||
const desiredScrollTop = this._computeDesiredScrollTop(args);
|
||||
|
||||
if (args.revealCursor) {
|
||||
// must ensure cursor is in new visible range
|
||||
const desiredVisibleViewRange = this.context.getCompletelyVisibleViewRangeAtScrollTop(desiredScrollTop);
|
||||
const r = OneCursorOp.findPositionInViewportIfOutside(this.context, this.cursors.getPrimaryCursor(), desiredVisibleViewRange, false);
|
||||
this.cursors.setStates([r], false);
|
||||
}
|
||||
|
||||
this._eventEmitter.emit(CursorEventType.CursorScrollRequest, new CursorScrollRequest(
|
||||
desiredScrollTop
|
||||
));
|
||||
|
||||
ctx.shouldReveal = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private _computeDesiredScrollTop(args: EditorScroll.ParsedArguments): number {
|
||||
|
||||
if (args.unit === EditorScroll.Unit.Line) {
|
||||
// scrolling by model lines
|
||||
const visibleModelRange = this.context.getCompletelyVisibleModelRange();
|
||||
|
@ -1624,43 +1643,19 @@ export class Cursor extends Disposable {
|
|||
}
|
||||
|
||||
const desiredTopViewPosition = this.context.convertModelPositionToViewPosition(new Position(desiredTopModelLineNumber, 1));
|
||||
const desiredScrollTop = this.context.getVerticalOffsetForViewLine(desiredTopViewPosition.lineNumber);
|
||||
|
||||
if (args.revealCursor) {
|
||||
// must ensure cursor is in new visible range
|
||||
const desiredVisibleViewRange = this.context.getCompletelyVisibleViewRangeAtScrollTop(desiredScrollTop);
|
||||
const r = OneCursorOp.findPositionInViewportIfOutside(this.context, this.cursors.getPrimaryCursor(), desiredVisibleViewRange, false);
|
||||
this.cursors.setStates([r], false);
|
||||
}
|
||||
|
||||
this._eventEmitter.emit(CursorEventType.CursorScrollRequest2, new CursorScrollTopRequest(
|
||||
desiredScrollTop
|
||||
));
|
||||
|
||||
ctx.shouldReveal = false;
|
||||
return true;
|
||||
return this.context.getVerticalOffsetForViewLine(desiredTopViewPosition.lineNumber);
|
||||
}
|
||||
|
||||
let up = args.direction === EditorScroll.Direction.Up;
|
||||
let noOfLines = args.value;
|
||||
switch (args.unit) {
|
||||
case EditorScroll.Unit.Page:
|
||||
noOfLines = this.context.config.pageSize * noOfLines;
|
||||
break;
|
||||
case EditorScroll.Unit.HalfPage:
|
||||
noOfLines = Math.round(this.context.config.pageSize / 2) * noOfLines;
|
||||
break;
|
||||
let noOfLines: number;
|
||||
if (args.unit === EditorScroll.Unit.Page) {
|
||||
noOfLines = this.context.config.pageSize * args.value;
|
||||
} else if (args.unit === EditorScroll.Unit.HalfPage) {
|
||||
noOfLines = Math.round(this.context.config.pageSize / 2) * args.value;
|
||||
} else {
|
||||
noOfLines = args.value;
|
||||
}
|
||||
this.emitCursorScrollRequest((up ? -1 : 1) * noOfLines, args.revealCursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
private emitCursorScrollRequest(deltaLines: number, revealCursor: boolean): void {
|
||||
var e: ICursorScrollRequestEvent = {
|
||||
deltaLines,
|
||||
revealCursor
|
||||
};
|
||||
this._eventEmitter.emit(CursorEventType.CursorScrollRequest, e);
|
||||
const deltaLines = (args.direction === EditorScroll.Direction.Up ? -1 : 1) * noOfLines;
|
||||
return this.context.getScrollTop() + deltaLines * this.context.config.lineHeight;
|
||||
}
|
||||
|
||||
private _undo(ctx: IMultipleCursorOperationContext): boolean {
|
||||
|
|
|
@ -28,6 +28,7 @@ export class CursorConfiguration {
|
|||
public readonly insertSpaces: boolean;
|
||||
public readonly oneIndent: string;
|
||||
public readonly pageSize: number;
|
||||
public readonly lineHeight: number;
|
||||
public readonly useTabStops: boolean;
|
||||
public readonly wordSeparators: string;
|
||||
public readonly autoClosingBrackets: boolean;
|
||||
|
@ -42,6 +43,7 @@ export class CursorConfiguration {
|
|||
|| e.wordSeparators
|
||||
|| e.autoClosingBrackets
|
||||
|| e.useTabStops
|
||||
|| e.lineHeight
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -57,6 +59,7 @@ export class CursorConfiguration {
|
|||
this.insertSpaces = modelOptions.insertSpaces;
|
||||
this.oneIndent = oneIndent;
|
||||
this.pageSize = Math.floor(c.layoutInfo.height / c.fontInfo.lineHeight) - 2;
|
||||
this.lineHeight = c.lineHeight;
|
||||
this.useTabStops = c.useTabStops;
|
||||
this.wordSeparators = c.wordSeparators;
|
||||
this.autoClosingBrackets = c.autoClosingBrackets;
|
||||
|
|
|
@ -17,7 +17,6 @@ export const CursorEventType = {
|
|||
CursorSelectionChanged: 'selectionChanged',
|
||||
CursorRevealRange: 'revealRange',
|
||||
CursorScrollRequest: 'scrollRequest',
|
||||
CursorScrollRequest2: 'scrollRequest2',
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -150,23 +149,7 @@ export interface ICursorRevealRangeEvent {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface ICursorScrollRequestEvent {
|
||||
readonly deltaLines: number;
|
||||
readonly revealCursor: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const enum CursorScrollRequestType {
|
||||
Absolute = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class CursorScrollTopRequest {
|
||||
public readonly type = CursorScrollRequestType.Absolute;
|
||||
export class CursorScrollRequest {
|
||||
|
||||
public readonly desiredScrollTop: number;
|
||||
|
||||
|
@ -174,8 +157,3 @@ export class CursorScrollTopRequest {
|
|||
this.desiredScrollTop = desiredScrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type CursorScrollRequest = CursorScrollTopRequest;
|
||||
|
|
|
@ -178,6 +178,8 @@ export interface IViewModelHelper {
|
|||
|
||||
viewModel: ICursorSimpleModel;
|
||||
|
||||
getScrollTop(): number;
|
||||
|
||||
getCompletelyVisibleViewRange(): Range;
|
||||
|
||||
getCompletelyVisibleViewRangeAtScrollTop(scrollTop: number): Range;
|
||||
|
@ -231,6 +233,10 @@ export class CursorContext {
|
|||
return this._coordinatesConverter.convertModelRangeToViewRange(modelRange);
|
||||
}
|
||||
|
||||
public getScrollTop(): number {
|
||||
return this._viewModelHelper.getScrollTop();
|
||||
}
|
||||
|
||||
public getCompletelyVisibleViewRange(): Range {
|
||||
return this._viewModelHelper.getCompletelyVisibleViewRange();
|
||||
}
|
||||
|
@ -252,43 +258,6 @@ export class CursorContext {
|
|||
public getVerticalOffsetForViewLine(viewLineNumber: number): number {
|
||||
return this._viewModelHelper.getVerticalOffsetForViewLineNumber(viewLineNumber);
|
||||
}
|
||||
|
||||
public getRangeToRevealModelLinesBeforeViewPortTop(noOfLinesBeforeTop: number): Range {
|
||||
let visibleModelRange = this.getCompletelyVisibleModelRange();
|
||||
|
||||
let startLineNumber: number;
|
||||
if (this.model.getLineMinColumn(visibleModelRange.startLineNumber) !== visibleModelRange.startColumn) {
|
||||
// Start line is partially visible by wrapping so reveal start line
|
||||
startLineNumber = visibleModelRange.startLineNumber;
|
||||
} else {
|
||||
// Reveal previous line
|
||||
startLineNumber = visibleModelRange.startLineNumber - 1;
|
||||
}
|
||||
|
||||
startLineNumber -= (noOfLinesBeforeTop - 1);
|
||||
startLineNumber = this.model.validateRange({ startLineNumber, startColumn: 1, endLineNumber: startLineNumber, endColumn: 1 }).startLineNumber;
|
||||
let startColumn = this.model.getLineMinColumn(startLineNumber);
|
||||
let endColumn = this.model.getLineMaxColumn(visibleModelRange.startLineNumber);
|
||||
|
||||
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
|
||||
}
|
||||
|
||||
public getRangeToRevealModelLinesAfterViewPortBottom(noOfLinesAfterBottom: number): Range {
|
||||
let visibleModelRange = this.getCompletelyVisibleModelRange();
|
||||
|
||||
// Last line in the view port is not considered revealed because scroll bar would cover it
|
||||
// Hence consider last line to reveal in the range
|
||||
let startLineNumber = visibleModelRange.endLineNumber + (noOfLinesAfterBottom - 1);
|
||||
startLineNumber = this.model.validateRange({ startLineNumber, startColumn: 1, endLineNumber: startLineNumber, endColumn: 1 }).startLineNumber;
|
||||
let startColumn = this.model.getLineMinColumn(startLineNumber);
|
||||
let endColumn = this.model.getLineMaxColumn(startLineNumber);
|
||||
|
||||
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
|
||||
}
|
||||
|
||||
public isLastLineVisibleInViewPort(): boolean {
|
||||
return this.viewModel.getLineCount() <= this.getCompletelyVisibleViewRange().getEndPosition().lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOneCursorState {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
|
|||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ScrollEvent } from 'vs/base/common/scrollable';
|
||||
import { IViewConfigurationChangedEvent, IConfigurationChangedEvent } from "vs/editor/common/config/editorOptions";
|
||||
import { VerticalRevealType, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { VerticalRevealType } from "vs/editor/common/controller/cursorEvents";
|
||||
|
||||
export const enum ViewEventType {
|
||||
ViewConfigurationChanged = 1,
|
||||
|
@ -25,10 +25,9 @@ export const enum ViewEventType {
|
|||
ViewRevealRangeRequest = 11,
|
||||
ViewScrollChanged = 12,
|
||||
ViewScrollRequest = 13,
|
||||
ViewScrollRequest2 = 14,
|
||||
ViewTokensChanged = 15,
|
||||
ViewTokensColorsChanged = 16,
|
||||
ViewZonesChanged = 17,
|
||||
ViewTokensChanged = 14,
|
||||
ViewTokensColorsChanged = 15,
|
||||
ViewZonesChanged = 16,
|
||||
}
|
||||
|
||||
export class ViewConfigurationChangedEvent {
|
||||
|
@ -244,23 +243,10 @@ export class ViewScrollRequestEvent {
|
|||
|
||||
public readonly type = ViewEventType.ViewScrollRequest;
|
||||
|
||||
public readonly deltaLines: number;
|
||||
public readonly revealCursor: boolean;
|
||||
public readonly desiredScrollTop: number;
|
||||
|
||||
constructor(deltaLines: number, revealCursor: boolean) {
|
||||
this.deltaLines = deltaLines;
|
||||
this.revealCursor = revealCursor;
|
||||
}
|
||||
}
|
||||
|
||||
export class ViewScrollRequestEvent2 {
|
||||
|
||||
public readonly type = ViewEventType.ViewScrollRequest2;
|
||||
|
||||
public readonly request: CursorScrollRequest;
|
||||
|
||||
constructor(request: CursorScrollRequest) {
|
||||
this.request = request;
|
||||
constructor(desiredScrollTop: number) {
|
||||
this.desiredScrollTop = desiredScrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +302,6 @@ export type ViewEvent = (
|
|||
| ViewRevealRangeRequestEvent
|
||||
| ViewScrollChangedEvent
|
||||
| ViewScrollRequestEvent
|
||||
| ViewScrollRequestEvent2
|
||||
| ViewTokensChangedEvent
|
||||
| ViewTokensColorsChangedEvent
|
||||
| ViewZonesChangedEvent
|
||||
|
|
|
@ -198,8 +198,15 @@ export class LayoutProvider extends Disposable implements IViewLayout {
|
|||
return this._linesLayout.getLinesViewportData(visibleBox.top, visibleBox.top + visibleBox.height);
|
||||
}
|
||||
public getLinesViewportDataAtScrollTop(scrollTop: number): IPartialViewLinesViewportData {
|
||||
const visibleBox = this.getCurrentViewport();
|
||||
return this._linesLayout.getLinesViewportData(scrollTop, scrollTop + visibleBox.height);
|
||||
// do some minimal validations on scrollTop
|
||||
const scrollState = this._scrollable.getState();
|
||||
if (scrollTop + scrollState.height > scrollState.scrollHeight) {
|
||||
scrollTop = scrollState.scrollHeight - scrollState.height;
|
||||
}
|
||||
if (scrollTop < 0) {
|
||||
scrollTop = 0;
|
||||
}
|
||||
return this._linesLayout.getLinesViewportData(scrollTop, scrollTop + scrollState.height);
|
||||
}
|
||||
public getWhitespaceViewportData(): IViewWhitespaceViewportData[] {
|
||||
const visibleBox = this.getCurrentViewport();
|
||||
|
|
|
@ -70,10 +70,7 @@ export class ViewEventHandler extends Disposable {
|
|||
public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {
|
||||
return false;
|
||||
}
|
||||
public onScrollRequest(e: viewEvents.ViewScrollRequestEvent): boolean {
|
||||
return false;
|
||||
}
|
||||
public onScrollRequest2(e: viewEvents.ViewScrollRequestEvent2): boolean {
|
||||
public onScrollRequest(e: viewEvents.ViewScrollRequestEvent): boolean { // TODO@cursor
|
||||
return false;
|
||||
}
|
||||
public onTokensChanged(e: viewEvents.ViewTokensChangedEvent): boolean {
|
||||
|
@ -175,12 +172,6 @@ export class ViewEventHandler extends Disposable {
|
|||
}
|
||||
break;
|
||||
|
||||
case viewEvents.ViewEventType.ViewScrollRequest2:
|
||||
if (this.onScrollRequest2(e)) {
|
||||
shouldRender = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case viewEvents.ViewEventType.ViewTokensChanged:
|
||||
if (this.onTokensChanged(e)) {
|
||||
shouldRender = true;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Position } from 'vs/editor/common/core/position';
|
|||
import { ICoordinatesConverter, ViewEventsCollector } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { ICursorRevealRangeEvent, ICursorScrollRequestEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { ICursorRevealRangeEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
|
||||
export interface ICursorPositionChangedEvent {
|
||||
readonly position: Position;
|
||||
|
@ -111,11 +111,7 @@ export class ViewModelCursors {
|
|||
}
|
||||
}
|
||||
|
||||
public onCursorScrollRequest(eventsCollector: ViewEventsCollector, e: ICursorScrollRequestEvent): void {
|
||||
eventsCollector.emit(new viewEvents.ViewScrollRequestEvent(e.deltaLines, e.revealCursor));
|
||||
}
|
||||
|
||||
public onCursorScrollRequest2(eventsCollector: ViewEventsCollector, e: CursorScrollRequest): void {
|
||||
eventsCollector.emit(new viewEvents.ViewScrollRequestEvent2(e));
|
||||
public onCursorScrollRequest(eventsCollector: ViewEventsCollector, e: CursorScrollRequest): void {
|
||||
eventsCollector.emit(new viewEvents.ViewScrollRequestEvent(e.desiredScrollTop));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import * as errors from 'vs/base/common/errors';
|
|||
import { MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer';
|
||||
import * as textModelEvents from 'vs/editor/common/model/textModelEvents';
|
||||
import { WrappingIndent, IConfigurationChangedEvent } from "vs/editor/common/config/editorOptions";
|
||||
import { CursorEventType, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent, ICursorRevealRangeEvent, ICursorScrollRequestEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { CursorEventType, ICursorPositionChangedEvent, VerticalRevealType, ICursorSelectionChangedEvent, ICursorRevealRangeEvent, CursorScrollRequest } from "vs/editor/common/controller/cursorEvents";
|
||||
import { Cursor } from "vs/editor/common/controller/cursor";
|
||||
|
||||
const ConfigurationChanged = 'configurationChanged';
|
||||
|
@ -398,13 +398,8 @@ export class ViewModel extends Disposable implements IViewModel {
|
|||
break;
|
||||
}
|
||||
case CursorEventType.CursorScrollRequest: {
|
||||
const e = <ICursorScrollRequestEvent>data;
|
||||
this.cursors.onCursorScrollRequest(eventsCollector, e);
|
||||
break;
|
||||
}
|
||||
case CursorEventType.CursorScrollRequest2: {
|
||||
const e = <CursorScrollRequest>data;
|
||||
this.cursors.onCursorScrollRequest2(eventsCollector, e);
|
||||
this.cursors.onCursorScrollRequest(eventsCollector, e);
|
||||
break;
|
||||
}
|
||||
case ConfigurationChanged: {
|
||||
|
|
|
@ -51,6 +51,8 @@ export function viewModelHelper(model: IModel): IViewModelHelper {
|
|||
},
|
||||
},
|
||||
|
||||
getScrollTop: (): number => 0,
|
||||
|
||||
getCompletelyVisibleViewRange: () => null,
|
||||
|
||||
getCompletelyVisibleViewRangeAtScrollTop: (scrollTop: number) => null,
|
||||
|
|
Loading…
Reference in a new issue