Skip to content

Commit a1a8636

Browse files
authored
object tree: preverve collapse state by id (microsoft#74462)
2 parents 6a05457 + 3ae0764 commit a1a8636

2 files changed

Lines changed: 32 additions & 8 deletions

File tree

src/vs/base/browser/ui/tree/objectTreeModel.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import { Iterator, ISequence, getSequenceIterator } from 'vs/base/common/iterato
88
import { IndexTreeModel, IIndexTreeModelOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
99
import { Event } from 'vs/base/common/event';
1010
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent } from 'vs/base/browser/ui/tree/tree';
11+
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
1112

1213
export interface IObjectTreeModelOptions<T, TFilterData> extends IIndexTreeModelOptions<T, TFilterData> {
1314
readonly sorter?: ITreeSorter<T>;
15+
readonly identityProvider?: IIdentityProvider<T>;
1416
}
1517

1618
export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends NonNullable<any> = void> implements ITreeModel<T | null, TFilterData, T | null> {
@@ -19,6 +21,8 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
1921

2022
private model: IndexTreeModel<T | null, TFilterData>;
2123
private nodes = new Map<T | null, ITreeNode<T, TFilterData>>();
24+
private readonly nodesByIdentity = new Map<string, ITreeNode<T, TFilterData>>();
25+
private readonly identityProvider?: IIdentityProvider<T>;
2226
private sorter?: ITreeSorter<{ element: T; }>;
2327

2428
readonly onDidSplice: Event<ITreeModelSpliceEvent<T | null, TFilterData>>;
@@ -40,6 +44,8 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
4044
}
4145
};
4246
}
47+
48+
this.identityProvider = options.identityProvider;
4349
}
4450

4551
setChildren(
@@ -59,11 +65,18 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
5965
onDidDeleteNode?: (node: ITreeNode<T, TFilterData>) => void
6066
): Iterator<ITreeElement<T | null>> {
6167
const insertedElements = new Set<T | null>();
68+
const insertedElementIds = new Set<string>();
6269

6370
const _onDidCreateNode = (node: ITreeNode<T, TFilterData>) => {
6471
insertedElements.add(node.element);
6572
this.nodes.set(node.element, node);
6673

74+
if (this.identityProvider) {
75+
const id = this.identityProvider.getId(node.element).toString();
76+
insertedElementIds.add(id);
77+
this.nodesByIdentity.set(id, node);
78+
}
79+
6780
if (onDidCreateNode) {
6881
onDidCreateNode(node);
6982
}
@@ -74,18 +87,27 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
7487
this.nodes.delete(node.element);
7588
}
7689

90+
if (this.identityProvider) {
91+
const id = this.identityProvider.getId(node.element).toString();
92+
if (!insertedElementIds.has(id)) {
93+
this.nodesByIdentity.delete(id);
94+
}
95+
}
96+
7797
if (onDidDeleteNode) {
7898
onDidDeleteNode(node);
7999
}
80100
};
81101

82-
return this.model.splice(
102+
const result = this.model.splice(
83103
[...location, 0],
84104
Number.MAX_VALUE,
85105
children,
86106
_onDidCreateNode,
87107
_onDidDeleteNode
88108
);
109+
110+
return result;
89111
}
90112

91113
private preserveCollapseState(elements: ISequence<ITreeElement<T>> | undefined): ISequence<ITreeElement<T>> {
@@ -96,7 +118,12 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
96118
}
97119

98120
return Iterator.map(iterator, treeElement => {
99-
const node = this.nodes.get(treeElement.element);
121+
let node = this.nodes.get(treeElement.element);
122+
123+
if (!node && this.identityProvider) {
124+
const id = this.identityProvider.getId(treeElement.element).toString();
125+
node = this.nodesByIdentity.get(id);
126+
}
100127

101128
if (!node) {
102129
return {

src/vs/workbench/contrib/preferences/browser/tocTree.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,12 @@ export function createTOCIterator(model: TOCTreeModel | SettingsTreeGroupElement
141141
const groupChildren = <SettingsTreeGroupElement[]>model.children.filter(c => c instanceof SettingsTreeGroupElement);
142142
const groupsIt = Iterator.fromArray(groupChildren);
143143

144-
145144
return Iterator.map(groupsIt, g => {
146-
let nodeExists = true;
147-
try { tree.getNode(g); } catch (e) { nodeExists = false; }
148-
149145
const hasGroupChildren = g.children.some(c => c instanceof SettingsTreeGroupElement);
150146

151147
return {
152148
element: g,
153-
collapsed: nodeExists ? undefined : true,
149+
collapsed: undefined,
154150
collapsible: hasGroupChildren,
155151
children: g instanceof SettingsTreeGroupElement ?
156152
createTOCIterator(g, tree) :
@@ -203,7 +199,8 @@ export class TOCTree extends ObjectTree<SettingsTreeGroupElement> {
203199
}
204200
},
205201
styleController: new DefaultStyleController(DOM.createStyleSheet(container), treeClass),
206-
accessibilityProvider: instantiationService.createInstance(SettingsAccessibilityProvider)
202+
accessibilityProvider: instantiationService.createInstance(SettingsAccessibilityProvider),
203+
collapseByDefault: true
207204
};
208205

209206
super(container,

0 commit comments

Comments
 (0)