提交 955bfdda 编写于 作者: S Sandeep Somavarapu

#9609 Reveal cursor while scrolling

上级 ad8520b4
......@@ -253,7 +253,8 @@ export class KeyboardHandler extends ViewEventHandler implements IDisposable {
let revealPositionEvent:editorCommon.IViewRevealRangeEvent = {
range: new Range(lineNumber, column, lineNumber, column),
verticalType: editorCommon.VerticalRevealType.Simple,
revealHorizontal: true
revealHorizontal: true,
revealCursor: false
};
this._context.privateViewEventBus.emit(editorCommon.ViewEventNames.RevealRangeEvent, revealPositionEvent);
......
......@@ -96,7 +96,7 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
commandService: ICommandService,
configuration:Configuration,
model:IViewModel,
triggerCursorHandler:TriggerCursorHandler
private triggerCursorHandler:TriggerCursorHandler
) {
super();
this._isDisposed = false;
......@@ -480,6 +480,19 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
}
return false;
}
public onCursorRevealRange(e: editorCommon.IViewRevealRangeEvent): boolean {
return e.revealCursor ? this.revealCursor() : false;
}
public onCursorScrollRequest(e: editorCommon.ICursorScrollRequestEvent): boolean {
return e.revealCursor ? this.revealCursor() : false;
}
private revealCursor(): boolean {
this.triggerCursorHandler('revealCursor', editorCommon.Handler.CursorMove, { to: editorCommon.CursorMovePosition.ViewPortIfOutside });
return false;
}
// --- end event handlers
public dispose(): void {
......
......@@ -346,7 +346,8 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
range: validatedRange,
viewRange: null,
verticalType: verticalType,
revealHorizontal: revealHorizontal
revealHorizontal: revealHorizontal,
revealCursor: false
};
this.cursor.emit(editorCommon.EventType.CursorRevealRange, revealRangeEvent);
}
......@@ -795,7 +796,7 @@ export abstract class CommonCodeEditor extends EventEmitter implements editorCom
getCurrentCompletelyVisibleViewLinesRangeInViewport: () => {
return this.viewModel.convertModelRangeToViewRange(this.getCompletelyVisibleLinesRangeInViewport());
},
getCurrentVisibleModelLinesRangeInViewport: () => {
getCurrentCompletelyVisibleModelLinesRangeInViewport: () => {
return this.getCompletelyVisibleLinesRangeInViewport();
},
convertModelPositionToViewPosition: (lineNumber:number, column:number) => {
......
......@@ -43,7 +43,6 @@ interface IMultipleCursorOperationContext {
executeCommands: editorCommon.ICommand[];
isAutoWhitespaceCommand: boolean[];
postOperationRunnables: IPostOperationRunnable[];
requestScrollDeltaLines: number;
setColumnSelectToLineNumber: number;
setColumnSelectToVisualColumn: number;
}
......@@ -296,7 +295,6 @@ export class Cursor extends EventEmitter {
postOperationRunnables: [],
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: false,
requestScrollDeltaLines: 0,
setColumnSelectToLineNumber: 0,
setColumnSelectToVisualColumn: 0
};
......@@ -328,7 +326,6 @@ export class Cursor extends EventEmitter {
var shouldRevealHorizontal: boolean;
var shouldRevealTarget: RevealTarget;
var isCursorUndo: boolean;
var requestScrollDeltaLines: number;
var hasExecutedCommands = this._createAndInterpretHandlerCtx(eventSource, data, (currentHandlerCtx:IMultipleCursorOperationContext) => {
handled = handler(currentHandlerCtx);
......@@ -339,7 +336,6 @@ export class Cursor extends EventEmitter {
shouldRevealVerticalInCenter = currentHandlerCtx.shouldRevealVerticalInCenter;
shouldRevealHorizontal = currentHandlerCtx.shouldRevealHorizontal;
isCursorUndo = currentHandlerCtx.isCursorUndo;
requestScrollDeltaLines = currentHandlerCtx.requestScrollDeltaLines;
});
if (hasExecutedCommands) {
......@@ -397,9 +393,6 @@ export class Cursor extends EventEmitter {
this.emitCursorSelectionChanged(eventSource, cursorPositionChangeReason);
}
if (requestScrollDeltaLines) {
this.emitCursorScrollRequest(requestScrollDeltaLines);
}
} catch (err) {
onUnexpectedError(err);
}
......@@ -857,9 +850,10 @@ export class Cursor extends EventEmitter {
this.emit(editorCommon.EventType.CursorSelectionChanged, e);
}
private emitCursorScrollRequest(lineScrollOffset: number): void {
private emitCursorScrollRequest(deltaLines: number, revealCursor: boolean): void {
var e:editorCommon.ICursorScrollRequestEvent = {
deltaLines: lineScrollOffset
deltaLines,
revealCursor
};
this.emit(editorCommon.EventType.CursorScrollRequest, e);
}
......@@ -894,15 +888,16 @@ export class Cursor extends EventEmitter {
var range = new Range(position.lineNumber, position.column, position.lineNumber, position.column);
var viewRange = new Range(viewPosition.lineNumber, viewPosition.column, viewPosition.lineNumber, viewPosition.column);
this.emitCursorRevealRange(range, viewRange, verticalType, revealHorizontal);
this.emitCursorRevealRange(range, viewRange, verticalType, revealHorizontal, false);
}
private emitCursorRevealRange(range: Range, viewRange: Range, verticalType: editorCommon.VerticalRevealType, revealHorizontal: boolean) {
private emitCursorRevealRange(range: Range, viewRange: Range, verticalType: editorCommon.VerticalRevealType, revealHorizontal: boolean, revealCursor: boolean) {
var e:editorCommon.ICursorRevealRangeEvent = {
range: range,
viewRange: viewRange,
verticalType: verticalType,
revealHorizontal: revealHorizontal
revealHorizontal: revealHorizontal,
revealCursor: revealCursor
};
this.emit(editorCommon.EventType.CursorRevealRange, e);
}
......@@ -1075,8 +1070,7 @@ export class Cursor extends EventEmitter {
isAutoWhitespaceCommand: false,
postOperationRunnable: null,
shouldPushStackElementBefore: false,
shouldPushStackElementAfter: false,
requestScrollDeltaLines: 0
shouldPushStackElementAfter: false
};
result = callable(i, cursors[i], context) || result;
......@@ -1086,7 +1080,6 @@ export class Cursor extends EventEmitter {
ctx.shouldRevealHorizontal = context.shouldRevealHorizontal;
ctx.shouldReveal = context.shouldReveal;
ctx.shouldRevealVerticalInCenter = context.shouldRevealVerticalInCenter;
ctx.requestScrollDeltaLines = context.requestScrollDeltaLines;
}
ctx.shouldPushStackElementBefore = ctx.shouldPushStackElementBefore || context.shouldPushStackElementBefore;
......@@ -1487,7 +1480,7 @@ export class Cursor extends EventEmitter {
}
}
this.emitCursorRevealRange(range, null, revealAt, false);
this.emitCursorRevealRange(range, null, revealAt, false, false);
return true;
}
......@@ -1508,7 +1501,7 @@ export class Cursor extends EventEmitter {
if (editorCommon.EditorScrollByUnit.Line === editorScrollArg.by) {
let range = up ? cursor.getRangeToRevealModelLinesBeforeViewPortTop(editorScrollArg.value) : cursor.getRangeToRevealModelLinesAfterViewPortBottom(editorScrollArg.value);
this.emitCursorRevealRange(range, null, up ? editorCommon.VerticalRevealType.Top : editorCommon.VerticalRevealType.Bottom, false);
this.emitCursorRevealRange(range, null, up ? editorCommon.VerticalRevealType.Top : editorCommon.VerticalRevealType.Bottom, false, true);
return true;
}
......@@ -1524,7 +1517,7 @@ export class Cursor extends EventEmitter {
noOfLines = Math.round(cursor.getPageSize() / 2) * editorScrollArg.value;
break;
}
ctx.requestScrollDeltaLines = (up ? -1 : 1) * noOfLines;
this.emitCursorScrollRequest((up ? -1 : 1) * noOfLines, !!editorScrollArg.revealCursor);
return true;
}
......
......@@ -31,7 +31,6 @@ export interface IOneCursorOperationContext {
executeCommand: editorCommon.ICommand;
isAutoWhitespaceCommand: boolean;
postOperationRunnable: IPostOperationRunnable;
requestScrollDeltaLines: number;
}
export interface IModeConfiguration {
......@@ -63,7 +62,7 @@ export interface IViewModelHelper {
viewModel:ICursorMoveHelperModel;
getCurrentCompletelyVisibleViewLinesRangeInViewport(): Range;
getCurrentVisibleModelLinesRangeInViewport(): Range;
getCurrentCompletelyVisibleModelLinesRangeInViewport(): Range;
convertModelPositionToViewPosition(lineNumber:number, column:number): Position;
convertModelRangeToViewRange(modelRange:Range): Range;
......@@ -519,7 +518,7 @@ export class OneCursor {
// -- model
public getRangeToRevealModelLinesBeforeViewPortTop(noOfLinesBeforeTop: number): Range {
let visibleModelRange = this.viewModelHelper.getCurrentVisibleModelLinesRangeInViewport();
let visibleModelRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let startLineNumber: number;
if (this.model.getLineMinColumn(visibleModelRange.startLineNumber) !== visibleModelRange.startColumn) {
......@@ -538,7 +537,7 @@ export class OneCursor {
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
}
public getRangeToRevealModelLinesAfterViewPortBottom(noOfLinesAfterBottom: number): Range {
let visibleModelRange = this.viewModelHelper.getCurrentVisibleModelLinesRangeInViewport();
let visibleModelRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
// 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
......@@ -550,7 +549,7 @@ export class OneCursor {
return new Range(startLineNumber, startColumn, startLineNumber, endColumn);
}
public getLineFromViewPortTop(lineFromTop: number = 1): number {
let visibleRange = this.viewModelHelper.getCurrentVisibleModelLinesRangeInViewport();
let visibleRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let startColumn = this.model.getLineMinColumn(visibleRange.startLineNumber);
// Use next line if the first line is partially visible
let visibleLineNumber = visibleRange.startColumn === startColumn ? visibleRange.startLineNumber : visibleRange.startLineNumber + 1;
......@@ -561,7 +560,7 @@ export class OneCursor {
return Math.round((this.getLineFromViewPortTop() + this.getLineFromViewPortBottom() - 1) / 2);
}
public getLineFromViewPortBottom(lineFromBottom: number = 1): number {
let visibleRange = this.viewModelHelper.getCurrentVisibleModelLinesRangeInViewport();
let visibleRange = this.viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport();
let visibleLineNumber = visibleRange.endLineNumber - (lineFromBottom - 1);
return visibleLineNumber > visibleRange.startLineNumber ? visibleLineNumber : this.getLineFromViewPortTop();
}
......@@ -600,6 +599,17 @@ export class OneCursor {
}
// -- view
public getCompletelyVisibleViewLinesRangeInViewport(): Range {
return this.viewModelHelper.getCurrentCompletelyVisibleViewLinesRangeInViewport();
}
public getRevealViewLinesRangeInViewport(): Range {
let visibleRange = this.getCompletelyVisibleViewLinesRangeInViewport().cloneRange();
if (visibleRange.endLineNumber > visibleRange.startLineNumber) {
visibleRange.endLineNumber = visibleRange.endLineNumber - 1;
visibleRange.endColumn = this.viewModelHelper.viewModel.getLineLastNonWhitespaceColumn(visibleRange.endLineNumber);
}
return visibleRange;
}
public getViewLineCount(): number {
return this.viewModelHelper.viewModel.getLineCount();
}
......@@ -652,6 +662,20 @@ export class OneCursor {
toVisualColumn: toViewVisibleColumn
};
}
public getNearestRevealViewPositionInViewport(): Position {
const position = this.getViewPosition();
const revealRange = this.getRevealViewLinesRangeInViewport();
if (position.lineNumber < revealRange.startLineNumber) {
return new Position(revealRange.startLineNumber, this.viewModelHelper.viewModel.getLineFirstNonWhitespaceColumn(revealRange.startLineNumber));
}
if (position.lineNumber > revealRange.endLineNumber) {
return new Position(revealRange.endLineNumber, this.viewModelHelper.viewModel.getLineFirstNonWhitespaceColumn(revealRange.endLineNumber));
}
return position;
}
// -------------------- END reading API
}
......@@ -748,6 +772,11 @@ export class OneCursorOp {
viewLineNumber= cursor.convertModelPositionToViewPosition(cursor.getCenterLineInViewPort(), 1).lineNumber;;
viewColumn = cursor.getViewLineFirstNonWhiteSpaceColumn(viewLineNumber);
break;
case editorCommon.CursorMovePosition.ViewPortIfOutside:
const position = cursor.getNearestRevealViewPositionInViewport();
viewLineNumber= position.lineNumber;
viewColumn = position.column;
break;
default:
return false;
}
......
......@@ -2622,7 +2622,11 @@ export interface ICursorRevealRangeEvent {
* If true: there should be a horizontal & vertical revealing
* If false: there should be just a vertical revealing
*/
revealHorizontal:boolean;
revealHorizontal: boolean;
/**
* If true: cursor is revealed if outside viewport
*/
revealCursor: boolean;
}
/**
......@@ -2630,6 +2634,7 @@ export interface ICursorRevealRangeEvent {
*/
export interface ICursorScrollRequestEvent {
deltaLines: number;
revealCursor: boolean;
}
/**
......@@ -3397,6 +3402,10 @@ export interface IViewRevealRangeEvent {
* If false: there should be just a vertical revealing
*/
revealHorizontal: boolean;
/**
* If true: cursor is revealed if outside viewport
*/
revealCursor: boolean;
}
/**
......@@ -3404,6 +3413,7 @@ export interface IViewRevealRangeEvent {
*/
export interface IViewScrollRequestEvent {
deltaLines: number;
revealCursor: boolean;
}
/**
......@@ -4236,6 +4246,8 @@ export const CursorMovePosition = {
ViewPortTop: 'viewPortTop',
ViewPortCenter: 'viewPortCenter',
ViewPortBottom: 'viewPortBottom',
ViewPortIfOutside: 'viewPortIfOutside'
};
/**
......@@ -4312,6 +4324,7 @@ export interface EditorScrollArguments {
to: string;
by?: string;
value?: number;
revealCursor?: boolean;
};
/**
......@@ -4336,6 +4349,10 @@ const isEditorScrollArgs= function(arg): boolean {
return false;
}
if (!types.isUndefined(scrollArg.revealCursor) && !types.isBoolean(scrollArg.revealCursor)) {
return false;
}
return true;
};
......@@ -4391,7 +4408,7 @@ export var CommandDescription = {
\`\`\`
'left', 'right', 'up', 'down',
'wrappedLineStart', 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineColumnCenter', 'wrappedLineEnd' ,'wrappedLineLastNonWhitespaceCharacter',
'viewPortTop', 'viewPortCenter', 'viewPortBottom'
'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside'
\`\`\`
'by': Unit to move. Default is computed based on 'to' value.
\`\`\`
......@@ -4419,6 +4436,7 @@ export var CommandDescription = {
'line', 'wrappedLine', 'page', 'halfPage'
\`\`\`
'value': Number of units to move. Default is '1'.
'revealCursor': If 'true' reveals the cursor if it is outside view port.
`,
constraint: isEditorScrollArgs
}
......
......@@ -102,14 +102,16 @@ export class ViewModelCursors {
var newEvent:editorCommon.IViewRevealRangeEvent = {
range: viewRange,
verticalType: e.verticalType,
revealHorizontal: e.revealHorizontal
revealHorizontal: e.revealHorizontal,
revealCursor: e.revealCursor
};
emit(editorCommon.ViewEventNames.RevealRangeEvent, newEvent);
}
public onCursorScrollRequest(e:editorCommon.ICursorScrollRequestEvent, emit:(eventType:string, payload:any)=>void): void {
var newEvent:editorCommon.IViewScrollRequestEvent = {
deltaLines: e.deltaLines
deltaLines: e.deltaLines,
revealCursor: e.revealCursor
};
emit(editorCommon.ViewEventNames.ScrollRequestEvent, newEvent);
}
......
......@@ -132,7 +132,8 @@ export class ViewModel extends EventEmitter implements IViewModel {
var restoreRevealEvent:editorCommon.IViewRevealRangeEvent = {
range: newCenteredViewRange,
verticalType: editorCommon.VerticalRevealType.Center,
revealHorizontal: false
revealHorizontal: false,
revealCursor: false
};
this.emit(editorCommon.ViewEventNames.RevealRangeEvent, restoreRevealEvent);
}
......
......@@ -358,7 +358,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to first visible line if it is first line', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(1, 1, 10, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(1, 1, 10, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -369,7 +369,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to top visible line when first line is not visible', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(2, 1, 10, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(2, 1, 10, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -380,7 +380,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to nth line from top', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(1, 1, 10, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(1, 1, 10, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -391,7 +391,7 @@ suite('Cursor move command test', () => {
test('move to view top line moves to last line if n is greater than last visible line number', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(1, 1, 3, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(1, 1, 3, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -402,7 +402,7 @@ suite('Cursor move command test', () => {
test('move to view center line moves to the center line', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(3, 1, 3, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(3, 1, 3, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -413,7 +413,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to last visible line if it is last line', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(1, 1, 5, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(1, 1, 5, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -424,7 +424,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to last visible line when last line is not visible', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(2, 1, 3, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(2, 1, 3, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 2, 2);
......@@ -435,7 +435,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to nth line from bottom', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(1, 1, 5, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(1, 1, 5, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......@@ -446,7 +446,7 @@ suite('Cursor move command test', () => {
test('move to view bottom line moves to first line if n is lesser than first visible line number', () => {
let viewModelHelper= aViewModelHelper(thisModel);
viewModelHelper.getCurrentVisibleModelLinesRangeInViewport= () => new Range(2, 1, 5, 1);
viewModelHelper.getCurrentCompletelyVisibleModelLinesRangeInViewport= () => new Range(2, 1, 5, 1);
thisCursor= aCursor(viewModelHelper);
moveTo(thisCursor, 4, 1);
......
......@@ -20,7 +20,7 @@ export function viewModelHelper(model): IViewModelHelper{
return {
viewModel: model,
getCurrentCompletelyVisibleViewLinesRangeInViewport: () => { return null; },
getCurrentVisibleModelLinesRangeInViewport: () => { return null; },
getCurrentCompletelyVisibleModelLinesRangeInViewport: () => { return null; },
convertModelPositionToViewPosition: (lineNumber: number, column: number) => {
return new Position(lineNumber, column);
},
......
......@@ -3168,6 +3168,7 @@ declare module monaco.editor {
ViewPortTop: string;
ViewPortCenter: string;
ViewPortBottom: string;
ViewPortIfOutside: string;
};
/**
......@@ -3215,6 +3216,7 @@ declare module monaco.editor {
to: string;
by?: string;
value?: number;
revealCursor?: boolean;
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册