Files
speckle-server/packages/viewer/src/modules/tree/WorldTree.ts
T
Alexandru Popovici de2bce89a5 Alex/verbosity and mouse event (#1275)
* Added a verbose flag in the viewer params. Default is false and it's equivalent to the ERROR level

* Piggybacked the original pointer event into the SelectionEvent
2023-01-02 16:23:52 +02:00

144 lines
3.7 KiB
TypeScript

import TreeModel from 'tree-model'
import { DataTree, DataTreeBuilder } from './DataTree'
import { NodeRenderView } from './NodeRenderView'
import { RenderTree } from './RenderTree'
import Logger from 'js-logger'
export type TreeNode = TreeModel.Node<NodeData>
export type SearchPredicate = (node: TreeNode) => boolean
export interface NodeData {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
raw: { [prop: string]: any }
children: Node[]
atomic: boolean
/**
* Keeps track wether this the root commit object or not.
* TODO: Ask Alex wether this is somehow avoidable.
*/
root: boolean
renderView?: NodeRenderView
}
export class WorldTree {
private static instance: WorldTree
private static renderTreeInstances: { [id: string]: RenderTree } = {}
private readonly supressWarnings = true
private constructor() {
this.tree = new TreeModel()
}
public static getInstance(): WorldTree {
if (!WorldTree.instance) {
WorldTree.instance = new WorldTree()
WorldTree.instance._root = WorldTree.getInstance().parse({
id: 'MOTHERSHIP',
raw: {},
atomic: true,
children: [],
renderView: null
})
}
return WorldTree.instance
}
public static getRenderTree(subtreeId?: string): RenderTree {
if (!WorldTree.getInstance()._root) {
console.error(`WorldTree not initialised`)
return null
}
const id = subtreeId ? subtreeId : WorldTree.getInstance().root.model.id
if (!WorldTree.renderTreeInstances[id]) {
WorldTree.renderTreeInstances[id] = new RenderTree(
WorldTree.getInstance().findId(id)
)
}
return WorldTree.renderTreeInstances[id]
}
public static getDataTree(): DataTree {
return DataTreeBuilder.build(WorldTree.instance._root)
}
private tree: TreeModel
public _root: TreeNode
public get root(): TreeNode {
return this._root
}
public parse(model) {
return this.tree.parse(model)
}
public addSubtree(node: TreeNode) {
Logger.warn(`Adding subtree with id: ${node.model.id}`)
this._root.addChild(node)
}
public addNode(node: TreeNode, parent: TreeNode) {
if (parent === null) {
Logger.error(`Invalid parent node!`)
return
}
parent.addChild(node)
}
public removeNode(node: TreeNode) {
node.drop()
}
public findAll(predicate: SearchPredicate, node?: TreeNode): Array<TreeNode> {
if (!node && !this.supressWarnings) {
Logger.warn(`Root will be used for searching. You might not want that`)
}
return (node ? node : this.root).all(predicate)
}
public findId(id: string, node?: TreeNode) {
if (!node && !this.supressWarnings) {
Logger.warn(`Root will be used for searching. You might not want that`)
}
return (node ? node : this.root).first((_node: TreeNode) => {
return _node.model.id === id
})
}
public getAncestors(node: TreeNode): Array<TreeNode> {
return node.getPath().reverse().slice(1) // We skip the node itself
}
public walk(predicate: SearchPredicate, node?: TreeNode): void {
if (!node && !this.supressWarnings) {
Logger.warn(`Root will be used for searching. You might not want that`)
this._root.walk(predicate)
}
this._root.walk(predicate, node)
}
public purge(subtreeId?: string) {
if (subtreeId) {
delete WorldTree.renderTreeInstances[subtreeId]
this.removeNode(this.findId(subtreeId))
return
}
Object.keys(WorldTree.renderTreeInstances).forEach(
(key) => delete WorldTree.renderTreeInstances[key]
)
this._root.drop()
this._root.children.length = 0
this.tree = new TreeModel()
this._root = WorldTree.getInstance().parse({
id: 'MOTHERSHIP',
raw: {},
atomic: true,
children: []
})
}
}