diff --git a/src/vs/base/browser/ui/tree/treeModel.ts b/src/vs/base/browser/ui/tree/treeModel.ts index ae662e1cb22..bb20f8eb727 100644 --- a/src/vs/base/browser/ui/tree/treeModel.ts +++ b/src/vs/base/browser/ui/tree/treeModel.ts @@ -125,7 +125,7 @@ export class TreeModel { } private _setCollapsed(location: number[], collapsed?: boolean | undefined): void { - const { node, listIndex, visible } = this.findNode(location); + let { node, listIndex, visible } = this.findNode(location); if (typeof collapsed === 'undefined') { collapsed = !node.collapsed; @@ -138,16 +138,23 @@ export class TreeModel { node.collapsed = collapsed; if (visible) { + let visibleCountDiff: number; + if (collapsed) { const deleteCount = getVisibleCount(node.children); this.list.splice(listIndex, 1 + deleteCount, [node]); - node.visibleCount = 1; + visibleCountDiff = -deleteCount; } else { const toInsert = [node, ...getVisibleNodes(node.children)]; this.list.splice(listIndex, 1, toInsert); - node.visibleCount = toInsert.length; + visibleCountDiff = toInsert.length - 1; + } + + while (node) { + node.visibleCount += visibleCountDiff; + node = node.parent; } } } diff --git a/src/vs/base/test/browser/ui/tree/treeModel.test.ts b/src/vs/base/test/browser/ui/tree/treeModel.test.ts index 28d0e37fda3..a4901161329 100644 --- a/src/vs/base/test/browser/ui/tree/treeModel.test.ts +++ b/src/vs/base/test/browser/ui/tree/treeModel.test.ts @@ -16,16 +16,20 @@ function toSpliceable(arr: T[]): ISpliceable { }; } -suite('TreeModel2', () => { +function toArray(list: ITreeNode[]): T[] { + return list.map(i => i.element); +} - test('ctor', () => { +suite('TreeModel2', function () { + + test('ctor', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); assert(model); assert.equal(list.length, 0); }); - test('insert', () => { + test('insert', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -47,7 +51,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[2].depth, 1); }); - test('deep insert', () => { + test('deep insert', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -84,7 +88,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[5].depth, 1); }); - test('deep insert collapsed', () => { + test('deep insert collapsed', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -112,7 +116,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[2].depth, 1); }); - test('delete', () => { + test('delete', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -137,7 +141,7 @@ suite('TreeModel2', () => { assert.deepEqual(list.length, 0); }); - test('nested delete', () => { + test('nested delete', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -171,7 +175,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[3].depth, 2); }); - test('deep delete', () => { + test('deep delete', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -199,7 +203,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[1].depth, 1); }); - test('hidden delete', () => { + test('hidden delete', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -224,7 +228,7 @@ suite('TreeModel2', () => { assert.deepEqual(list.length, 3); }); - test('collapse', () => { + test('collapse', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -255,7 +259,7 @@ suite('TreeModel2', () => { assert.deepEqual(list[2].depth, 1); }); - test('expand', () => { + test('expand', function () { const list = [] as ITreeNode[]; const model = new TreeModel(toSpliceable(list)); @@ -294,4 +298,37 @@ suite('TreeModel2', () => { assert.deepEqual(list[5].collapsed, false); assert.deepEqual(list[5].depth, 1); }); + + test('collapse should recursively adjust visible count', function () { + const list = [] as ITreeNode[]; + const model = new TreeModel(toSpliceable(list)); + + model.splice([0], 0, iter([ + { + element: 1, children: [ + { + element: 11, children: [ + { element: 111 } + ] + } + ] + }, + { + element: 2, children: [ + { element: 21 } + ] + } + ])); + + assert.deepEqual(list.length, 5); + assert.deepEqual(toArray(list), [1, 11, 111, 2, 21]); + + model.setCollapsed([0, 0], true); + assert.deepEqual(list.length, 4); + assert.deepEqual(toArray(list), [1, 11, 2, 21]); + + model.setCollapsed([1], true); + assert.deepEqual(list.length, 3); + assert.deepEqual(toArray(list), [1, 11, 2]); + }); }); \ No newline at end of file diff --git a/test/tree/server.js b/test/tree/server.js index 14b8cf5ac76..2a931b51727 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 >= 2) { + if (!stat.isDirectory() || element === '.git' || element === '.build' || level >= 3) { return { element }; }