@21epub/epub-thirdparty
Version:
epub-thirdparty
162 lines (161 loc) • 6.74 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IndexTreeModel } from './indexTreeModel.js';
import { TreeError } from './tree.js';
import { Iterable } from '../../../common/iterator.js';
export class ObjectTreeModel {
constructor(user, list, options = {}) {
this.user = user;
this.rootRef = null;
this.nodes = new Map();
this.nodesByIdentity = new Map();
this.model = new IndexTreeModel(user, list, null, options);
this.onDidSplice = this.model.onDidSplice;
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState;
this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount;
if (options.sorter) {
this.sorter = {
compare(a, b) {
return options.sorter.compare(a.element, b.element);
}
};
}
this.identityProvider = options.identityProvider;
}
setChildren(element, children = Iterable.empty(), options = {}) {
const location = this.getElementLocation(element);
this._setChildren(location, this.preserveCollapseState(children), options);
}
_setChildren(location, children = Iterable.empty(), options) {
const insertedElements = new Set();
const insertedElementIds = new Set();
const onDidCreateNode = (node) => {
var _a;
if (node.element === null) {
return;
}
const tnode = node;
insertedElements.add(tnode.element);
this.nodes.set(tnode.element, tnode);
if (this.identityProvider) {
const id = this.identityProvider.getId(tnode.element).toString();
insertedElementIds.add(id);
this.nodesByIdentity.set(id, tnode);
}
(_a = options.onDidCreateNode) === null || _a === void 0 ? void 0 : _a.call(options, tnode);
};
const onDidDeleteNode = (node) => {
var _a;
if (node.element === null) {
return;
}
const tnode = node;
if (!insertedElements.has(tnode.element)) {
this.nodes.delete(tnode.element);
}
if (this.identityProvider) {
const id = this.identityProvider.getId(tnode.element).toString();
if (!insertedElementIds.has(id)) {
this.nodesByIdentity.delete(id);
}
}
(_a = options.onDidDeleteNode) === null || _a === void 0 ? void 0 : _a.call(options, tnode);
};
this.model.splice([...location, 0], Number.MAX_VALUE, children, Object.assign(Object.assign({}, options), { onDidCreateNode, onDidDeleteNode }));
}
preserveCollapseState(elements = Iterable.empty()) {
if (this.sorter) {
elements = [...elements].sort(this.sorter.compare.bind(this.sorter));
}
return Iterable.map(elements, treeElement => {
let node = this.nodes.get(treeElement.element);
if (!node && this.identityProvider) {
const id = this.identityProvider.getId(treeElement.element).toString();
node = this.nodesByIdentity.get(id);
}
if (!node) {
return Object.assign(Object.assign({}, treeElement), { children: this.preserveCollapseState(treeElement.children) });
}
const collapsible = typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : node.collapsible;
const collapsed = typeof treeElement.collapsed !== 'undefined' ? treeElement.collapsed : node.collapsed;
return Object.assign(Object.assign({}, treeElement), { collapsible,
collapsed, children: this.preserveCollapseState(treeElement.children) });
});
}
rerender(element) {
const location = this.getElementLocation(element);
this.model.rerender(location);
}
has(element) {
return this.nodes.has(element);
}
getListIndex(element) {
const location = this.getElementLocation(element);
return this.model.getListIndex(location);
}
getListRenderCount(element) {
const location = this.getElementLocation(element);
return this.model.getListRenderCount(location);
}
isCollapsible(element) {
const location = this.getElementLocation(element);
return this.model.isCollapsible(location);
}
setCollapsible(element, collapsible) {
const location = this.getElementLocation(element);
return this.model.setCollapsible(location, collapsible);
}
isCollapsed(element) {
const location = this.getElementLocation(element);
return this.model.isCollapsed(location);
}
setCollapsed(element, collapsed, recursive) {
const location = this.getElementLocation(element);
return this.model.setCollapsed(location, collapsed, recursive);
}
expandTo(element) {
const location = this.getElementLocation(element);
this.model.expandTo(location);
}
refilter() {
this.model.refilter();
}
getNode(element = null) {
if (element === null) {
return this.model.getNode(this.model.rootRef);
}
const node = this.nodes.get(element);
if (!node) {
throw new TreeError(this.user, `Tree element not found: ${element}`);
}
return node;
}
getNodeLocation(node) {
return node.element;
}
getParentNodeLocation(element) {
if (element === null) {
throw new TreeError(this.user, `Invalid getParentNodeLocation call`);
}
const node = this.nodes.get(element);
if (!node) {
throw new TreeError(this.user, `Tree element not found: ${element}`);
}
const location = this.model.getNodeLocation(node);
const parentLocation = this.model.getParentNodeLocation(location);
const parent = this.model.getNode(parentLocation);
return parent.element;
}
getElementLocation(element) {
if (element === null) {
return [];
}
const node = this.nodes.get(element);
if (!node) {
throw new TreeError(this.user, `Tree element not found: ${element}`);
}
return this.model.getNodeLocation(node);
}
}