From 7c678d4e165ca9edddeee7406165b0aef38a7d80 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Mon, 9 Sep 2019 11:46:24 +0200 Subject: [PATCH] fix bad index tree collapse state update change --- src/vs/base/browser/ui/tree/indexTreeModel.ts | 52 +++++++++++++------ .../browser/ui/tree/indexTreeModel.test.ts | 31 +++++++++++ 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/vs/base/browser/ui/tree/indexTreeModel.ts b/src/vs/base/browser/ui/tree/indexTreeModel.ts index e4336640caf..f7f421ebf4d 100644 --- a/src/vs/base/browser/ui/tree/indexTreeModel.ts +++ b/src/vs/base/browser/ui/tree/indexTreeModel.ts @@ -46,6 +46,21 @@ export interface IIndexTreeModelOptions { readonly autoExpandSingleChildren?: boolean; } +interface CollapsibleStateUpdate { + readonly collapsible: boolean; +} + +interface CollapsedStateUpdate { + readonly collapsed: boolean; + readonly recursive: boolean; +} + +type CollapseStateUpdate = CollapsibleStateUpdate | CollapsedStateUpdate; + +function isCollapsibleStateUpdate(update: CollapseStateUpdate): update is CollapsibleStateUpdate { + return typeof (update as any).collapsible === 'boolean'; +} + export class IndexTreeModel, TFilterData = void> implements ITreeModel { readonly rootRef = []; @@ -212,7 +227,8 @@ export class IndexTreeModel, TFilterData = voi collapsible = !node.collapsible; } - return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, collapsible!, node.collapsed)); + const update: CollapsibleStateUpdate = { collapsible }; + return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update)); } isCollapsed(location: number[]): boolean { @@ -226,15 +242,16 @@ export class IndexTreeModel, TFilterData = voi collapsed = !node.collapsed; } - return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, node.collapsible, collapsed!, recursive)); + const update: CollapsedStateUpdate = { collapsed, recursive: recursive || false }; + return this.eventBufferer.bufferEvents(() => this._setCollapseState(location, update)); } - private _setCollapseState(location: number[], collapsible: boolean, collapsed: boolean, recursive?: boolean): boolean { + private _setCollapseState(location: number[], update: CollapseStateUpdate): boolean { const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location); - const result = this._setListNodeCollapseState(node, listIndex, revealed, collapsible, collapsed, recursive || false); + const result = this._setListNodeCollapseState(node, listIndex, revealed, update); - if (node !== this.root && this.autoExpandSingleChildren && !collapsed! && !recursive) { + if (node !== this.root && this.autoExpandSingleChildren && result && !isCollapsibleStateUpdate(update) && node.collapsible && !node.collapsed && !update.recursive) { let onlyVisibleChildIndex = -1; for (let i = 0; i < node.children.length; i++) { @@ -251,15 +268,15 @@ export class IndexTreeModel, TFilterData = voi } if (onlyVisibleChildIndex > -1) { - this._setCollapseState([...location, onlyVisibleChildIndex], false, false); + this._setCollapseState([...location, onlyVisibleChildIndex], update); } } return result; } - private _setListNodeCollapseState(node: IMutableTreeNode, listIndex: number, revealed: boolean, collapsible: boolean, collapsed: boolean, recursive: boolean): boolean { - const result = this._setNodeCollapseState(node, collapsible, collapsed, recursive, false); + private _setListNodeCollapseState(node: IMutableTreeNode, listIndex: number, revealed: boolean, update: CollapseStateUpdate): boolean { + const result = this._setNodeCollapseState(node, update, false); if (!revealed || !node.visible) { return result; @@ -273,23 +290,28 @@ export class IndexTreeModel, TFilterData = voi return result; } - private _setNodeCollapseState(node: IMutableTreeNode, collapsible: boolean, collapsed: boolean, recursive: boolean, deep: boolean): boolean { - let result = node.collapsible !== collapsible || node.collapsed !== collapsed; + private _setNodeCollapseState(node: IMutableTreeNode, update: CollapseStateUpdate, deep: boolean): boolean { + let result: boolean; if (node === this.root) { result = false; } else { - node.collapsible = collapsible; - node.collapsed = collapsed; + if (isCollapsibleStateUpdate(update)) { + result = node.collapsible !== update.collapsible; + node.collapsible = update.collapsible; + } else { + result = node.collapsed !== update.collapsed; + node.collapsed = update.collapsed; + } if (result) { this._onDidChangeCollapseState.fire({ node, deep }); } } - if (recursive) { + if (!isCollapsibleStateUpdate(update) && update.recursive) { for (const child of node.children) { - result = this._setNodeCollapseState(child, collapsible, collapsed, true, true) || result; + result = this._setNodeCollapseState(child, update, true) || result; } } @@ -305,7 +327,7 @@ export class IndexTreeModel, TFilterData = voi location = location.slice(0, location.length - 1); if (node.collapsed) { - this._setCollapseState(location, node.collapsible, false); + this._setCollapseState(location, { collapsed: false, recursive: false }); } } }); diff --git a/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts b/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts index 96817cb4bbc..6d660f358e9 100644 --- a/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts +++ b/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts @@ -348,10 +348,27 @@ suite('IndexTreeModel', function () { assert.deepEqual(list.length, 2); model.setCollapsible([0], false); + assert.deepEqual(list.length, 2); + assert.deepEqual(list[0].element, 0); + assert.deepEqual(list[0].collapsible, false); + assert.deepEqual(list[0].collapsed, false); + assert.deepEqual(list[1].element, 10); + assert.deepEqual(list[1].collapsible, false); + assert.deepEqual(list[1].collapsed, false); + + model.setCollapsed([0], true); assert.deepEqual(list.length, 1); assert.deepEqual(list[0].element, 0); assert.deepEqual(list[0].collapsible, false); + assert.deepEqual(list[0].collapsed, true); + + model.setCollapsed([0], false); + assert.deepEqual(list[0].element, 0); + assert.deepEqual(list[0].collapsible, false); assert.deepEqual(list[0].collapsed, false); + assert.deepEqual(list[1].element, 10); + assert.deepEqual(list[1].collapsible, false); + assert.deepEqual(list[1].collapsed, false); model.setCollapsible([0], true); assert.deepEqual(list.length, 2); @@ -361,6 +378,20 @@ suite('IndexTreeModel', function () { assert.deepEqual(list[1].element, 10); assert.deepEqual(list[1].collapsible, false); assert.deepEqual(list[1].collapsed, false); + + model.setCollapsed([0], true); + assert.deepEqual(list.length, 1); + assert.deepEqual(list[0].element, 0); + assert.deepEqual(list[0].collapsible, true); + assert.deepEqual(list[0].collapsed, true); + + model.setCollapsed([0], false); + assert.deepEqual(list[0].element, 0); + assert.deepEqual(list[0].collapsible, true); + assert.deepEqual(list[0].collapsed, false); + assert.deepEqual(list[1].element, 10); + assert.deepEqual(list[1].collapsible, false); + assert.deepEqual(list[1].collapsed, false); }); test('simple filter', function () { -- GitLab