Skip to content

Commit 60fa1de

Browse files
committed
wip: more tree node mappers
1 parent 435ce2e commit 60fa1de

1 file changed

Lines changed: 55 additions & 21 deletions

File tree

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

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,32 +67,41 @@ interface IDataTreeListTemplateData<T> {
6767
templateData: T;
6868
}
6969

70-
class NodeMapper<TInput, T, TFilterData> {
70+
abstract class WeakMapper<T extends object, R> {
7171

72-
private map = new WeakMap<ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>, ITreeNode<TInput | T, TFilterData>>();
72+
private _map = new WeakMap<T, R>();
7373

74-
mapNode(node: ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>): ITreeNode<TInput | T, TFilterData> {
74+
map(obj: T): R {
7575
const that = this;
76-
let result = this.map.get(node);
76+
let result = this._map.get(obj);
7777

7878
if (!result) {
79-
result = new Proxy(node, {
79+
result = new Proxy(obj, {
8080
get(obj, prop) {
81-
if (prop === 'element') {
82-
return node.element!.element;
83-
} else if (prop === 'children') {
84-
return node.children.map(child => that.mapNode(child));
85-
}
86-
87-
return (obj as any)[prop];
81+
return that.getProp(obj, prop);
8882
}
89-
}) as unknown as ITreeNode<TInput | T, TFilterData>;
83+
}) as unknown as R;
9084

91-
this.map.set(node, result);
85+
this._map.set(obj, result);
9286
}
9387

9488
return result;
9589
}
90+
91+
protected abstract getProp(obj: T, prop: string | number | symbol): any;
92+
}
93+
94+
class AsyncDataTreeNodeMapper<TInput, T, TFilterData> extends WeakMapper<ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>, ITreeNode<TInput | T, TFilterData>> {
95+
96+
protected getProp(node: ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>, prop: string | number | symbol): any {
97+
if (prop === 'element') {
98+
return node.element!.element;
99+
} else if (prop === 'children') {
100+
return node.children.map(child => this.map(child));
101+
}
102+
103+
return (node as any)[prop];
104+
}
96105
}
97106

98107
class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRenderer<IAsyncDataTreeNode<TInput, T>, TFilterData, IDataTreeListTemplateData<TTemplateData>> {
@@ -103,7 +112,7 @@ class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRe
103112

104113
constructor(
105114
protected renderer: ITreeRenderer<T, TFilterData, TTemplateData>,
106-
protected nodeMapper: NodeMapper<TInput, T, TFilterData>,
115+
protected nodeMapper: AsyncDataTreeNodeMapper<TInput, T, TFilterData>,
107116
readonly onDidChangeTwistieState: Event<IAsyncDataTreeNode<TInput, T>>
108117
) {
109118
this.templateId = renderer.templateId;
@@ -115,7 +124,7 @@ class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRe
115124
}
116125

117126
renderElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, height: number | undefined): void {
118-
this.renderer.renderElement(this.nodeMapper.mapNode(node) as ITreeNode<T, TFilterData>, index, templateData.templateData, height);
127+
this.renderer.renderElement(this.nodeMapper.map(node) as ITreeNode<T, TFilterData>, index, templateData.templateData, height);
119128
}
120129

121130
renderTwistie(element: IAsyncDataTreeNode<TInput, T>, twistieElement: HTMLElement): boolean {
@@ -125,7 +134,7 @@ class DataTreeRenderer<TInput, T, TFilterData, TTemplateData> implements ITreeRe
125134

126135
disposeElement(node: ITreeNode<IAsyncDataTreeNode<TInput, T>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, height: number | undefined): void {
127136
if (this.renderer.disposeElement) {
128-
this.renderer.disposeElement(this.nodeMapper.mapNode(node) as ITreeNode<T, TFilterData>, index, templateData.templateData, height);
137+
this.renderer.disposeElement(this.nodeMapper.map(node) as ITreeNode<T, TFilterData>, index, templateData.templateData, height);
129138
}
130139
}
131140

@@ -320,7 +329,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
320329
private readonly _onDidRender = new Emitter<void>();
321330
protected readonly _onDidChangeNodeSlowState = new Emitter<IAsyncDataTreeNode<TInput, T>>();
322331

323-
protected readonly nodeMapper = new NodeMapper<TInput, T, TFilterData>();
332+
protected readonly nodeMapper = new AsyncDataTreeNodeMapper<TInput, T, TFilterData>();
324333

325334
protected readonly disposables: IDisposable[] = [];
326335

@@ -536,7 +545,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
536545
getNode(element: TInput | T = this.root.element): ITreeNode<TInput | T, TFilterData> {
537546
const dataNode = this.getDataNode(element);
538547
const node = this.tree.getNode(dataNode === this.root ? null : dataNode);
539-
return this.nodeMapper.mapNode(node);
548+
return this.nodeMapper.map(node);
540549
}
541550

542551
collapse(element: T, recursive: boolean = false): boolean {
@@ -945,12 +954,37 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
945954
}
946955
}
947956

957+
class CompressibleAsyncDataTreeNodeMapper<TInput, T, TFilterData> extends WeakMapper<ITreeNode<ICompressedTreeNode<IAsyncDataTreeNode<TInput, T> | null>, TFilterData>, ITreeNode<ICompressedTreeNode<TInput | T>, TFilterData>> {
958+
959+
constructor(private nodeMapper: AsyncDataTreeNodeMapper<TInput, T, TFilterData>) {
960+
super();
961+
}
962+
963+
protected getProp(node: ITreeNode<ICompressedTreeNode<IAsyncDataTreeNode<TInput, T> | null>, TFilterData>, prop: string | number | Symbol): any {
964+
if (prop === 'element') {
965+
return node.element.element;
966+
} else if (prop === 'children') {
967+
return node.children.map(child => this.map(child));
968+
}
969+
970+
return (node as any)[prop];
971+
}
972+
}
973+
948974
class CompressibleDataTreeRenderer<TInput, T, TFilterData, TTemplateData>
949975
extends DataTreeRenderer<TInput, T, TFilterData, TTemplateData>
950976
implements ICompressibleTreeRenderer<IAsyncDataTreeNode<TInput, T>, TFilterData, IDataTreeListTemplateData<TTemplateData>>
951977
{
978+
constructor(
979+
protected renderer: ICompressibleTreeRenderer<T, TFilterData, TTemplateData>,
980+
nodeMapper: AsyncDataTreeNodeMapper<TInput, T, TFilterData>,
981+
onDidChangeTwistieState: Event<IAsyncDataTreeNode<TInput, T>>
982+
) {
983+
super(renderer, nodeMapper, onDidChangeTwistieState);
984+
}
985+
952986
renderCompressedElements(node: ITreeNode<ICompressedTreeNode<IAsyncDataTreeNode<TInput, T>>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, height: number | undefined): void {
953-
this.renderer.renderElement(this.nodeMapper.mapNode(node) as ITreeNode<T, TFilterData>, index, templateData.templateData, height);
987+
this.renderer.renderCompressedElements(this.nodeMapper.map(node), index, templateData.templateData, height);
954988
}
955989
}
956990

@@ -971,7 +1005,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
9711005
user: string,
9721006
container: HTMLElement,
9731007
delegate: IListVirtualDelegate<T>,
974-
renderers: ITreeRenderer<T, TFilterData, any>[],
1008+
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
9751009
options: IAsyncDataTreeOptions<T, TFilterData>
9761010
): ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData> {
9771011
const objectTreeDelegate = new ComposedTreeDelegate<TInput | T, IAsyncDataTreeNode<TInput, T>>(delegate);

0 commit comments

Comments
 (0)