UNPKG

@jbrowse/core

Version:

JBrowse 2 core libraries used by plugins

116 lines (115 loc) 3.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class SceneGraph { constructor(name, left, top, width, height, data) { this.name = name; this.left = left; this.top = top; this.width = width; this.height = height; this.data = data; this.children = new Map(); this.absoluteCache = { dirty: true }; } addChild(nameOrSceneGraph, left, top, width, height, data) { const child = nameOrSceneGraph instanceof SceneGraph ? nameOrSceneGraph : new SceneGraph(nameOrSceneGraph, left, top, width, height, data); if (!(child instanceof SceneGraph)) { throw new TypeError('argument to addChild must be an array or a SceneGraph'); } if (this.children.has(child.name)) { throw new Error(`child named "${child.name}" already exists`); } child.parent = this; const { left: childLeft, right: childRight, top: childTop, bottom: childBottom, } = child.absolute; if (childLeft !== undefined && childRight !== undefined && childTop !== undefined && childBottom !== undefined) { this.expand(childLeft, childRight, childTop, childBottom); this.children.set(child.name, child); } return child; } getSubRecord(name) { return this.children.get(name); } expand(newLeft, newRight, newTop, newBottom) { const { left, right, top, bottom } = this.absolute; if (left !== undefined && newLeft < left) { const diff = left - newLeft; this.width += diff; this.left -= diff; } if (right !== undefined && newRight > right) { this.width += newRight - right; } if (top !== undefined && newTop < top) { const diff = top - newTop; this.height += diff; this.top -= diff; } if (bottom !== undefined && newBottom > bottom) { this.height += newBottom - bottom; } if (this.parent) { this.parent.expand(newLeft, newRight, newTop, newBottom); } this.absoluteCache.dirty = true; } get bottom() { return this.top + this.height; } get right() { return this.left + this.width; } walkParents(callback) { if (this.parent) { callback(this.parent); this.parent.walkParents(callback); } } walkChildren(callback) { for (const sub of this.children.values()) { callback(sub); sub.walkChildren(callback); } } get absolute() { if (this.absoluteCache.dirty) { let xOffset = 0; let yOffset = 0; this.walkParents((node) => { xOffset += node.left; yOffset += node.top; }); this.absoluteCache = { dirty: false, left: this.left + xOffset, right: this.right + xOffset, top: this.top + yOffset, bottom: this.bottom + yOffset, width: this.width, height: this.height, }; } return this.absoluteCache; } move(x, y) { this.left += x; this.top += y; this.absoluteCache.dirty = true; this.walkChildren(c => { c.absoluteCache.dirty = true; }); const { left, right, top, bottom } = this.absolute; if (left !== undefined && right !== undefined && top !== undefined && bottom !== undefined) { this.expand(left, right, top, bottom); } } } exports.default = SceneGraph;