mirror of
https://github.com/Microsoft/vscode
synced 2024-09-19 18:48:00 +00:00
Work in progress
This commit is contained in:
parent
22c1836f97
commit
930de5510d
|
@ -16,21 +16,23 @@ import { IModelTokensChangedEvent } from 'vs/editor/common/textModelEvents';
|
|||
export class StickyScrollController extends Disposable implements IEditorContribution {
|
||||
|
||||
static readonly ID = 'store.contrib.stickyScrollController';
|
||||
private readonly editor: ICodeEditor;
|
||||
private readonly stickyScrollWidget: StickyScrollWidget;
|
||||
private readonly stickyLineCandidateProvider: StickyLineCandidateProvider;
|
||||
private readonly sessionStore: DisposableStore = new DisposableStore();
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly _stickyScrollWidget: StickyScrollWidget;
|
||||
private readonly _stickyLineCandidateProvider: StickyLineCandidateProvider;
|
||||
private readonly _sessionStore: DisposableStore = new DisposableStore();
|
||||
private _widgetState: StickyScrollWidgetState;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@ILanguageFeaturesService _languageFeaturesService: ILanguageFeaturesService,
|
||||
@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
|
||||
) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.stickyScrollWidget = new StickyScrollWidget(this.editor);
|
||||
this.stickyLineCandidateProvider = new StickyLineCandidateProvider(this.editor, _languageFeaturesService);
|
||||
this._editor = editor;
|
||||
this._stickyScrollWidget = new StickyScrollWidget(this._editor);
|
||||
this._stickyLineCandidateProvider = new StickyLineCandidateProvider(this._editor, languageFeaturesService);
|
||||
this._widgetState = new StickyScrollWidgetState([], 0);
|
||||
|
||||
this._register(this.editor.onDidChangeConfiguration(e => {
|
||||
this._register(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.experimental)) {
|
||||
this.readConfiguration();
|
||||
}
|
||||
|
@ -38,27 +40,35 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
|||
this.readConfiguration();
|
||||
}
|
||||
|
||||
public get stickyScrollCandidateProvider() {
|
||||
return this._stickyLineCandidateProvider;
|
||||
}
|
||||
|
||||
public get stickyScrollWidgetState() {
|
||||
return this._widgetState;
|
||||
}
|
||||
|
||||
private readConfiguration() {
|
||||
const options = this.editor.getOption(EditorOption.experimental);
|
||||
const options = this._editor.getOption(EditorOption.experimental);
|
||||
if (options.stickyScroll.enabled === false) {
|
||||
this.editor.removeOverlayWidget(this.stickyScrollWidget);
|
||||
this.sessionStore.clear();
|
||||
this._editor.removeOverlayWidget(this._stickyScrollWidget);
|
||||
this._sessionStore.clear();
|
||||
return;
|
||||
} else {
|
||||
this.editor.addOverlayWidget(this.stickyScrollWidget);
|
||||
this.sessionStore.add(this.editor.onDidScrollChange(() => this.renderStickyScroll()));
|
||||
this.sessionStore.add(this.editor.onDidLayoutChange(() => this.onDidResize()));
|
||||
this.sessionStore.add(this.editor.onDidChangeModelTokens((e) => this.onTokensChange(e)));
|
||||
this.sessionStore.add(this.stickyLineCandidateProvider.onStickyScrollChange(() => this.renderStickyScroll()));
|
||||
const lineNumberOption = this.editor.getOption(EditorOption.lineNumbers);
|
||||
this._editor.addOverlayWidget(this._stickyScrollWidget);
|
||||
this._sessionStore.add(this._editor.onDidScrollChange(() => this.renderStickyScroll()));
|
||||
this._sessionStore.add(this._editor.onDidLayoutChange(() => this.onDidResize()));
|
||||
this._sessionStore.add(this._editor.onDidChangeModelTokens((e) => this.onTokensChange(e)));
|
||||
this._sessionStore.add(this._stickyLineCandidateProvider.onStickyScrollChange(() => this.renderStickyScroll()));
|
||||
const lineNumberOption = this._editor.getOption(EditorOption.lineNumbers);
|
||||
if (lineNumberOption.renderType === RenderLineNumbersType.Relative) {
|
||||
this.sessionStore.add(this.editor.onDidChangeCursorPosition(() => this.renderStickyScroll()));
|
||||
this._sessionStore.add(this._editor.onDidChangeCursorPosition(() => this.renderStickyScroll()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private needsUpdate(event: IModelTokensChangedEvent) {
|
||||
const stickyLineNumbers = this.stickyScrollWidget.getCurrentLines();
|
||||
const stickyLineNumbers = this._stickyScrollWidget.getCurrentLines();
|
||||
for (const stickyLineNumber of stickyLineNumbers) {
|
||||
for (const range of event.ranges) {
|
||||
if (stickyLineNumber >= range.fromLineNumber && stickyLineNumber <= range.toLineNumber) {
|
||||
|
@ -76,31 +86,32 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
|||
}
|
||||
|
||||
private onDidResize() {
|
||||
const width = this.editor.getLayoutInfo().width - this.editor.getLayoutInfo().minimap.minimapCanvasOuterWidth - this.editor.getLayoutInfo().verticalScrollbarWidth;
|
||||
this.stickyScrollWidget.getDomNode().style.width = `${width}px`;
|
||||
const width = this._editor.getLayoutInfo().width - this._editor.getLayoutInfo().minimap.minimapCanvasOuterWidth - this._editor.getLayoutInfo().verticalScrollbarWidth;
|
||||
this._stickyScrollWidget.getDomNode().style.width = `${width}px`;
|
||||
}
|
||||
|
||||
private renderStickyScroll() {
|
||||
if (!(this.editor.hasModel())) {
|
||||
if (!(this._editor.hasModel())) {
|
||||
return;
|
||||
}
|
||||
const model = this.editor.getModel();
|
||||
if (this.stickyLineCandidateProvider.getVersionId() !== model.getVersionId()) {
|
||||
const model = this._editor.getModel();
|
||||
if (this._stickyLineCandidateProvider.getVersionId() !== model.getVersionId()) {
|
||||
// Old _ranges not updated yet
|
||||
return;
|
||||
}
|
||||
this.stickyScrollWidget.setState(this.getScrollWidgetState());
|
||||
this._widgetState = this.getScrollWidgetState();
|
||||
this._stickyScrollWidget.setState(this._widgetState);
|
||||
}
|
||||
|
||||
private getScrollWidgetState(): StickyScrollWidgetState {
|
||||
const lineHeight: number = this.editor.getOption(EditorOption.lineHeight);
|
||||
const scrollTop: number = this.editor.getScrollTop();
|
||||
public getScrollWidgetState(): StickyScrollWidgetState {
|
||||
const lineHeight: number = this._editor.getOption(EditorOption.lineHeight);
|
||||
const scrollTop: number = this._editor.getScrollTop();
|
||||
let lastLineRelativePosition: number = 0;
|
||||
const lineNumbers: number[] = [];
|
||||
const arrayVisibleRanges = this.editor.getVisibleRanges();
|
||||
const arrayVisibleRanges = this._editor.getVisibleRanges();
|
||||
if (arrayVisibleRanges.length !== 0) {
|
||||
const fullVisibleRange = new StickyRange(arrayVisibleRanges[0].startLineNumber, arrayVisibleRanges[arrayVisibleRanges.length - 1].endLineNumber);
|
||||
const candidateRanges = this.stickyLineCandidateProvider.getCandidateStickyLinesIntersecting(fullVisibleRange);
|
||||
const candidateRanges = this._stickyLineCandidateProvider.getCandidateStickyLinesIntersecting(fullVisibleRange);
|
||||
for (const range of candidateRanges) {
|
||||
const start = range.startLineNumber;
|
||||
const end = range.endLineNumber;
|
||||
|
@ -109,9 +120,9 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
|||
const topOfElementAtDepth = (depth - 1) * lineHeight;
|
||||
const bottomOfElementAtDepth = depth * lineHeight;
|
||||
|
||||
const bottomOfBeginningLine = this.editor.getBottomForLineNumber(start) - scrollTop;
|
||||
const topOfEndLine = this.editor.getTopForLineNumber(end) - scrollTop;
|
||||
const bottomOfEndLine = this.editor.getBottomForLineNumber(end) - scrollTop;
|
||||
const bottomOfBeginningLine = this._editor.getBottomForLineNumber(start) - scrollTop;
|
||||
const topOfEndLine = this._editor.getTopForLineNumber(end) - scrollTop;
|
||||
const bottomOfEndLine = this._editor.getBottomForLineNumber(end) - scrollTop;
|
||||
|
||||
if (topOfElementAtDepth > topOfEndLine && topOfElementAtDepth <= bottomOfEndLine) {
|
||||
lineNumbers.push(start);
|
||||
|
@ -129,7 +140,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
|||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this.sessionStore.dispose();
|
||||
this._sessionStore.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,24 +33,24 @@ export class StickyLineCandidateProvider extends Disposable {
|
|||
public readonly onStickyScrollChange = this.onStickyScrollChangeEmitter.event;
|
||||
|
||||
static readonly ID = 'store.contrib.stickyScrollController';
|
||||
private readonly editor: ICodeEditor;
|
||||
private readonly languageFeaturesService: ILanguageFeaturesService;
|
||||
private readonly updateSoon: RunOnceScheduler;
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly _languageFeaturesService: ILanguageFeaturesService;
|
||||
private readonly _updateSoon: RunOnceScheduler;
|
||||
|
||||
private cts: CancellationTokenSource | undefined;
|
||||
private outlineModel: StickyOutlineElement | undefined;
|
||||
private readonly sessionStore: DisposableStore = new DisposableStore();
|
||||
private modelVersionId: number = 0;
|
||||
private _cts: CancellationTokenSource | undefined;
|
||||
private _outlineModel: StickyOutlineElement | undefined;
|
||||
private readonly _sessionStore: DisposableStore = new DisposableStore();
|
||||
private _modelVersionId: number = 0;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@ILanguageFeaturesService _languageFeaturesService: ILanguageFeaturesService,
|
||||
@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
|
||||
) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.languageFeaturesService = _languageFeaturesService;
|
||||
this.updateSoon = this._register(new RunOnceScheduler(() => this.update(), 50));
|
||||
this._register(this.editor.onDidChangeConfiguration(e => {
|
||||
this._editor = editor;
|
||||
this._languageFeaturesService = languageFeaturesService;
|
||||
this._updateSoon = this._register(new RunOnceScheduler(() => this.update(), 50));
|
||||
this._register(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.experimental)) {
|
||||
this.readConfiguration();
|
||||
}
|
||||
|
@ -59,40 +59,40 @@ export class StickyLineCandidateProvider extends Disposable {
|
|||
}
|
||||
|
||||
private readConfiguration() {
|
||||
const options = this.editor.getOption(EditorOption.experimental);
|
||||
const options = this._editor.getOption(EditorOption.experimental);
|
||||
if (options.stickyScroll.enabled === false) {
|
||||
this.sessionStore.clear();
|
||||
this._sessionStore.clear();
|
||||
return;
|
||||
} else {
|
||||
this.sessionStore.add(this.editor.onDidChangeModel(() => this.update()));
|
||||
this.sessionStore.add(this.editor.onDidChangeHiddenAreas(() => this.update()));
|
||||
this.sessionStore.add(this.editor.onDidChangeModelContent(() => this.updateSoon.schedule()));
|
||||
this.sessionStore.add(this.languageFeaturesService.documentSymbolProvider.onDidChange(() => this.update()));
|
||||
this._sessionStore.add(this._editor.onDidChangeModel(() => this.update()));
|
||||
this._sessionStore.add(this._editor.onDidChangeHiddenAreas(() => this.update()));
|
||||
this._sessionStore.add(this._editor.onDidChangeModelContent(() => this._updateSoon.schedule()));
|
||||
this._sessionStore.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(() => this.update()));
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
public getVersionId() {
|
||||
return this.modelVersionId;
|
||||
return this._modelVersionId;
|
||||
}
|
||||
|
||||
private async update(): Promise<void> {
|
||||
this.cts?.dispose(true);
|
||||
this.cts = new CancellationTokenSource();
|
||||
await this.updateOutlineModel(this.cts.token);
|
||||
public async update(): Promise<void> {
|
||||
this._cts?.dispose(true);
|
||||
this._cts = new CancellationTokenSource();
|
||||
await this.updateOutlineModel(this._cts.token);
|
||||
this.onStickyScrollChangeEmitter.fire();
|
||||
}
|
||||
|
||||
private async updateOutlineModel(token: CancellationToken) {
|
||||
if (this.editor.hasModel()) {
|
||||
const model = this.editor.getModel();
|
||||
if (this._editor.hasModel()) {
|
||||
const model = this._editor.getModel();
|
||||
const modelVersionId = model.getVersionId();
|
||||
const outlineModel = await OutlineModel.create(this.languageFeaturesService.documentSymbolProvider, model, token) as OutlineModel;
|
||||
const outlineModel = await OutlineModel.create(this._languageFeaturesService.documentSymbolProvider, model, token) as OutlineModel;
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
this.outlineModel = StickyOutlineElement.fromOutlineModel(outlineModel);
|
||||
this.modelVersionId = modelVersionId;
|
||||
this._outlineModel = StickyOutlineElement.fromOutlineModel(outlineModel);
|
||||
this._modelVersionId = modelVersionId;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,8 +115,8 @@ export class StickyLineCandidateProvider extends Disposable {
|
|||
|
||||
public getCandidateStickyLinesIntersecting(range: StickyRange): StickyLineCandidate[] {
|
||||
let stickyLineCandidates: StickyLineCandidate[] = [];
|
||||
this.getCandidateStickyLinesIntersectingFromOutline(range, this.outlineModel as StickyOutlineElement, stickyLineCandidates, 0, -1);
|
||||
const hiddenRanges: Range[] | undefined = this.editor._getViewModel()?.getHiddenAreas();
|
||||
this.getCandidateStickyLinesIntersectingFromOutline(range, this._outlineModel as StickyOutlineElement, stickyLineCandidates, 0, -1);
|
||||
const hiddenRanges: Range[] | undefined = this._editor._getViewModel()?.getHiddenAreas();
|
||||
if (hiddenRanges) {
|
||||
for (const hiddenRange of hiddenRanges) {
|
||||
stickyLineCandidates = stickyLineCandidates.filter(stickyLine => !(stickyLine.startLineNumber >= hiddenRange.startLineNumber && stickyLine.endLineNumber <= hiddenRange.endLineNumber + 1));
|
||||
|
@ -127,7 +127,7 @@ export class StickyLineCandidateProvider extends Disposable {
|
|||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this.sessionStore.dispose();
|
||||
this._sessionStore.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,61 +23,65 @@ const _ttPolicy = window.trustedTypes?.createPolicy('stickyScrollViewLayer', { c
|
|||
|
||||
export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
||||
|
||||
private readonly layoutInfo: EditorLayoutInfo;
|
||||
private readonly rootDomNode: HTMLElement = document.createElement('div');
|
||||
private readonly disposableStore = this._register(new DisposableStore());
|
||||
private lineHeight: number;
|
||||
private lineNumbers: number[];
|
||||
private lastLineRelativePosition: number;
|
||||
private readonly _layoutInfo: EditorLayoutInfo;
|
||||
private readonly _rootDomNode: HTMLElement = document.createElement('div');
|
||||
private readonly _disposableStore = this._register(new DisposableStore());
|
||||
private _lineHeight: number;
|
||||
private _lineNumbers: number[];
|
||||
private _lastLineRelativePosition: number;
|
||||
|
||||
constructor(private readonly _editor: ICodeEditor) {
|
||||
constructor(private readonly editor: ICodeEditor) {
|
||||
super();
|
||||
this.layoutInfo = this._editor.getLayoutInfo();
|
||||
this.rootDomNode = document.createElement('div');
|
||||
this.rootDomNode.className = 'sticky-widget';
|
||||
this.rootDomNode.style.width = `${this.layoutInfo.width - this.layoutInfo.minimap.minimapCanvasOuterWidth - this.layoutInfo.verticalScrollbarWidth}px`;
|
||||
this._layoutInfo = this.editor.getLayoutInfo();
|
||||
this._rootDomNode = document.createElement('div');
|
||||
this._rootDomNode.className = 'sticky-widget';
|
||||
this._rootDomNode.style.width = `${this._layoutInfo.width - this._layoutInfo.minimap.minimapCanvasOuterWidth - this._layoutInfo.verticalScrollbarWidth}px`;
|
||||
|
||||
this.lineNumbers = [];
|
||||
this.lastLineRelativePosition = 0;
|
||||
this._lineNumbers = [];
|
||||
this._lastLineRelativePosition = 0;
|
||||
|
||||
this.lineHeight = this._editor.getOption(EditorOption.lineHeight);
|
||||
this._register(this._editor.onDidChangeConfiguration(e => {
|
||||
this._lineHeight = this.editor.getOption(EditorOption.lineHeight);
|
||||
this._register(this.editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.lineHeight)) {
|
||||
this.lineHeight = this._editor.getOption(EditorOption.lineHeight);
|
||||
this._lineHeight = this.editor.getOption(EditorOption.lineHeight);
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
public get lineNumbers(): number[] {
|
||||
return this._lineNumbers;
|
||||
}
|
||||
|
||||
public get codeLineCount(): number {
|
||||
return this.lineNumbers.length;
|
||||
return this._lineNumbers.length;
|
||||
}
|
||||
|
||||
public getCurrentLines(): readonly number[] {
|
||||
return this.lineNumbers;
|
||||
return this._lineNumbers;
|
||||
}
|
||||
|
||||
public setState(state: StickyScrollWidgetState): void {
|
||||
this.disposableStore.clear();
|
||||
this.lineNumbers.length = 0;
|
||||
dom.clearNode(this.rootDomNode);
|
||||
this._disposableStore.clear();
|
||||
this._lineNumbers.length = 0;
|
||||
dom.clearNode(this._rootDomNode);
|
||||
|
||||
this.lastLineRelativePosition = state.lastLineRelativePosition;
|
||||
this.lineNumbers = state.lineNumbers;
|
||||
this._lastLineRelativePosition = state.lastLineRelativePosition;
|
||||
this._lineNumbers = state.lineNumbers;
|
||||
this.renderRootNode();
|
||||
}
|
||||
|
||||
private getChildNode(index: number, line: number): HTMLElement {
|
||||
|
||||
const child = document.createElement('div');
|
||||
const viewModel = this._editor._getViewModel();
|
||||
const viewModel = this.editor._getViewModel();
|
||||
const viewLineNumber = viewModel!.coordinatesConverter.convertModelPositionToViewPosition(new Position(line, 1)).lineNumber;
|
||||
const lineRenderingData = viewModel!.getViewLineRenderingData(viewLineNumber);
|
||||
const layoutInfo = this._editor.getLayoutInfo();
|
||||
const layoutInfo = this.editor.getLayoutInfo();
|
||||
const width = layoutInfo.width - layoutInfo.minimap.minimapCanvasOuterWidth - layoutInfo.verticalScrollbarWidth;
|
||||
const minimapSide = this._editor.getOption(EditorOption.minimap).side;
|
||||
const lineHeight = this._editor.getOption(EditorOption.lineHeight);
|
||||
const lineNumberOption = this._editor.getOption(EditorOption.lineNumbers);
|
||||
const minimapSide = this.editor.getOption(EditorOption.minimap).side;
|
||||
const lineHeight = this.editor.getOption(EditorOption.lineHeight);
|
||||
const lineNumberOption = this.editor.getOption(EditorOption.lineNumbers);
|
||||
|
||||
let actualInlineDecorations: LineDecoration[];
|
||||
try {
|
||||
|
@ -122,7 +126,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
if (lineNumberOption.renderType === RenderLineNumbersType.On || lineNumberOption.renderType === RenderLineNumbersType.Interval && line % 10 === 0) {
|
||||
innerLineNumberHTML.innerText = line.toString();
|
||||
} else if (lineNumberOption.renderType === RenderLineNumbersType.Relative) {
|
||||
innerLineNumberHTML.innerText = Math.abs(line - this._editor.getPosition()!.lineNumber).toString();
|
||||
innerLineNumberHTML.innerText = Math.abs(line - this.editor.getPosition()!.lineNumber).toString();
|
||||
}
|
||||
innerLineNumberHTML.className = 'sticky-line-number';
|
||||
innerLineNumberHTML.style.lineHeight = `${lineHeight}px`;
|
||||
|
@ -134,8 +138,8 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
}
|
||||
lineNumberHTMLNode.appendChild(innerLineNumberHTML);
|
||||
|
||||
this._editor.applyFontInfo(lineHTMLNode);
|
||||
this._editor.applyFontInfo(innerLineNumberHTML);
|
||||
this.editor.applyFontInfo(lineHTMLNode);
|
||||
this.editor.applyFontInfo(innerLineNumberHTML);
|
||||
|
||||
child.appendChild(lineNumberHTMLNode);
|
||||
child.appendChild(lineHTMLNode);
|
||||
|
@ -147,15 +151,15 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
child.style.zIndex = '0';
|
||||
|
||||
// Special case for the last line of sticky scroll
|
||||
if (index === this.lineNumbers.length - 1) {
|
||||
if (index === this._lineNumbers.length - 1) {
|
||||
child.style.position = 'relative';
|
||||
child.style.zIndex = '-1';
|
||||
child.style.top = this.lastLineRelativePosition + 'px';
|
||||
child.style.top = this._lastLineRelativePosition + 'px';
|
||||
}
|
||||
this.disposableStore.add(dom.addDisposableListener(child, 'click', e => {
|
||||
this._disposableStore.add(dom.addDisposableListener(child, 'click', e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this._editor.revealPosition({ lineNumber: line - index, column: 1 });
|
||||
this.editor.revealPosition({ lineNumber: line - index, column: 1 });
|
||||
}));
|
||||
|
||||
return child;
|
||||
|
@ -163,20 +167,20 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
|
||||
private renderRootNode(): void {
|
||||
|
||||
if (!this._editor._getViewModel()) {
|
||||
if (!this.editor._getViewModel()) {
|
||||
return;
|
||||
}
|
||||
for (const [index, line] of this.lineNumbers.entries()) {
|
||||
this.rootDomNode.appendChild(this.getChildNode(index, line));
|
||||
for (const [index, line] of this._lineNumbers.entries()) {
|
||||
this._rootDomNode.appendChild(this.getChildNode(index, line));
|
||||
}
|
||||
|
||||
const widgetHeight: number = this.lineNumbers.length * this.lineHeight + this.lastLineRelativePosition;
|
||||
this.rootDomNode.style.height = widgetHeight.toString() + 'px';
|
||||
const minimapSide = this._editor.getOption(EditorOption.minimap).side;
|
||||
const widgetHeight: number = this._lineNumbers.length * this._lineHeight + this._lastLineRelativePosition;
|
||||
this._rootDomNode.style.height = widgetHeight.toString() + 'px';
|
||||
const minimapSide = this.editor.getOption(EditorOption.minimap).side;
|
||||
if (minimapSide === 'left') {
|
||||
this.rootDomNode.style.marginLeft = this._editor.getLayoutInfo().minimap.minimapCanvasOuterWidth + 'px';
|
||||
this._rootDomNode.style.marginLeft = this.editor.getLayoutInfo().minimap.minimapCanvasOuterWidth + 'px';
|
||||
} else if (minimapSide === 'right') {
|
||||
this.rootDomNode.style.marginLeft = '0px';
|
||||
this._rootDomNode.style.marginLeft = '0px';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +189,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
}
|
||||
|
||||
public getDomNode(): HTMLElement {
|
||||
return this.rootDomNode;
|
||||
return this._rootDomNode;
|
||||
}
|
||||
|
||||
public getPosition(): IOverlayWidgetPosition | null {
|
||||
|
@ -196,6 +200,6 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
|||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this.disposableStore.dispose();
|
||||
this._disposableStore.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,21 +3,233 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { ITestCodeEditor, withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { withAsyncTestCodeEditor, withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { StickyScrollController } from 'vs/editor/contrib/stickyScroll/browser/stickyScroll';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||
import { createTextModel } from 'vs/editor/test/common/testTextModel';
|
||||
import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService';
|
||||
import { DocumentSymbol, SymbolKind } from 'vs/editor/common/languages';
|
||||
import { CoreEditingCommands, CoreNavigationCommands } from 'vs/editor/browser/coreCommands';
|
||||
import { StickyLineCandidate, StickyLineCandidateProvider } from 'vs/editor/contrib/stickyScroll/browser/stickyScrollProvider';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
// To run this test file : ./test.bat --glob **/stickyScroll.test.js in the scripts folder
|
||||
|
||||
suite('Sticky Scroll Tests', () => {
|
||||
|
||||
test('issue #8817: Cursor position changes when you cancel multicursor', () => {
|
||||
withTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], {}, (editor) => {
|
||||
const serviceCollection = new ServiceCollection(
|
||||
[ILanguageFeaturesService, new LanguageFeaturesService()]
|
||||
);
|
||||
|
||||
const stickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
|
||||
const model = createTextModel([
|
||||
'function foo() {',
|
||||
'',
|
||||
'}',
|
||||
'/* comment related to TestClass',
|
||||
' end of the comment */',
|
||||
'@classDecorator',
|
||||
'class TestClass {',
|
||||
'// comment related to the function functionOfClass',
|
||||
'functionOfClass(){',
|
||||
'function function1(){',
|
||||
'}',
|
||||
'}}',
|
||||
'function bar() { function insideBar() {}',
|
||||
'}'
|
||||
].join('\n'));
|
||||
|
||||
function documentSymbolProviderForTestModel() {
|
||||
return {
|
||||
provideDocumentSymbols() {
|
||||
return [
|
||||
{
|
||||
name: 'foo',
|
||||
detail: 'foo',
|
||||
kind: SymbolKind.Function,
|
||||
tags: [],
|
||||
range: { startLineNumber: 1, endLineNumber: 3, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 1 }
|
||||
} as DocumentSymbol,
|
||||
{
|
||||
name: 'TestClass',
|
||||
detail: 'TestClass',
|
||||
kind: SymbolKind.Class,
|
||||
tags: [],
|
||||
range: { startLineNumber: 4, endLineNumber: 12, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 7, endLineNumber: 7, startColumn: 1, endColumn: 1 },
|
||||
children: [
|
||||
{
|
||||
name: 'functionOfClass',
|
||||
detail: 'functionOfClass',
|
||||
kind: SymbolKind.Function,
|
||||
tags: [],
|
||||
range: { startLineNumber: 8, endLineNumber: 12, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 9, endLineNumber: 9, startColumn: 1, endColumn: 1 },
|
||||
children: [
|
||||
{
|
||||
name: 'function1',
|
||||
detail: 'function1',
|
||||
kind: SymbolKind.Function,
|
||||
tags: [],
|
||||
range: { startLineNumber: 10, endLineNumber: 11, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 10, endLineNumber: 10, startColumn: 1, endColumn: 1 },
|
||||
}
|
||||
]
|
||||
} as DocumentSymbol
|
||||
]
|
||||
} as DocumentSymbol,
|
||||
{
|
||||
name: 'bar',
|
||||
detail: 'bar',
|
||||
kind: SymbolKind.Function,
|
||||
tags: [],
|
||||
range: { startLineNumber: 13, endLineNumber: 14, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 13, endLineNumber: 13, startColumn: 1, endColumn: 1 },
|
||||
children: [
|
||||
{
|
||||
name: 'insideBar',
|
||||
detail: 'insideBar',
|
||||
kind: SymbolKind.Function,
|
||||
tags: [],
|
||||
range: { startLineNumber: 13, endLineNumber: 13, startColumn: 1, endColumn: 1 },
|
||||
selectionRange: { startLineNumber: 13, endLineNumber: 13, startColumn: 1, endColumn: 1 },
|
||||
} as DocumentSymbol
|
||||
]
|
||||
} as DocumentSymbol
|
||||
];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test('Testing the function getCandidateStickyLinesIntersecting', async () => {
|
||||
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, _viewModel, instantiationService) => {
|
||||
const languageService = instantiationService.get(ILanguageFeaturesService);
|
||||
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());
|
||||
const provider: StickyLineCandidateProvider = new StickyLineCandidateProvider(editor, languageService);
|
||||
|
||||
/*
|
||||
provider.onStickyScrollChange(() => {
|
||||
console.log('resolve');
|
||||
});
|
||||
*/
|
||||
|
||||
// TODO: The below times out doesn't return after 5000 ms
|
||||
/*
|
||||
await new Promise<void>(resolve => {
|
||||
const disposable = provider.onStickyScrollChange(() => {
|
||||
console.log('resolve');
|
||||
resolve();
|
||||
});
|
||||
disposable.dispose();
|
||||
});
|
||||
*/
|
||||
|
||||
// console.log('before update of provider');
|
||||
await provider.update();
|
||||
|
||||
assert.deepStrictEqual(provider.getCandidateStickyLinesIntersecting({ startLineNumber: 1, endLineNumber: 4 }), [new StickyLineCandidate(1, 2, 1)]);
|
||||
assert.deepStrictEqual(provider.getCandidateStickyLinesIntersecting({ startLineNumber: 1, endLineNumber: 10 }), [new StickyLineCandidate(1, 2, 1), new StickyLineCandidate(7, 11, 1), new StickyLineCandidate(9, 11, 2), new StickyLineCandidate(10, 10, 3)]);
|
||||
assert.deepStrictEqual(provider.getCandidateStickyLinesIntersecting({ startLineNumber: 1, endLineNumber: 13 }), [new StickyLineCandidate(1, 2, 1), new StickyLineCandidate(7, 11, 1), new StickyLineCandidate(9, 11, 2), new StickyLineCandidate(10, 10, 3), new StickyLineCandidate(13, 13, 1)]);
|
||||
|
||||
provider.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #157180: Render the correct line corresponding to the scope definition', async () => {
|
||||
|
||||
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, _viewModel, instantiationService) => {
|
||||
|
||||
const stickyScrollController: StickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
|
||||
await stickyScrollController.stickyScrollCandidateProvider.update();
|
||||
|
||||
const lineHeight: number = editor.getOption(EditorOption.lineHeight);
|
||||
const languageService: ILanguageFeaturesService = instantiationService.get(ILanguageFeaturesService);
|
||||
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());
|
||||
let state;
|
||||
|
||||
editor.setScrollTop(lineHeight + 1);
|
||||
state = stickyScrollController.getScrollWidgetState();
|
||||
assert.deepStrictEqual(state.lineNumbers, [1]);
|
||||
|
||||
editor.setScrollTop(4 * lineHeight + 1);
|
||||
state = stickyScrollController.getScrollWidgetState();
|
||||
assert.deepStrictEqual(state.lineNumbers, []);
|
||||
|
||||
editor.setScrollTop(8 * lineHeight + 1);
|
||||
state = stickyScrollController.getScrollWidgetState();
|
||||
assert.deepStrictEqual(state.lineNumbers, [7, 9]);
|
||||
|
||||
editor.setScrollTop(9 * lineHeight + 1);
|
||||
state = stickyScrollController.getScrollWidgetState();
|
||||
assert.deepStrictEqual(state.lineNumbers, [7, 9]);
|
||||
|
||||
editor.setScrollTop(10 * lineHeight + 1);
|
||||
state = stickyScrollController.getScrollWidgetState();
|
||||
assert.deepStrictEqual(state.lineNumbers, [7]);
|
||||
|
||||
stickyScrollController.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #157809: Reveal the correct range taking into account the widget height', async () => {
|
||||
|
||||
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, viewModel, instantiationService) => {
|
||||
|
||||
const stickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
|
||||
await stickyScrollController.stickyScrollCandidateProvider.update();
|
||||
const lineHeight = editor.getOption(EditorOption.lineHeight);
|
||||
|
||||
const languageService = instantiationService.get(ILanguageFeaturesService);
|
||||
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());
|
||||
|
||||
// editor.setPosition({ lineNumber: 5, column: 1 }, 'test');
|
||||
editor.setScrollTop(11 * lineHeight);
|
||||
|
||||
/*
|
||||
CoreNavigationCommands.CreateCursor.runCoreEditorCommand(viewModel, {
|
||||
source: 'mouse',
|
||||
position: new Position(2, 1),
|
||||
viewPosition: new Position(2, 1),
|
||||
wholeLine: true
|
||||
});
|
||||
*/
|
||||
// CoreNavigationCommands.MoveTo.runCoreEditorCommand(viewModel, { position: new Position(2, 1) });
|
||||
|
||||
|
||||
console.log('visible ranges : ', editor.getVisibleRanges()[0].startLineNumber);
|
||||
console.log('scroll top : ', Math.floor(editor.getScrollTop() / lineHeight));
|
||||
console.log('position : ', editor.getPosition().lineNumber);
|
||||
|
||||
/*
|
||||
editor.trigger('keyboard', Handler.Type, { text: 'd' });
|
||||
CoreNavigationCommands.RevealLine.runCoreEditorCommand(viewModel, { lineNumber: 5, source: undefined });
|
||||
*/
|
||||
CoreEditingCommands.Tab.runEditorCommand(null, editor, null);
|
||||
|
||||
console.log('visible ranges : ', editor.getVisibleRanges()[0].startLineNumber);
|
||||
console.log('scroll top : ', Math.floor(editor.getScrollTop() / lineHeight));
|
||||
console.log('position : ', editor.getPosition().lineNumber);
|
||||
|
||||
stickyScrollController.dispose();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #156268 : Do not reveal sticky lines when they are in a folded region ', async () => {
|
||||
|
||||
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, viewModel, instantiationService) => {
|
||||
|
||||
const stickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
|
||||
await stickyScrollController.stickyScrollCandidateProvider.update();
|
||||
const lineHeight = editor.getOption(EditorOption.lineHeight);
|
||||
|
||||
const languageService = instantiationService.get(ILanguageFeaturesService);
|
||||
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());
|
||||
|
||||
stickyScrollController.dispose();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue