molstar
Version:
A comprehensive macromolecular library.
173 lines • 7.76 kB
JavaScript
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { __assign, __extends } from "tslib";
import { StatefulPluginComponent } from '../../component';
import { arrayRemoveAtInPlace } from '../../../mol-util/array';
import { StructureElement } from '../../../mol-model/structure';
import { Loci } from '../../../mol-model/loci';
import { lociLabel } from '../../../mol-theme/label';
import { PluginStateObject } from '../../objects';
import { StateSelection } from '../../../mol-state';
import { Vec3 } from '../../../mol-math/linear-algebra';
import { Sphere3D } from '../../../mol-math/geometry';
var HISTORY_CAPACITY = 8;
var StructureFocusManager = /** @class */ (function (_super) {
__extends(StructureFocusManager, _super);
function StructureFocusManager(plugin) {
var _this = _super.call(this, { history: [] }) || this;
_this.plugin = plugin;
_this.events = {
historyUpdated: _this.ev()
};
_this.behaviors = {
current: _this.ev.behavior(void 0)
};
plugin.state.data.events.object.removed.subscribe(function (_a) {
var _b;
var _c;
var obj = _a.obj;
if (!PluginStateObject.Molecule.Structure.is(obj))
return;
if (((_c = _this.current) === null || _c === void 0 ? void 0 : _c.loci.structure) === obj.data) {
_this.clear();
}
var keep = [];
for (var _i = 0, _d = _this.history; _i < _d.length; _i++) {
var e = _d[_i];
if (e.loci.structure === obj.data)
keep.push(e);
}
if (keep.length !== _this.history.length) {
_this.history.length = 0;
(_b = _this.history).push.apply(_b, keep);
_this.events.historyUpdated.next(void 0);
}
});
var sphere = Sphere3D();
plugin.state.data.events.object.updated.subscribe(function (_a) {
var _b;
var oldData = _a.oldData, obj = _a.obj, action = _a.action;
if (!PluginStateObject.Molecule.Structure.is(obj))
return;
// structure NOT changed, keep everything as is; fixes #123
if (oldData === obj.data)
return;
// structure changed (e.g. coordinates), try to remap and re-focus
if (action === 'in-place') {
var current = _this.state.current;
var structure = obj.data;
if (current && current.loci.structure === oldData) {
var loci = StructureElement.Loci.remap(current.loci, structure);
_this.state.current = __assign(__assign({}, current), { loci: loci });
_this.behaviors.current.next(_this.state.current);
Loci.getBoundingSphere(loci, sphere);
var camera = (_b = _this.plugin.canvas3d) === null || _b === void 0 ? void 0 : _b.camera;
var d = camera.getTargetDistance(sphere.radius + 4); // default extraRadius
if (Vec3.distance(camera.target, sphere.center) > sphere.radius ||
d > camera.viewport.height / camera.zoom) {
_this.plugin.managers.camera.focusSphere(sphere, { durationMs: 0 });
}
}
// TODO remap history as well
}
});
return _this;
}
Object.defineProperty(StructureFocusManager.prototype, "current", {
get: function () { return this.state.current; },
enumerable: false,
configurable: true
});
Object.defineProperty(StructureFocusManager.prototype, "history", {
get: function () { return this.state.history; },
enumerable: false,
configurable: true
});
StructureFocusManager.prototype.tryAddHistory = function (entry) {
if (StructureElement.Loci.isEmpty(entry.loci))
return;
var idx = 0, existingEntry = void 0;
for (var _i = 0, _a = this.state.history; _i < _a.length; _i++) {
var e = _a[_i];
if (StructureElement.Loci.areEqual(e.loci, entry.loci)) {
existingEntry = e;
break;
}
idx++;
}
if (existingEntry) {
// move to top, use new
arrayRemoveAtInPlace(this.state.history, idx);
this.state.history.unshift(entry);
this.events.historyUpdated.next(void 0);
return;
}
this.state.history.unshift(entry);
if (this.state.history.length > HISTORY_CAPACITY)
this.state.history.pop();
this.events.historyUpdated.next(void 0);
};
StructureFocusManager.prototype.set = function (entry) {
this.tryAddHistory(entry);
if (!this.state.current || !StructureElement.Loci.areEqual(this.state.current.loci, entry.loci)) {
this.state.current = entry;
this.behaviors.current.next(entry);
}
};
StructureFocusManager.prototype.setFromLoci = function (anyLoci) {
var loci = Loci.normalize(anyLoci);
if (!StructureElement.Loci.is(loci) || StructureElement.Loci.isEmpty(loci)) {
this.clear();
return;
}
this.set({ loci: loci, label: lociLabel(loci, { reverse: true, hidePrefix: true, htmlStyling: false }) });
};
StructureFocusManager.prototype.addFromLoci = function (anyLoci) {
var union = this.state.current && StructureElement.Loci.is(anyLoci) && anyLoci.structure === this.state.current.loci.structure
? StructureElement.Loci.union(anyLoci, this.state.current.loci)
: anyLoci;
this.setFromLoci(union);
};
StructureFocusManager.prototype.clear = function () {
if (this.state.current) {
this.state.current = undefined;
this.behaviors.current.next(void 0);
}
};
StructureFocusManager.prototype.getSnapshot = function () {
if (!this.current)
return {};
var node = this.plugin.helpers.substructureParent.get(this.current.loci.structure);
var ref = node === null || node === void 0 ? void 0 : node.transform.ref;
if (!ref)
return {};
return {
current: {
label: this.current.label,
ref: ref,
bundle: StructureElement.Bundle.fromLoci(this.current.loci),
category: this.current.category
}
};
};
StructureFocusManager.prototype.setSnapshot = function (snapshot) {
var _a, _b;
if (!snapshot.current) {
this.clear();
return;
}
var _c = snapshot.current, label = _c.label, ref = _c.ref, bundle = _c.bundle, category = _c.category;
var structure = (_b = (_a = this.plugin.state.data.select(StateSelection.Generators.byRef(ref))[0]) === null || _a === void 0 ? void 0 : _a.obj) === null || _b === void 0 ? void 0 : _b.data;
if (!structure)
return;
var loci = StructureElement.Bundle.toLoci(bundle, structure);
this.set({ label: label, loci: loci, category: category });
};
return StructureFocusManager;
}(StatefulPluginComponent));
export { StructureFocusManager };
//# sourceMappingURL=focus.js.map