list: finish dynamic height
This commit is contained in:
parent
82d00f5383
commit
352ede78ea
4 changed files with 64 additions and 12 deletions
|
@ -40,7 +40,7 @@ interface IItem<T> {
|
|||
row: IRow | null;
|
||||
size: number;
|
||||
hasDynamicHeight: boolean;
|
||||
dynamicSizeSnapshotId: number;
|
||||
renderWidth: number | undefined;
|
||||
}
|
||||
|
||||
export interface IListViewOptions {
|
||||
|
@ -68,7 +68,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||
private renderers = new Map<string, IListRenderer<T, any>>();
|
||||
private lastRenderTop: number;
|
||||
private lastRenderHeight: number;
|
||||
private dynamicSizeSnapshotId = 0;
|
||||
private renderWidth = 0;
|
||||
private gesture: Gesture;
|
||||
private rowsContainer: HTMLElement;
|
||||
private scrollableElement: ScrollableElement;
|
||||
|
@ -170,7 +170,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||
templateId: this.virtualDelegate.getTemplateId(element),
|
||||
size: this.virtualDelegate.getHeight(element),
|
||||
hasDynamicHeight: !!this.virtualDelegate.hasDynamicHeight && this.virtualDelegate.hasDynamicHeight(element),
|
||||
dynamicSizeSnapshotId: this.dynamicSizeSnapshotId - 1,
|
||||
renderWidth: undefined,
|
||||
row: null
|
||||
}));
|
||||
|
||||
|
@ -278,6 +278,14 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||
});
|
||||
}
|
||||
|
||||
layoutWidth(width: number): void {
|
||||
this.renderWidth = width;
|
||||
|
||||
if (this.supportDynamicHeights) {
|
||||
this.rerender(this.scrollTop, this.renderHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Render
|
||||
|
||||
private render(renderTop: number, renderHeight: number): void {
|
||||
|
@ -587,7 +595,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||
private probeDynamicHeight(index: number): number {
|
||||
const item = this.items[index];
|
||||
|
||||
if (!item.hasDynamicHeight || item.dynamicSizeSnapshotId === this.dynamicSizeSnapshotId) {
|
||||
if (!item.hasDynamicHeight || item.renderWidth === this.renderWidth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -599,7 +607,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
|||
this.rowsContainer.appendChild(row.domNode);
|
||||
renderer.renderElement(item.element, index, row.templateData);
|
||||
item.size = row.domNode.offsetHeight;
|
||||
item.dynamicSizeSnapshotId = this.dynamicSizeSnapshotId;
|
||||
item.renderWidth = this.renderWidth;
|
||||
this.rowsContainer.removeChild(row.domNode);
|
||||
this.cache.release(row);
|
||||
|
||||
|
|
|
@ -1055,6 +1055,10 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
|||
this.view.layout(height);
|
||||
}
|
||||
|
||||
layoutWidth(width: number): void {
|
||||
this.view.layoutWidth(width);
|
||||
}
|
||||
|
||||
setSelection(indexes: number[], browserEvent?: UIEvent): void {
|
||||
for (const index of indexes) {
|
||||
if (index < 0 || index >= this.length) {
|
||||
|
|
|
@ -246,6 +246,10 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
|||
this.view.layout(height);
|
||||
}
|
||||
|
||||
layoutWidth(width: number): void {
|
||||
this.view.layoutWidth(width);
|
||||
}
|
||||
|
||||
style(styles: IListStyles): void {
|
||||
this.view.style(styles);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<body>
|
||||
<input type="text" id="filter" />
|
||||
<button id="collapseall">Collapse All</button>
|
||||
<button id="renderwidth">Render Width</button>
|
||||
<div id="container"></div>
|
||||
|
||||
<script src="/static/vs/loader.js"></script>
|
||||
|
@ -42,7 +43,9 @@
|
|||
require.config({ baseUrl: '/static' });
|
||||
|
||||
require(['vs/base/browser/ui/tree/indexTree', 'vs/base/browser/ui/tree/dataTree', 'vs/base/browser/ui/tree/tree', 'vs/base/common/iterator'], ({ IndexTree }, { DataTree }, { TreeVisibility }, { iter }) => {
|
||||
function createIndexTree() {
|
||||
function createIndexTree(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
const delegate = {
|
||||
getHeight() { return 22; },
|
||||
getTemplateId() { return 'template'; },
|
||||
|
@ -53,7 +56,15 @@
|
|||
templateId: 'template',
|
||||
renderTemplate(container) { return container; },
|
||||
renderElement(element, index, container) {
|
||||
container.innerHTML = `${element.element}<br />${element.element}<br />${element.element}`;
|
||||
if (opts.supportDynamicHeights) {
|
||||
let v = [];
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
v.push(element.element);
|
||||
}
|
||||
container.innerHTML = v.join('<br />');
|
||||
} else {
|
||||
container.innerHTML = element.element;
|
||||
}
|
||||
},
|
||||
disposeElement() { },
|
||||
disposeTemplate() { }
|
||||
|
@ -82,7 +93,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
const tree = new IndexTree(container, delegate, [renderer], { filter: treeFilter, setRowLineHeight: false, supportDynamicHeights: true });
|
||||
const tree = new IndexTree(container, delegate, [renderer], { ...opts, filter: treeFilter, setRowLineHeight: false });
|
||||
|
||||
return { tree, treeFilter };
|
||||
}
|
||||
|
@ -161,6 +172,9 @@
|
|||
case '?problems': {
|
||||
const { tree, treeFilter } = createIndexTree();
|
||||
|
||||
collapseall.onclick = () => perf('collapse all', () => tree.collapseAll());
|
||||
renderwidth.onclick = () => perf('renderwidth', () => tree.layoutWidth(Math.random()));
|
||||
|
||||
const files = [];
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
const errors = [];
|
||||
|
@ -178,12 +192,18 @@
|
|||
case '?data': {
|
||||
const { tree, treeFilter } = createDataTree();
|
||||
|
||||
collapseall.onclick = () => perf('collapse all', () => tree.collapseAll());
|
||||
renderwidth.onclick = () => perf('renderwidth', () => tree.layoutWidth(Math.random()));
|
||||
|
||||
tree.refresh(null);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
const { tree, treeFilter } = createIndexTree();
|
||||
case '?height': {
|
||||
const { tree, treeFilter } = createIndexTree({ supportDynamicHeights: true });
|
||||
|
||||
collapseall.onclick = () => perf('collapse all', () => tree.collapseAll());
|
||||
renderwidth.onclick = () => perf('renderwidth', () => tree.layoutWidth(Math.random()));
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/ls?path=');
|
||||
|
@ -194,9 +214,25 @@
|
|||
treeFilter.updatePattern();
|
||||
}
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const { tree, treeFilter } = createIndexTree();
|
||||
|
||||
collapseall.onclick = () => perf('collapse all', () => tree.collapseAll());
|
||||
collapseall.onclick = () => perf('collapse all', () => tree.collapseAll());
|
||||
renderwidth.onclick = () => perf('renderwidth', () => tree.layoutWidth(Math.random()));
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/ls?path=');
|
||||
xhr.send();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
perf('splice', () => tree.splice([0], 0, [JSON.parse(this.responseText)]));
|
||||
treeFilter.updatePattern();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in a new issue