diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 39a7a0a2cd1579290b4fe12f6998c7f72e5f6ece..3ec13bfdcf1ef89655ffde1dc8206a60c4af487f 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -288,15 +288,15 @@ export abstract class AbstractTree implements IDisposable // Tree navigation - getParentElement(location: TRef | null = null): T | null { + getParentElement(location: TRef): T { return this.model.getParentElement(location); } - getFirstElementChild(location: TRef | null = null): T | null { + getFirstElementChild(location: TRef): T | undefined { return this.model.getFirstElementChild(location); } - getLastElementAncestor(location: TRef | null = null): T | null { + getLastElementAncestor(location: TRef): T | undefined { return this.model.getLastElementAncestor(location); } diff --git a/src/vs/base/browser/ui/tree/indexTree.ts b/src/vs/base/browser/ui/tree/indexTree.ts index fa6a3ad5e9ebda5183e1ce99da47cb6a7bfb8196..d8e56d81167bae24518893b9a3f718adc1452938 100644 --- a/src/vs/base/browser/ui/tree/indexTree.ts +++ b/src/vs/base/browser/ui/tree/indexTree.ts @@ -23,6 +23,7 @@ export class IndexTree extends AbstractTree, renderers: ITreeRenderer[], + private rootElement: T, options: IIndexTreeOptions = {} ) { super(container, delegate, renderers, options); @@ -33,6 +34,6 @@ export class IndexTree extends AbstractTree>, options: IIndexTreeOptions): ITreeModel { - return new IndexTreeModel(view, options); + return new IndexTreeModel(view, this.rootElement, options); } } \ No newline at end of file diff --git a/src/vs/base/browser/ui/tree/indexTreeModel.ts b/src/vs/base/browser/ui/tree/indexTreeModel.ts index d57e98846cba4f07d725cd94a654a883a10fb47a..d23626cdc6251a7b075b00f122e8b1a1a0480ca1 100644 --- a/src/vs/base/browser/ui/tree/indexTreeModel.ts +++ b/src/vs/base/browser/ui/tree/indexTreeModel.ts @@ -43,20 +43,9 @@ export interface IIndexTreeModelOptions { filter?: ITreeFilter; } -export class IndexTreeModel implements ITreeModel { - - private root: IMutableTreeNode = { - parent: undefined, - element: undefined!, - children: [], - depth: 0, - collapsible: false, - collapsed: false, - renderNodeCount: 0, - visible: true, - filterData: undefined - }; +export class IndexTreeModel, TFilterData = void> implements ITreeModel { + private root: IMutableTreeNode; private eventBufferer = new EventBufferer(); private _onDidChangeCollapseState = new Emitter>(); @@ -68,9 +57,21 @@ export class IndexTreeModel implements ITreeModel; - constructor(private list: ISpliceable>, options: IIndexTreeModelOptions = {}) { + constructor(private list: ISpliceable>, rootElement: T, options: IIndexTreeModelOptions = {}) { this.collapseByDefault = typeof options.collapseByDefault === 'undefined' ? false : options.collapseByDefault; this.filter = options.filter; + + this.root = { + parent: undefined, + element: rootElement, + children: [], + depth: 0, + collapsible: false, + collapsed: false, + renderNodeCount: 0, + visible: true, + filterData: undefined + }; } splice( @@ -353,7 +354,7 @@ export class IndexTreeModel implements ITreeModel = this.root): IMutableTreeNode { + private getTreeNode(location: number[], node: IMutableTreeNode = this.root): IMutableTreeNode { if (!location || location.length === 0) { return node; } @@ -418,7 +419,7 @@ export class IndexTreeModel implements ITreeModel implements ITreeModel): T | null { + private _getLastElementAncestor(node: ITreeNode): T { if (node.children.length === 0) { return node.element; } diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index fcce8f4613f483fd756209194670b7bbafb7a207..90cedbbda8be6465bf53a45914e4321ab8b66444 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -32,11 +32,11 @@ export class ObjectTree, TFilterData = void> extends children?: ISequence>, onDidCreateNode?: (node: ITreeNode) => void, onDidDeleteNode?: (node: ITreeNode) => void - ): Iterator> { + ): Iterator> { return this.model.setChildren(element, children, onDidCreateNode, onDidDeleteNode); } - protected createModel(view: ISpliceable>, options: IObjectTreeOptions): ITreeModel { + protected createModel(view: ISpliceable>, options: IObjectTreeOptions): ITreeModel { return new ObjectTreeModel(view, options); } } \ No newline at end of file diff --git a/src/vs/base/browser/ui/tree/objectTreeModel.ts b/src/vs/base/browser/ui/tree/objectTreeModel.ts index 0aa4cedeb334b76c90a34273377b4e835a0a71cd..2d3ee5222cdafabf6dfe090a9833b1020eebfd64 100644 --- a/src/vs/base/browser/ui/tree/objectTreeModel.ts +++ b/src/vs/base/browser/ui/tree/objectTreeModel.ts @@ -11,10 +11,10 @@ import { ITreeModel, ITreeNode, ITreeElement } from 'vs/base/browser/ui/tree/tre export interface IObjectTreeModelOptions extends IIndexTreeModelOptions { } -export class ObjectTreeModel, TFilterData = void> implements ITreeModel { +export class ObjectTreeModel, TFilterData extends NonNullable = void> implements ITreeModel { - private model: IndexTreeModel; - private nodes = new Map>(); + private model: IndexTreeModel; + private nodes = new Map>(); readonly onDidChangeCollapseState: Event>; readonly onDidChangeRenderNodeCount: Event>; @@ -22,9 +22,9 @@ export class ObjectTreeModel, TFilterData = void> imp get size(): number { return this.nodes.size; } constructor(list: ISpliceable>, options: IObjectTreeModelOptions = {}) { - this.model = new IndexTreeModel(list, options); - this.onDidChangeCollapseState = this.model.onDidChangeCollapseState; - this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount; + this.model = new IndexTreeModel(list, null, options); + this.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event>; + this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount as Event>; } setChildren( @@ -32,9 +32,9 @@ export class ObjectTreeModel, TFilterData = void> imp children: ISequence> | undefined, onDidCreateNode?: (node: ITreeNode) => void, onDidDeleteNode?: (node: ITreeNode) => void - ): Iterator> { + ): Iterator> { const location = this.getElementLocation(element); - const insertedElements = new Set(); + const insertedElements = new Set(); const _onDidCreateNode = (node: ITreeNode) => { insertedElements.add(node.element); @@ -64,7 +64,7 @@ export class ObjectTreeModel, TFilterData = void> imp ); } - private preserveCollapseState(elements: ISequence> | undefined): ISequence> { + private preserveCollapseState(elements: ISequence> | undefined): ISequence> { const iterator = elements ? getSequenceIterator(elements) : Iterator.empty>(); return Iterator.map(iterator, treeElement => { @@ -91,12 +91,12 @@ export class ObjectTreeModel, TFilterData = void> imp return this.model.getParentElement(location); } - getFirstElementChild(ref: T | null = null): T | null { + getFirstElementChild(ref: T | null = null): T | null | undefined { const location = this.getElementLocation(ref); return this.model.getFirstElementChild(location); } - getLastElementAncestor(ref: T | null = null): T | null { + getLastElementAncestor(ref: T | null = null): T | null | undefined { const location = this.getElementLocation(ref); return this.model.getLastElementAncestor(location); } @@ -129,7 +129,7 @@ export class ObjectTreeModel, TFilterData = void> imp this.model.refilter(); } - getNode(element: T | null = null): ITreeNode { + getNode(element: T | null = null): ITreeNode { const location = this.getElementLocation(element); return this.model.getNode(location); } diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index e60d3794f3e85ad055d992263a77d34dfe1811f2..668386bff57ff0c6fad52ba99934c39350b773c8 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -92,11 +92,11 @@ export interface ITreeModel { getListIndex(location: TRef): number; getNode(location?: TRef): ITreeNode; getNodeLocation(node: ITreeNode): TRef; - getParentNodeLocation(location: TRef): TRef | null; + getParentNodeLocation(location: TRef): TRef; - getParentElement(location: TRef | null): T | null; - getFirstElementChild(location: TRef | null): T | null; - getLastElementAncestor(location: TRef | null): T | null; + getParentElement(location: TRef): T; + getFirstElementChild(location: TRef): T | undefined; + getLastElementAncestor(location: TRef): T | undefined; isCollapsed(location: TRef): boolean; setCollapsed(location: TRef, collapsed: boolean): boolean; 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 07431d166b862a84a9abeab447f531b39215f1d7..25e84a34f4c673763a864a353ec6b0c857cc74d7 100644 --- a/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts +++ b/src/vs/base/test/browser/ui/tree/indexTreeModel.test.ts @@ -25,14 +25,14 @@ suite('IndexTreeModel', function () { test('ctor', () => { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); assert(model); assert.equal(list.length, 0); }); test('insert', () => { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { element: 0 }, @@ -54,7 +54,7 @@ suite('IndexTreeModel', function () { test('deep insert', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -91,7 +91,7 @@ suite('IndexTreeModel', function () { test('deep insert collapsed', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -119,7 +119,7 @@ suite('IndexTreeModel', function () { test('delete', () => { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { element: 0 }, @@ -144,7 +144,7 @@ suite('IndexTreeModel', function () { test('nested delete', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -178,7 +178,7 @@ suite('IndexTreeModel', function () { test('deep delete', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -206,7 +206,7 @@ suite('IndexTreeModel', function () { test('hidden delete', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -231,7 +231,7 @@ suite('IndexTreeModel', function () { test('collapse', () => { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -262,7 +262,7 @@ suite('IndexTreeModel', function () { test('expand', () => { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -302,7 +302,7 @@ suite('IndexTreeModel', function () { test('collapse should recursively adjust visible count', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -341,7 +341,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), -1, { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -375,7 +375,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), -1, { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -398,7 +398,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), -1, { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -437,7 +437,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), 'root', { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -483,7 +483,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), 'root', { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -529,7 +529,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), 'root', { filter }); model.splice([0], 0, Iterator.fromArray([ { @@ -577,7 +577,7 @@ suite('IndexTreeModel', function () { test('simple', function () { const list: ITreeNode[] = []; - const model = new IndexTreeModel(toSpliceable(list)); + const model = new IndexTreeModel(toSpliceable(list), -1); model.splice([0], 0, Iterator.fromArray([ { @@ -607,7 +607,7 @@ suite('IndexTreeModel', function () { } }; - const model = new IndexTreeModel(toSpliceable(list), { filter }); + const model = new IndexTreeModel(toSpliceable(list), -1, { filter }); model.splice([0], 0, Iterator.fromArray([ {