diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index a90726815f7..1b020fee6e7 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -60,6 +60,7 @@ class TreeDelegate implements IVirtualDelegate> { interface ITreeListTemplateData { twistie: HTMLElement; + count: HTMLElement; templateData: T; } @@ -89,9 +90,10 @@ class TreeRenderer implements IRenderer, ITreeLis const el = append(container, $('.monaco-tl-row')); const twistie = append(el, $('.tl-twistie')); const contents = append(el, $('.tl-contents')); + const count = append(el, $('.tl-count')); const templateData = this.renderer.renderTemplate(contents); - return { twistie, templateData }; + return { twistie, count, templateData }; } renderElement(node: ITreeNode, index: number, templateData: ITreeListTemplateData): void { @@ -99,6 +101,7 @@ class TreeRenderer implements IRenderer, ITreeLis templateData.twistie.style.width = `${10 + node.depth * 10}px`; renderTwistie(node, templateData.twistie); + templateData.count.textContent = `${node.visibleCount}`; this.renderer.renderElement(node.element, index, templateData.templateData); } @@ -119,6 +122,7 @@ class TreeRenderer implements IRenderer, ITreeLis } renderTwistie(node, templateData.twistie); + templateData.count.textContent = `${node.visibleCount}`; } dispose(): void { diff --git a/src/vs/base/browser/ui/tree/treeModel.ts b/src/vs/base/browser/ui/tree/treeModel.ts index 1a30ff92292..7d8e2b70c98 100644 --- a/src/vs/base/browser/ui/tree/treeModel.ts +++ b/src/vs/base/browser/ui/tree/treeModel.ts @@ -39,13 +39,35 @@ function getVisibleCount(nodes: IMutableTreeNode[]): number { return nodes.reduce(visibleCountReducer, 0); } -function getVisibleNodes(nodes: IMutableTreeNode[], result: ITreeNode[] = []): ITreeNode[] { - for (const node of nodes) { +/** + * Recursively updates the visibleCount of a subtree, while collecting + * all the visible nodes in an array. + */ +function updateVisibleCount(node: IMutableTreeNode): ITreeNode[] { + const previousVisibleCount = node.visibleCount; + const result: ITreeNode[] = []; + + function _updateVisibleCount(node: IMutableTreeNode): number { result.push(node); + node.visibleCount = 1; if (!node.collapsed) { - getVisibleNodes(node.children, result); + for (const child of node.children) { + node.visibleCount += _updateVisibleCount(child); + } } + + return node.visibleCount; + } + + _updateVisibleCount(node); + + const visibleCountDiff = result.length - previousVisibleCount; + node = node.parent; + + while (node) { + node.visibleCount += visibleCountDiff; + node = node.parent; } return result; @@ -108,6 +130,7 @@ export class TreeModel { visibleCount: 1 }; + // TODO@joao can't we do without this? private _onDidChangeCollapseState = new Emitter>(); readonly onDidChangeCollapseState: Event> = this._onDidChangeCollapseState.event; @@ -165,30 +188,14 @@ export class TreeModel { node.collapsed = collapsed; if (visible) { - this._onDidChangeCollapseState.fire(node); + const previousVisibleCount = node.visibleCount; + const toInsert = updateVisibleCount(node); - let visibleCountDiff: number; - - if (collapsed) { - const deleteCount = getVisibleCount(node.children); - - this.list.splice(listIndex + 1, deleteCount, []); - visibleCountDiff = -deleteCount; - } else { - const toInsert = getVisibleNodes(node.children); - - this.list.splice(listIndex + 1, 0, toInsert); - visibleCountDiff = toInsert.length; - } - - let mutableNode = node; - - while (mutableNode) { - mutableNode.visibleCount += visibleCountDiff; - mutableNode = mutableNode.parent; - } + this.list.splice(listIndex + 1, previousVisibleCount - 1, toInsert.slice(1)); } + this._onDidChangeCollapseState.fire(node); + return true; } diff --git a/test/tree/public/index.html b/test/tree/public/index.html index f676b7a8753..3716374c0de 100644 --- a/test/tree/public/index.html +++ b/test/tree/public/index.html @@ -13,6 +13,10 @@ .monaco-scrollable-element>.scrollbar>.slider { background: rgba(100, 100, 100, .4); } + + .tl-contents { + flex: 1; + } diff --git a/test/tree/server.js b/test/tree/server.js index b1105bfb741..11ac8e1ac9b 100644 --- a/test/tree/server.js +++ b/test/tree/server.js @@ -17,7 +17,7 @@ async function getTree(fsPath, level) { const element = path.basename(fsPath); const stat = await fs.stat(fsPath); - if (!stat.isDirectory() || element === '.git' || element === '.build' || level >= 3) { + if (!stat.isDirectory() || element === '.git' || element === '.build' || level >= 4) { return { element }; }