molstar
Version:
A comprehensive macromolecular library.
298 lines • 11.8 kB
JavaScript
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { OrderedSet } from 'immutable';
import { StateTransform } from '../transform';
import { StateTree } from './immutable';
import { shallowEqual } from '../../mol-util/object';
import { arrayEqual } from '../../mol-util/array';
export { TransientTree };
var TransientTree = /** @class */ (function () {
function TransientTree(tree) {
this.tree = tree;
this.transforms = this.tree.transforms;
this.children = this.tree.children;
this.dependencies = this.tree.dependencies;
this.changedNodes = false;
this.changedChildren = false;
this.changedDependencies = false;
this._childMutations = void 0;
this._dependencyMutations = void 0;
this._stateUpdates = void 0;
}
Object.defineProperty(TransientTree.prototype, "childMutations", {
get: function () {
if (this._childMutations)
return this._childMutations;
this._childMutations = new Map();
return this._childMutations;
},
enumerable: false,
configurable: true
});
Object.defineProperty(TransientTree.prototype, "dependencyMutations", {
get: function () {
if (this._dependencyMutations)
return this._dependencyMutations;
this._dependencyMutations = new Map();
return this._dependencyMutations;
},
enumerable: false,
configurable: true
});
TransientTree.prototype.changeNodes = function () {
if (this.changedNodes)
return;
this.changedNodes = true;
this.transforms = this.transforms.asMutable();
};
TransientTree.prototype.changeChildren = function () {
if (this.changedChildren)
return;
this.changedChildren = true;
this.children = this.children.asMutable();
};
TransientTree.prototype.changeDependencies = function () {
if (this.changedDependencies)
return;
this.changedDependencies = true;
this.dependencies = this.dependencies.asMutable();
};
Object.defineProperty(TransientTree.prototype, "root", {
get: function () { return this.transforms.get(StateTransform.RootRef); },
enumerable: false,
configurable: true
});
TransientTree.prototype.asTransient = function () {
return this.asImmutable().asTransient();
};
TransientTree.prototype.addChild = function (parent, child) {
this.changeChildren();
if (this.childMutations.has(parent)) {
this.childMutations.get(parent).add(child);
}
else {
var set = this.children.get(parent).asMutable();
set.add(child);
this.children.set(parent, set);
this.childMutations.set(parent, set);
}
};
TransientTree.prototype.removeChild = function (parent, child) {
this.changeChildren();
if (this.childMutations.has(parent)) {
this.childMutations.get(parent).remove(child);
}
else {
var set = this.children.get(parent).asMutable();
set.remove(child);
this.children.set(parent, set);
this.childMutations.set(parent, set);
}
};
TransientTree.prototype.clearRoot = function () {
var parent = StateTransform.RootRef;
if (this.children.get(parent).size === 0)
return;
this.changeChildren();
var set = OrderedSet();
this.children.set(parent, set);
this.childMutations.set(parent, set);
};
TransientTree.prototype.mutateDependency = function (parent, child, action) {
var set = this.dependencyMutations.get(parent);
if (!set) {
var src = this.dependencies.get(parent);
if (!src && action === 'remove')
return;
this.changeDependencies();
set = src ? src.asMutable() : OrderedSet().asMutable();
this.dependencyMutations.set(parent, set);
this.dependencies.set(parent, set);
}
if (action === 'add') {
set.add(child);
}
else {
set.remove(child);
}
};
TransientTree.prototype.changeParent = function (ref, newParent) {
ensurePresent(this.transforms, ref);
var old = this.transforms.get(ref);
this.removeChild(old.parent, ref);
this.addChild(newParent, ref);
this.changeNodes();
this.transforms.set(ref, StateTransform.withParent(old, newParent));
};
TransientTree.prototype.add = function (transform) {
var ref = transform.ref;
if (this.transforms.has(transform.ref)) {
var node = this.transforms.get(transform.ref);
if (node.parent !== transform.parent)
alreadyPresent(transform.ref);
}
var children = this.children.get(transform.parent);
if (!children)
parentNotPresent(transform.parent);
if (!children.has(transform.ref)) {
this.addChild(transform.parent, transform.ref);
}
if (!this.children.has(transform.ref)) {
if (!this.changedChildren) {
this.changedChildren = true;
this.children = this.children.asMutable();
}
this.children.set(transform.ref, OrderedSet());
}
this.changeNodes();
this.transforms.set(ref, transform);
if (transform.dependsOn) {
for (var _i = 0, _a = transform.dependsOn; _i < _a.length; _i++) {
var d = _a[_i];
this.mutateDependency(d, ref, 'add');
}
}
return this;
};
/** Calls Transform.definition.params.areEqual if available, otherwise uses shallowEqual to check if the params changed */
TransientTree.prototype.setParams = function (ref, params) {
ensurePresent(this.transforms, ref);
var transform = this.transforms.get(ref);
// TODO: should this be here?
if (shallowEqual(transform.params, params)) {
return false;
}
if (!this.changedNodes) {
this.changedNodes = true;
this.transforms = this.transforms.asMutable();
}
this.transforms.set(transform.ref, StateTransform.withParams(transform, params));
return true;
};
/** Calls Transform.definition.params.areEqual if available, otherwise uses shallowEqual to check if the params changed */
TransientTree.prototype.setTags = function (ref, tags) {
ensurePresent(this.transforms, ref);
var transform = this.transforms.get(ref);
var withTags = StateTransform.withParams(transform, tags);
// TODO: should this be here?
if (arrayEqual(transform.tags, withTags.tags)) {
return false;
}
if (!this.changedNodes) {
this.changedNodes = true;
this.transforms = this.transforms.asMutable();
}
this.transforms.set(transform.ref, withTags);
return true;
};
TransientTree.prototype.assignState = function (ref, state) {
ensurePresent(this.transforms, ref);
var old = this.transforms.get(ref);
if (this._stateUpdates && this._stateUpdates.has(ref)) {
StateTransform.assignState(old.state, state);
return old;
}
else {
if (!this._stateUpdates)
this._stateUpdates = new Set();
this._stateUpdates.add(old.ref);
this.changeNodes();
var updated = StateTransform.withState(old, state);
this.transforms.set(ref, updated);
return updated;
}
};
TransientTree.prototype.remove = function (ref) {
var node = this.transforms.get(ref);
if (!node)
return [];
var st = StateTree.subtreePostOrder(this, node);
if (ref === StateTransform.RootRef) {
st.pop();
if (st.length === 0)
return st;
this.clearRoot();
}
else {
if (st.length === 0)
return st;
this.removeChild(node.parent, node.ref);
}
this.changeNodes();
this.changeChildren();
for (var _i = 0, st_1 = st; _i < st_1.length; _i++) {
var n = st_1[_i];
this.transforms.delete(n.ref);
this.children.delete(n.ref);
if (this._childMutations)
this._childMutations.delete(n.ref);
}
var depRemoves = [];
for (var _a = 0, st_2 = st; _a < st_2.length; _a++) {
var n = st_2[_a];
if (n.dependsOn) {
for (var _b = 0, _c = n.dependsOn; _b < _c.length; _b++) {
var d = _c[_b];
if (!this.transforms.has(d))
continue;
this.mutateDependency(d, n.ref, 'remove');
}
}
if (this.dependencies.has(n.ref)) {
var deps = this.dependencies.get(n.ref).toArray();
this.changeDependencies();
this.dependencies.delete(n.ref);
if (this._dependencyMutations)
this._dependencyMutations.delete(n.ref);
for (var _d = 0, deps_1 = deps; _d < deps_1.length; _d++) {
var dep = deps_1[_d];
if (!this.transforms.has(dep))
continue;
for (var _e = 0, _f = this.remove(dep); _e < _f.length; _e++) {
var del = _f[_e];
depRemoves[depRemoves.length] = del;
}
}
}
}
for (var _g = 0, depRemoves_1 = depRemoves; _g < depRemoves_1.length; _g++) {
var dep = depRemoves_1[_g];
st[st.length] = dep;
}
return st;
};
TransientTree.prototype.asImmutable = function () {
if (!this.changedNodes && !this.changedChildren && !this._childMutations)
return this.tree;
if (this._childMutations)
this._childMutations.forEach(fixChildMutations, this.children);
if (this._dependencyMutations)
this._dependencyMutations.forEach(fixDependencyMutations, this.dependencies);
return StateTree.create(this.changedNodes ? this.transforms.asImmutable() : this.transforms, this.changedChildren ? this.children.asImmutable() : this.children, this.changedDependencies ? this.dependencies.asImmutable() : this.dependencies);
};
return TransientTree;
}());
function fixChildMutations(m, k) {
this.set(k, m.asImmutable());
}
function fixDependencyMutations(m, k) {
if (m.size === 0)
this.delete(k);
else
this.set(k, m.asImmutable());
}
function alreadyPresent(ref) {
throw new Error("Transform '" + ref + "' is already present in the tree.");
}
function parentNotPresent(ref) {
throw new Error("Parent '" + ref + "' must be present in the tree.");
}
function ensurePresent(nodes, ref) {
if (!nodes.has(ref)) {
throw new Error("Node '" + ref + "' is not present in the tree.");
}
}
//# sourceMappingURL=transient.js.map