提交 e32e353b 编写于 作者: R rebornix

fix #114171.

上级 255853d1
......@@ -1294,11 +1294,17 @@ declare module 'vscode' {
* The range will always be revealed in the center of the viewport.
*/
InCenter = 1,
/**
* If the range is outside the viewport, it will be revealed in the center of the viewport.
* Otherwise, it will be revealed with as little scrolling as possible.
*/
InCenterIfOutsideViewport = 2,
/**
* The range will always be revealed at the top of the viewport.
*/
AtTop = 3
}
export interface NotebookEditor {
......
......@@ -646,14 +646,13 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
switch (revealType) {
case NotebookEditorRevealType.Default:
notebookEditor.revealInView(cell);
break;
return notebookEditor.revealCellRangeInView(range);
case NotebookEditorRevealType.InCenter:
notebookEditor.revealInCenter(cell);
break;
return notebookEditor.revealInCenter(cell);
case NotebookEditorRevealType.InCenterIfOutsideViewport:
notebookEditor.revealInCenterIfOutsideViewport(cell);
break;
return notebookEditor.revealInCenterIfOutsideViewport(cell);
case NotebookEditorRevealType.AtTop:
return notebookEditor.revealInViewAtTop(cell);
default:
break;
}
......
......@@ -754,6 +754,7 @@ export enum NotebookEditorRevealType {
Default = 0,
InCenter = 1,
InCenterIfOutsideViewport = 2,
AtTop = 3
}
export interface INotebookDocumentShowOptions {
......
......@@ -2858,7 +2858,8 @@ export enum NotebookCellStatusBarAlignment {
export enum NotebookEditorRevealType {
Default = 0,
InCenter = 1,
InCenterIfOutsideViewport = 2
InCenterIfOutsideViewport = 2,
AtTop = 3
}
......
......@@ -500,11 +500,21 @@ export interface INotebookEditor extends IEditor, ICommonNotebookEditor {
*/
triggerScroll(event: IMouseWheelEvent): void;
/**
* The range will be revealed with as little scrolling as possible.
*/
revealCellRangeInView(range: ICellRange): void;
/**
* Reveal cell into viewport.
*/
revealInView(cell: ICellViewModel): void;
/**
* Reveal cell into the top of viewport.
*/
revealInViewAtTop(cell: ICellViewModel): void;
/**
* Reveal cell into viewport center.
*/
......@@ -614,7 +624,9 @@ export interface INotebookCellList {
focusElement(element: ICellViewModel): void;
selectElement(element: ICellViewModel): void;
getFocusedElements(): ICellViewModel[];
revealElementsInView(range: ICellRange): void;
revealElementInView(element: ICellViewModel): void;
revealElementInViewAtTop(element: ICellViewModel): void;
revealElementInCenterIfOutsideViewport(element: ICellViewModel): void;
revealElementInCenter(element: ICellViewModel): void;
revealElementInCenterIfOutsideViewportAsync(element: ICellViewModel): Promise<void>;
......
......@@ -1226,10 +1226,18 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
// this.viewModel!.selectionHandles = [cell.handle];
}
revealCellRangeInView(range: ICellRange) {
return this._list.revealElementsInView(range);
}
revealInView(cell: ICellViewModel) {
this._list.revealElementInView(cell);
}
revealInViewAtTop(cell: ICellViewModel) {
this._list.revealElementInViewAtTop(cell);
}
revealInCenterIfOutsideViewport(cell: ICellViewModel) {
this._list.revealElementInCenterIfOutsideViewport(cell);
}
......
......@@ -547,6 +547,22 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
return viewIndexInfo.index;
}
private _getViewIndexUpperBound2(modelIndex: number) {
if (!this.hiddenRangesPrefixSum) {
return modelIndex;
}
const viewIndexInfo = this.hiddenRangesPrefixSum.getIndexOf(modelIndex);
if (viewIndexInfo.remainder !== 0) {
if (modelIndex >= this.hiddenRangesPrefixSum.getTotalValue()) {
return modelIndex - (this.hiddenRangesPrefixSum.getTotalValue() - this.hiddenRangesPrefixSum.getCount());
}
}
return viewIndexInfo.index;
}
focusElement(cell: ICellViewModel) {
const index = this._getViewIndexUpperBound(cell);
......@@ -587,6 +603,46 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
super.setFocus(indexes, browserEvent);
}
revealElementsInView(range: ICellRange) {
const startIndex = this._getViewIndexUpperBound2(range.start);
if (startIndex < 0) {
return;
}
const endIndex = this._getViewIndexUpperBound2(range.end);
const scrollTop = this.getViewScrollTop();
const wrapperBottom = this.getViewScrollBottom();
const elementTop = this.view.elementTop(startIndex);
if (elementTop >= scrollTop
&& elementTop < wrapperBottom) {
// start element is visible
// check end
const endElementTop = this.view.elementTop(endIndex);
const endElementHeight = this.view.elementHeight(endIndex);
if (endElementTop >= wrapperBottom) {
return this._revealInternal(startIndex, false, CellRevealPosition.Top);
}
if (endElementTop < wrapperBottom) {
// end element partially visible
if (endElementTop + endElementHeight - wrapperBottom < elementTop - scrollTop) {
// there is enough space to just scroll up a little bit to make the end element visible
return this.view.setScrollTop(scrollTop + endElementTop + endElementHeight - wrapperBottom);
} else {
// don't even try it
return this._revealInternal(startIndex, false, CellRevealPosition.Top);
}
}
}
this._revealInView(startIndex);
}
revealElementInView(cell: ICellViewModel) {
const index = this._getViewIndexUpperBound(cell);
......@@ -595,6 +651,14 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
}
}
revealElementInViewAtTop(cell: ICellViewModel) {
const index = this._getViewIndexUpperBound(cell);
if (index >= 0) {
this._revealInternal(index, false, CellRevealPosition.Top);
}
}
revealElementInCenterIfOutsideViewport(cell: ICellViewModel) {
const index = this._getViewIndexUpperBound(cell);
......
......@@ -275,7 +275,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const mainCells = cells.map(cell => {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
const cellUri = CellUri.generate(this.uri, this.viewType, cellHandle);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modelService);
});
......@@ -425,7 +425,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
// prepare add
const cells = cellDtos.map(cellDto => {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
const cellUri = CellUri.generate(this.uri, this.viewType, cellHandle);
const cell = new NotebookCellTextModel(
cellUri, cellHandle,
cellDto.source, cellDto.language, cellDto.cellKind, cellDto.outputs || [], cellDto.metadata, this.transientOptions,
......
......@@ -467,7 +467,7 @@ export function getCellUndoRedoComparisonKey(uri: URI) {
return uri.toString();
}
return data.notebook.toString();
return `vt=${data.viewType}&uri=data.notebook.toString()`;
}
......@@ -477,10 +477,11 @@ export namespace CellUri {
const _regex = /^ch(\d{7,})/;
export function generate(notebook: URI, handle: number): URI {
export function generate(notebook: URI, viewType: string, handle: number): URI {
return notebook.with({
scheme,
fragment: `ch${handle.toString().padStart(7, '0')}${notebook.scheme !== Schemas.file ? notebook.scheme : ''}`
fragment: `ch${handle.toString().padStart(7, '0')}${notebook.scheme !== Schemas.file ? notebook.scheme : ''}`,
query: `vt=${viewType}`
});
}
......@@ -492,7 +493,7 @@ export namespace CellUri {
});
}
export function parse(cell: URI): { notebook: URI, handle: number } | undefined {
export function parse(cell: URI): { notebook: URI, handle: number, viewType: string } | undefined {
if (cell.scheme !== scheme) {
return undefined;
}
......@@ -505,8 +506,10 @@ export namespace CellUri {
handle,
notebook: cell.with({
scheme: cell.fragment.substr(match[0].length) || Schemas.file,
fragment: null
})
fragment: null,
query: null
}),
viewType: cell.query.substr('vt='.length)
};
}
}
......
......@@ -336,11 +336,12 @@ suite('CellUri', function () {
const nb = URI.parse('foo:///bar/følder/file.nb');
const id = 17;
const data = CellUri.generate(nb, id);
const data = CellUri.generate(nb, 'test', id);
const actual = CellUri.parse(data);
assert.ok(Boolean(actual));
assert.equal(actual?.handle, id);
assert.equal(actual?.notebook.toString(), nb.toString());
assert.equal(actual?.viewType, 'test');
});
test('parse, generate (foo-scheme)', function () {
......@@ -348,10 +349,11 @@ suite('CellUri', function () {
const nb = URI.parse('foo:///bar/følder/file.nb');
const id = 17;
const data = CellUri.generate(nb, id);
const data = CellUri.generate(nb, 'test', id);
const actual = CellUri.parse(data);
assert.ok(Boolean(actual));
assert.equal(actual?.handle, id);
assert.equal(actual?.notebook.toString(), nb.toString());
assert.equal(actual?.viewType, 'test');
});
});
......@@ -47,7 +47,7 @@ export class TestCell extends NotebookCellTextModel {
outputs: IProcessedOutput[],
modelService: ITextModelService
) {
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, { transientMetadata: {}, transientOutputs: false }, modelService);
super(CellUri.generate(URI.parse('test:///fake/notebook'), viewType, handle), handle, source, language, cellKind, outputs, undefined, { transientMetadata: {}, transientOutputs: false }, modelService);
}
}
......
......@@ -62,7 +62,7 @@ suite('NotebookCell#Document', function () {
versionId: 0,
cells: [{
handle: 0,
uri: CellUri.generate(notebookUri, 0),
uri: CellUri.generate(notebookUri, 'test', 0),
source: ['### Heading'],
eol: '\n',
language: 'markdown',
......@@ -70,7 +70,7 @@ suite('NotebookCell#Document', function () {
outputs: [],
}, {
handle: 1,
uri: CellUri.generate(notebookUri, 1),
uri: CellUri.generate(notebookUri, 'test', 1),
source: ['console.log("aaa")', 'console.log("bbb")'],
eol: '\n',
language: 'javascript',
......@@ -167,7 +167,7 @@ suite('NotebookCell#Document', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 2,
uri: CellUri.generate(notebookUri, 2),
uri: CellUri.generate(notebookUri, 'test', 2),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -175,7 +175,7 @@ suite('NotebookCell#Document', function () {
outputs: [],
}, {
handle: 3,
uri: CellUri.generate(notebookUri, 3),
uri: CellUri.generate(notebookUri, 'test', 3),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -284,7 +284,7 @@ suite('NotebookCell#Document', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 2,
uri: CellUri.generate(notebookUri, 2),
uri: CellUri.generate(notebookUri, 'test', 2),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -292,7 +292,7 @@ suite('NotebookCell#Document', function () {
outputs: [],
}, {
handle: 3,
uri: CellUri.generate(notebookUri, 3),
uri: CellUri.generate(notebookUri, 'test', 3),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......
......@@ -61,7 +61,7 @@ suite('NotebookConcatDocument', function () {
viewType: 'test',
cells: [{
handle: 0,
uri: CellUri.generate(notebookUri, 0),
uri: CellUri.generate(notebookUri, 'test', 0),
source: ['### Heading'],
eol: '\n',
language: 'markdown',
......@@ -122,8 +122,8 @@ suite('NotebookConcatDocument', function () {
test('contains', function () {
const cellUri1 = CellUri.generate(notebook.uri, 1);
const cellUri2 = CellUri.generate(notebook.uri, 2);
const cellUri1 = CellUri.generate(notebook.uri, 'test', 1);
const cellUri2 = CellUri.generate(notebook.uri, 'test', 2);
extHostNotebooks.$acceptModelChanged(notebookUri, {
versionId: notebook.notebookDocument.version + 1,
......@@ -169,7 +169,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -177,7 +177,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -214,7 +214,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -241,7 +241,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[1, 0, [{
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -292,7 +292,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -300,7 +300,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -350,7 +350,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['fooLang-document'],
eol: '\n',
language: 'fooLang',
......@@ -358,7 +358,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['barLang-document'],
eol: '\n',
language: 'barLang',
......@@ -384,7 +384,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[2, 0, [{
handle: 3,
uri: CellUri.generate(notebook.uri, 3),
uri: CellUri.generate(notebook.uri, 'test', 3),
source: ['barLang-document2'],
eol: '\n',
language: 'barLang',
......@@ -422,7 +422,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -430,7 +430,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -479,7 +479,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -487,7 +487,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -520,7 +520,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -528,7 +528,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......@@ -558,7 +558,7 @@ suite('NotebookConcatDocument', function () {
kind: NotebookCellsChangeType.ModelChange,
changes: [[0, 0, [{
handle: 1,
uri: CellUri.generate(notebook.uri, 1),
uri: CellUri.generate(notebook.uri, 'test', 1),
source: ['Hello', 'World', 'Hello World!'],
eol: '\n',
language: 'test',
......@@ -566,7 +566,7 @@ suite('NotebookConcatDocument', function () {
outputs: [],
}, {
handle: 2,
uri: CellUri.generate(notebook.uri, 2),
uri: CellUri.generate(notebook.uri, 'test', 2),
source: ['Hallo', 'Welt', 'Hallo Welt!'],
eol: '\n',
language: 'test',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册