未验证 提交 be2e900e 编写于 作者: R rebornix

batch dom read and write

上级 1a22d1ac
......@@ -11,6 +11,7 @@ export interface IListVirtualDelegate<T> {
getHeight(element: T): number;
getTemplateId(element: T): string;
hasDynamicHeight?(element: T): boolean;
getDynamicHeight?(element: T): number | null;
setDynamicHeight?(element: T, height: number): void;
}
......
......@@ -1318,6 +1318,14 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private probeDynamicHeight(index: number): number {
const item = this.items[index];
if (!!this.virtualDelegate.getDynamicHeight && this.virtualDelegate.getDynamicHeight(item.element) !== null) {
const size = item.size;
let newSize = this.virtualDelegate.getDynamicHeight(item.element)!;
item.size = newSize;
item.lastDynamicHeightWidth = this.renderWidth;
return newSize - size;
}
if (!item.hasDynamicHeight || item.lastDynamicHeightWidth === this.renderWidth) {
return 0;
}
......
......@@ -749,6 +749,7 @@
.monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container,
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container {
position: absolute;
top: 0px;
display: flex;
height: 33px;
justify-content: center;
......
......@@ -1320,7 +1320,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._localStore.add(this._list.onWillScroll(e => {
if (this._webview?.isResolved()) {
this._webviewTransparentCover!.style.top = `${e.scrollTop}px`;
this._webviewTransparentCover!.style.transform = `translateY(${e.scrollTop})`;
}
}));
......
......@@ -68,9 +68,14 @@ export class CellOutputElement extends Disposable {
public useDedicatedDOM: boolean = true;
private _height: number = -1;
get domOffsetHeight() {
if (this.useDedicatedDOM) {
return this.innerContainer.offsetHeight;
if (this._height === -1) {
return this.innerContainer.offsetHeight;
} else {
return this._height;
}
} else {
return 0;
}
......@@ -200,6 +205,16 @@ export class CellOutputElement extends Disposable {
this.innerContainer.setAttribute('output-mime-type', pickedMimeTypeRenderer.mimeType);
}
private _initHeightChecked = false;
probeHeight(index: number) {
if (!this._initHeightChecked) {
// postponed DOM read
const offsetHeight = this.domOffsetHeight;
this.viewCell.updateOutputHeight(index, offsetHeight, 'CellOutputElement#renderResultInitHeight');
}
}
render(previousSibling?: HTMLElement): IRenderResult | undefined {
const index = this.viewCell.outputsViewModels.indexOf(this.output);
......@@ -264,12 +279,20 @@ export class CellOutputElement extends Disposable {
return { initRenderIsSynchronous: true };
}
// let's use resize listener for them
const offsetHeight = this.renderResult?.initHeight !== undefined ? this.renderResult?.initHeight : Math.ceil(this.innerContainer.offsetHeight);
let offsetHeight = 0;
if (this.renderResult?.initHeight) {
offsetHeight = this.renderResult.initHeight;
this._initHeightChecked = true;
} else {
this._initHeightChecked = false;
}
const dimension = {
width: this.viewCell.layoutInfo.editorWidth,
height: offsetHeight
};
// let's use resize listener for them
this._bindResizeListener(dimension);
this.viewCell.updateOutputHeight(index, offsetHeight, 'CellOutputElement#renderResultInitHeight');
const top = this.viewCell.getOutputOffsetInContainer(index);
......@@ -296,6 +319,8 @@ export class CellOutputElement extends Disposable {
height: height
};
this._initHeightChecked = true;
this._height = height;
this._validateFinalOutputHeight(true);
this.viewCell.updateOutputHeight(currIndex, height, 'CellOutputElement#outputResize');
this._relayoutCell();
......@@ -537,6 +562,15 @@ export class CellOutputContainer extends Disposable {
}));
}
probeHeight() {
this._outputEntries.forEach(entry => {
const index = this.viewCell.outputsViewModels.indexOf(entry.model);
if (index >= 0) {
entry.element.probeHeight(index);
}
});
}
render(editorHeight: number) {
if (this.viewCell.outputsViewModels.length > 0) {
if (this.viewCell.layoutInfo.totalHeight !== 0 && this.viewCell.layoutInfo.editorHeight > editorHeight) {
......
......@@ -74,6 +74,10 @@ export class NotebookCellListDelegate extends Disposable implements IListVirtual
return element.hasDynamicHeight();
}
getDynamicHeight(element: CellViewModel): number | null {
return element.getDynamicHeight();
}
getTemplateId(element: CellViewModel): string {
if (element.cellKind === CellKind.Markup) {
return MarkupCellRenderer.TEMPLATE_ID;
......@@ -144,11 +148,11 @@ abstract class AbstractCellRenderer {
const container = templateData.bottomCellContainer;
const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset;
container.style.top = `${bottomToolbarOffset}px`;
container.style.transform = `translateY(${bottomToolbarOffset}px)`;
templateData.elementDisposables.add(element.onDidChangeLayout(() => {
const bottomToolbarOffset = element.layoutInfo.bottomToolbarOffset;
container.style.top = `${bottomToolbarOffset}px`;
container.style.transform = `translateY(${bottomToolbarOffset}px)`;
}));
}
......@@ -192,14 +196,14 @@ abstract class AbstractCellRenderer {
if (actions.primary.length || actions.secondary.length) {
templateData.container.classList.add('cell-has-toolbar-actions');
if (isCodeCellRenderTemplate(templateData)) {
templateData.focusIndicatorLeft.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`;
templateData.focusIndicatorRight.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`;
templateData.focusIndicatorLeft.style.transform = `translateY(${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px)`;
templateData.focusIndicatorRight.style.transform = `translateY(${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px)`;
}
} else {
templateData.container.classList.remove('cell-has-toolbar-actions');
if (isCodeCellRenderTemplate(templateData)) {
templateData.focusIndicatorLeft.style.top = `${layoutInfo.cellTopMargin}px`;
templateData.focusIndicatorRight.style.top = `${layoutInfo.cellTopMargin}px`;
templateData.focusIndicatorLeft.style.transform = `translateY(${layoutInfo.cellTopMargin}px)`;
templateData.focusIndicatorRight.style.transform = `translateY(${layoutInfo.cellTopMargin}px)`;
}
}
};
......@@ -436,7 +440,8 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen
private updateForLayout(element: MarkupCellViewModel, templateData: MarkdownCellRenderTemplate): void {
const indicatorPostion = this.notebookEditor.notebookOptions.computeIndicatorPosition(element.layoutInfo.totalHeight, this.notebookEditor.textModel?.viewType);
templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`;
templateData.focusIndicatorBottom.style.transform = `translateY(${indicatorPostion.bottomIndicatorTop}px)`;
templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`;
templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`;
......@@ -930,17 +935,19 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
}
private updateForLayout(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void {
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
const bottomToolbarDimensions = this.notebookEditor.notebookOptions.computeBottomToolbarDimensions(this.notebookEditor.textModel?.viewType);
templateData.disposables.add(DOM.scheduleAtNextAnimationFrame(() => {
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
const bottomToolbarDimensions = this.notebookEditor.notebookOptions.computeBottomToolbarDimensions(this.notebookEditor.textModel?.viewType);
templateData.focusIndicatorLeft.style.height = `${element.layoutInfo.indicatorHeight}px`;
templateData.focusIndicatorRight.style.height = `${element.layoutInfo.indicatorHeight}px`;
templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - bottomToolbarDimensions.bottomToolbarGap - layoutInfo.cellBottomMargin}px`;
templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`;
templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`;
templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - bottomToolbarDimensions.bottomToolbarGap}px`;
templateData.focusIndicatorLeft.style.height = `${element.layoutInfo.indicatorHeight}px`;
templateData.focusIndicatorRight.style.height = `${element.layoutInfo.indicatorHeight}px`;
templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - bottomToolbarDimensions.bottomToolbarGap - layoutInfo.cellBottomMargin}px`;
templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`;
templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`;
templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - bottomToolbarDimensions.bottomToolbarGap}px`;
templateData.container.classList.toggle('cell-statusbar-hidden', this.notebookEditor.notebookOptions.computeEditorStatusbarHeight(element.internalMetadata) === 0);
templateData.container.classList.toggle('cell-statusbar-hidden', this.notebookEditor.notebookOptions.computeEditorStatusbarHeight(element.internalMetadata) === 0);
}));
}
renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void {
......
......@@ -250,6 +250,10 @@ export class CodeCell extends Disposable {
this.viewCell.layoutChange({});
}
this._register(this.viewCell.onLayoutInfoRead(() => {
this._outputContainerRenderer.probeHeight();
}));
this.updateForCollapseState();
}
......
......@@ -23,6 +23,8 @@ import { BaseCellViewModel } from './baseCellViewModel';
export class CodeCellViewModel extends BaseCellViewModel implements ICellViewModel {
readonly cellKind = CellKind.Code;
protected readonly _onLayoutInfoRead = this._register(new Emitter<void>());
readonly onLayoutInfoRead = this._onLayoutInfoRead.event;
protected readonly _onDidChangeOutputs = this._register(new Emitter<NotebookCellOutputsSplice>());
readonly onDidChangeOutputs = this._onDidChangeOutputs.event;
......@@ -285,6 +287,11 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
return false;
}
getDynamicHeight() {
this._onLayoutInfoRead.fire();
return this._layoutInfo.totalHeight;
}
firstLine(): string {
return this.getText().split('\n')[0];
}
......
......@@ -250,6 +250,10 @@ export class MarkupCellViewModel extends BaseCellViewModel implements ICellViewM
return false;
}
getDynamicHeight() {
return null;
}
getHeight(lineHeight: number) {
if (this._layoutInfo.layoutState === CellLayoutState.Uninitialized) {
return 100;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册