UNPKG

rhamt-vscode-extension

Version:

RHAMT VSCode extension

135 lines (117 loc) 5.48 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { EventEmitter } from 'vscode'; import { IRhamtNode, IRhamtParentTreeItem, IRhamtTreeItem } from './index'; import { RhamtNode, IRhamtParentNodeInternal } from './RhamtNode'; import { CreatingTreeItem } from './CreatingTreeItem'; import { NotImplementedError } from './errors'; export class RhamtParentNode<T extends IRhamtParentTreeItem = IRhamtParentTreeItem> extends RhamtNode<T> implements IRhamtParentNodeInternal { private _cachedChildren: RhamtNode[] = []; private _creatingNodes: RhamtNode[] = []; private _onNodeCreateEmitter: EventEmitter<IRhamtNode>; private _clearCache: boolean = true; private _loadMoreChildrenTask: Promise<void> | undefined; private _initChildrenTask: Promise<void> | undefined; public constructor(parent: IRhamtParentNodeInternal | undefined, treeItem: T, onNodeCreateEmitter: EventEmitter<IRhamtNode>) { super(parent, treeItem); this._onNodeCreateEmitter = onNodeCreateEmitter; } public async getCachedChildren(): Promise<RhamtNode[]> { if (this._clearCache) { this._initChildrenTask = this.loadMoreChildren(); } if (this._initChildrenTask) { await this._initChildrenTask; } return this._cachedChildren; } public get creatingNodes(): RhamtNode[] { return this._creatingNodes; } public clearCache(): void { this._clearCache = true; } public async createChild(userOptions?: {}): Promise<RhamtNode> { if (this.treeItem.createChild) { let creatingNode: RhamtNode | undefined; try { const newTreeItem: IRhamtTreeItem = await this.treeItem.createChild( this, (label: string): void => { creatingNode = new RhamtNode(this, new CreatingTreeItem(label)); this._creatingNodes.push(creatingNode); //tslint:disable-next-line:no-floating-promises this.treeDataProvider.refresh(this, false); }, userOptions); const newNode: RhamtNode = this.createNewNode(newTreeItem); await this.addNodeToCache(newNode); this._onNodeCreateEmitter.fire(newNode); return newNode; } finally { if (creatingNode) { this._creatingNodes.splice(this._creatingNodes.indexOf(creatingNode), 1); await this.treeDataProvider.refresh(this, false); } } } else { throw new NotImplementedError('createChild', this.treeItem); } } public async addNodeToCache(node: RhamtNode): Promise<void> { let index: number = this._cachedChildren.length; // tslint:disable-next-line:no-increment-decrement for (let i: number = 0; i < this._cachedChildren.length; i++) { if (node.treeItem.label.localeCompare(this._cachedChildren[i].treeItem.label) < 1) { index = i; break; } } this._cachedChildren.splice(index, 0, node); await this.treeDataProvider.refresh(this, false); } public async removeNodeFromCache(node: RhamtNode): Promise<void> { const index: number = this._cachedChildren.indexOf(node); if (index !== -1) { this._cachedChildren.splice(index, 1); await this.treeDataProvider.refresh(this, false); } } public async loadMoreChildren(): Promise<void> { if (this._loadMoreChildrenTask) { await this._loadMoreChildrenTask; } else { this._loadMoreChildrenTask = this.loadMoreChildrenInternal(); try { await this._loadMoreChildrenTask; } finally { this._loadMoreChildrenTask = undefined; } } } private async loadMoreChildrenInternal(): Promise<void> { if (this._clearCache) { this._cachedChildren = []; } const sortCallback: (n1: IRhamtNode, n2: IRhamtNode) => number = this.treeItem.compareChildren ? this.treeItem.compareChildren : (n1: RhamtNode, n2: RhamtNode): number => n1.treeItem.label.localeCompare(n2.treeItem.label); const newTreeItems: IRhamtTreeItem[] = await this.treeItem.loadMoreChildren(this, this._clearCache); this._cachedChildren = this._cachedChildren .concat(newTreeItems.map((t: IRhamtTreeItem) => this.createNewNode(t))) .sort(sortCallback); this._clearCache = false; } private createNewNode(treeItem: IRhamtTreeItem): RhamtNode { const parentTreeItem: IRhamtParentTreeItem = <IRhamtParentTreeItem>treeItem; // tslint:disable-next-line:strict-boolean-expressions if (parentTreeItem.loadMoreChildren) { return new RhamtParentNode(this, parentTreeItem, this._onNodeCreateEmitter); } else { return new RhamtNode(this, treeItem); } } }