molstar
Version:
A comprehensive macromolecular library.
324 lines • 21.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VolumeSourceControls = exports.VolumeStreamingControls = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
var hierarchy_1 = require("../../mol-plugin-state/manager/structure/hierarchy");
var hierarchy_2 = require("../../mol-plugin-state/manager/volume/hierarchy");
var representation_1 = require("../../mol-plugin/behavior/dynamic/representation");
var behavior_1 = require("../../mol-plugin/behavior/dynamic/volume-streaming/behavior");
var transformers_1 = require("../../mol-plugin/behavior/dynamic/volume-streaming/transformers");
var mol_state_1 = require("../../mol-state");
var base_1 = require("../base");
var action_menu_1 = require("../controls/action-menu");
var common_1 = require("../controls/common");
var apply_action_1 = require("../state/apply-action");
var update_transform_1 = require("../state/update-transform");
var help_1 = require("../viewport/help");
var commands_1 = require("../../mol-plugin/commands");
var icons_1 = require("../controls/icons");
var transforms_1 = require("../../mol-plugin-state/transforms");
var volume_representation_params_1 = require("../../mol-plugin-state/helpers/volume-representation-params");
var VolumeStreamingControls = /** @class */ (function (_super) {
(0, tslib_1.__extends)(VolumeStreamingControls, _super);
function VolumeStreamingControls() {
return _super !== null && _super.apply(this, arguments) || this;
}
VolumeStreamingControls.prototype.defaultState = function () {
return {
header: 'Volume Streaming',
isCollapsed: false,
isBusy: false,
isHidden: true,
brand: { accent: 'cyan', svg: icons_1.BlurOnSvg }
};
};
VolumeStreamingControls.prototype.componentDidMount = function () {
var _this = this;
// TODO: do not hide this but instead show some help text??
this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, function () {
_this.setState({
isHidden: !_this.canEnable(),
description: hierarchy_1.StructureHierarchyManager.getSelectedStructuresDescription(_this.plugin)
});
});
this.subscribe(this.plugin.state.events.cell.stateUpdated, function (e) {
if (mol_state_1.StateTransform.hasTag(e.cell.transform, behavior_1.VolumeStreaming.RootTag))
_this.forceUpdate();
});
this.subscribe(this.plugin.behaviors.state.isBusy, function (v) {
_this.setState({ isBusy: v });
});
};
Object.defineProperty(VolumeStreamingControls.prototype, "pivot", {
get: function () {
return this.plugin.managers.structure.hierarchy.selection.structures[0];
},
enumerable: false,
configurable: true
});
VolumeStreamingControls.prototype.canEnable = function () {
var _a, _b;
var selection = this.plugin.managers.structure.hierarchy.selection;
if (selection.structures.length !== 1)
return false;
var pivot = this.pivot.cell;
if (!pivot.obj)
return false;
return !!((_b = (_a = transformers_1.InitVolumeStreaming.definition).isApplicable) === null || _b === void 0 ? void 0 : _b.call(_a, pivot.obj, pivot.transform, this.plugin));
};
VolumeStreamingControls.prototype.renderEnable = function () {
var _a;
var pivot = this.pivot;
if (!pivot.cell.parent)
return null;
var root = mol_state_1.StateSelection.findTagInSubtree(pivot.cell.parent.tree, this.pivot.cell.transform.ref, behavior_1.VolumeStreaming.RootTag);
var rootCell = root && pivot.cell.parent.cells.get(root);
var simpleApply = rootCell && rootCell.status === 'error'
? { header: 'Error enabling', icon: icons_1.ErrorSvg, title: rootCell.errorText }
: rootCell && ((_a = rootCell.obj) === null || _a === void 0 ? void 0 : _a.data.entries.length) === 0
? { header: 'Error enabling', icon: icons_1.ErrorSvg, title: 'No entry for streaming found' }
: { header: 'Enable', icon: icons_1.CheckSvg, title: 'Enable' };
return (0, jsx_runtime_1.jsx)(apply_action_1.ApplyActionControl, { state: pivot.cell.parent, action: transformers_1.InitVolumeStreaming, initiallyCollapsed: true, nodeRef: pivot.cell.transform.ref, simpleApply: simpleApply }, void 0);
};
VolumeStreamingControls.prototype.renderParams = function () {
var _a, _b, _c, _d, _e;
var pivot = this.pivot;
if (!pivot.cell.parent)
return null;
var bindings = ((_b = (_a = pivot.volumeStreaming) === null || _a === void 0 ? void 0 : _a.cell.transform.params) === null || _b === void 0 ? void 0 : _b.entry.params.view.name) === 'selection-box' && ((_e = (_d = (_c = this.plugin.state.behaviors.cells.get(representation_1.FocusLoci.id)) === null || _c === void 0 ? void 0 : _c.params) === null || _d === void 0 ? void 0 : _d.values) === null || _e === void 0 ? void 0 : _e.bindings);
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(update_transform_1.UpdateTransformControl, { state: pivot.cell.parent, transform: pivot.volumeStreaming.cell.transform, customHeader: 'none', noMargin: true }, void 0), bindings && (0, jsx_runtime_1.jsx)(common_1.ExpandGroup, (0, tslib_1.__assign)({ header: 'Controls Help' }, { children: (0, jsx_runtime_1.jsx)(help_1.BindingsHelp, { bindings: bindings }, void 0) }), void 0)] }, void 0);
};
VolumeStreamingControls.prototype.renderControls = function () {
var pivot = this.pivot;
if (!pivot)
return null;
if (!pivot.volumeStreaming)
return this.renderEnable();
return this.renderParams();
};
return VolumeStreamingControls;
}(base_1.CollapsableControls));
exports.VolumeStreamingControls = VolumeStreamingControls;
var VolumeSourceControls = /** @class */ (function (_super) {
(0, tslib_1.__extends)(VolumeSourceControls, _super);
function VolumeSourceControls() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.item = function (ref) {
var _a;
var selected = _this.plugin.managers.volume.hierarchy.selection;
var label = ((_a = ref.cell.obj) === null || _a === void 0 ? void 0 : _a.label) || 'Volume';
var item = {
kind: 'item',
label: (ref.kind === 'lazy-volume' ? 'Load ' : '') + (label || ref.kind),
selected: selected === ref,
value: ref
};
return item;
};
_this.selectCurrent = function (item) {
_this.toggleHierarchy();
if (!item)
return;
var current = item.value;
if (current.kind === 'volume') {
_this.plugin.managers.volume.hierarchy.setCurrent(current);
}
else {
_this.lazyLoad(current.cell);
}
};
_this.selectAdd = function (item) {
if (!item)
return;
_this.setState({ show: void 0 });
item.value();
};
_this.toggleHierarchy = function () { return _this.setState({ show: _this.state.show !== 'hierarchy' ? 'hierarchy' : void 0 }); };
_this.toggleAddRepr = function () { return _this.setState({ show: _this.state.show !== 'add-repr' ? 'add-repr' : void 0 }); };
return _this;
}
VolumeSourceControls.prototype.defaultState = function () {
return {
header: 'Volume',
isCollapsed: false,
isBusy: false,
isHidden: true,
brand: { accent: 'purple', svg: icons_1.BlurOnSvg }
};
};
VolumeSourceControls.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.managers.volume.hierarchy.behaviors.selection, function (sel) {
_this.setState({ isHidden: sel.hierarchy.volumes.length === 0 && sel.hierarchy.lazyVolumes.length === 0 });
});
this.subscribe(this.plugin.behaviors.state.isBusy, function (v) {
_this.setState({ isBusy: v });
});
};
Object.defineProperty(VolumeSourceControls.prototype, "hierarchyItems", {
get: function () {
var mng = this.plugin.managers.volume.hierarchy;
var current = mng.current;
var ret = [];
for (var _i = 0, _a = current.volumes; _i < _a.length; _i++) {
var ref = _a[_i];
ret.push(this.item(ref));
}
for (var _b = 0, _c = current.lazyVolumes; _b < _c.length; _b++) {
var ref = _c[_b];
ret.push(this.item(ref));
}
return ret;
},
enumerable: false,
configurable: true
});
Object.defineProperty(VolumeSourceControls.prototype, "addActions", {
get: function () {
var mng = this.plugin.managers.volume.hierarchy;
var current = mng.selection;
var ret = (0, tslib_1.__spreadArray)([], hierarchy_2.VolumeHierarchyManager.getRepresentationTypes(this.plugin, current)
.map(function (t) { return action_menu_1.ActionMenu.Item(t[1], function () { return mng.addRepresentation(current, t[0]); }); }), true);
return ret;
},
enumerable: false,
configurable: true
});
Object.defineProperty(VolumeSourceControls.prototype, "isEmpty", {
get: function () {
var _a = this.plugin.managers.volume.hierarchy.current, volumes = _a.volumes, lazyVolumes = _a.lazyVolumes;
return volumes.length === 0 && lazyVolumes.length === 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(VolumeSourceControls.prototype, "label", {
get: function () {
var _a;
if (this.state.loadingLabel)
return "Loading " + this.state.loadingLabel + "...";
var selected = this.plugin.managers.volume.hierarchy.selection;
if (!selected)
return 'Nothing Selected';
return ((_a = selected === null || selected === void 0 ? void 0 : selected.cell.obj) === null || _a === void 0 ? void 0 : _a.label) || 'Volume';
},
enumerable: false,
configurable: true
});
VolumeSourceControls.prototype.lazyLoad = function (cell) {
return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
var _a, url, isBinary, format, entryId, isovalues, plugin_1;
var _this = this;
return (0, tslib_1.__generator)(this, function (_b) {
switch (_b.label) {
case 0:
_a = cell.obj.data, url = _a.url, isBinary = _a.isBinary, format = _a.format, entryId = _a.entryId, isovalues = _a.isovalues;
this.setState({ isBusy: true, loadingLabel: cell.obj.label });
_b.label = 1;
case 1:
_b.trys.push([1, , 3, 4]);
plugin_1 = this.plugin;
return [4 /*yield*/, plugin_1.dataTransaction(function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var data, parsed, firstVolume, repr, _i, isovalues_1, iso;
var _a, _b, _c, _d;
return (0, tslib_1.__generator)(this, function (_e) {
switch (_e.label) {
case 0: return [4 /*yield*/, plugin_1.builders.data.download({ url: url, isBinary: isBinary }, { state: { isGhost: true } })];
case 1:
data = _e.sent();
return [4 /*yield*/, plugin_1.dataFormats.get(format).parse(plugin_1, data, { entryId: entryId })];
case 2:
parsed = _e.sent();
firstVolume = (parsed.volume || parsed.volumes[0]);
if (!(firstVolume === null || firstVolume === void 0 ? void 0 : firstVolume.isOk))
throw new Error('Failed to parse any volume.');
repr = plugin_1.build();
for (_i = 0, isovalues_1 = isovalues; _i < isovalues_1.length; _i++) {
iso = isovalues_1[_i];
repr
.to((_c = (_a = parsed.volumes) === null || _a === void 0 ? void 0 : _a[(_b = iso.volumeIndex) !== null && _b !== void 0 ? _b : 0]) !== null && _c !== void 0 ? _c : parsed.volume)
.apply(transforms_1.StateTransforms.Representation.VolumeRepresentation3D, (0, volume_representation_params_1.createVolumeRepresentationParams)(this.plugin, firstVolume.data, {
type: 'isosurface',
typeParams: { alpha: (_d = iso.alpha) !== null && _d !== void 0 ? _d : 1, isoValue: iso.type === 'absolute' ? { kind: 'absolute', absoluteValue: iso.value } : { kind: 'relative', relativeValue: iso.value } },
color: 'uniform',
colorParams: { value: iso.color }
}));
}
return [4 /*yield*/, repr.commit()];
case 3:
_e.sent();
return [4 /*yield*/, plugin_1.build().delete(cell).commit()];
case 4:
_e.sent();
return [2 /*return*/];
}
});
}); })];
case 2:
_b.sent();
return [3 /*break*/, 4];
case 3:
this.setState({ isBusy: false, loadingLabel: void 0 });
return [7 /*endfinally*/];
case 4: return [2 /*return*/];
}
});
});
};
VolumeSourceControls.prototype.renderControls = function () {
var disabled = this.state.isBusy || this.isEmpty;
var label = this.label;
var selected = this.plugin.managers.volume.hierarchy.selection;
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row', style: { marginTop: '1px' } }, { children: [(0, jsx_runtime_1.jsx)(common_1.Button, (0, tslib_1.__assign)({ noOverflow: true, flex: true, onClick: this.toggleHierarchy, disabled: disabled, title: label }, { children: label }), void 0), !this.isEmpty && selected && (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.AddSvg, onClick: this.toggleAddRepr, title: 'Apply a structure presets to the current hierarchy.', toggleState: this.state.show === 'add-repr', disabled: disabled }, void 0)] }), void 0), this.state.show === 'hierarchy' && (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: this.hierarchyItems, onSelect: this.selectCurrent }, void 0), this.state.show === 'add-repr' && (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: this.addActions, onSelect: this.selectAdd }, void 0), selected && selected.representations.length > 0 && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ style: { marginTop: '6px' } }, { children: selected.representations.map(function (r) { return (0, jsx_runtime_1.jsx)(VolumeRepresentationControls, { representation: r }, r.cell.transform.ref); }) }), void 0)] }, void 0);
};
return VolumeSourceControls;
}(base_1.CollapsableControls));
exports.VolumeSourceControls = VolumeSourceControls;
var VolumeRepresentationControls = /** @class */ (function (_super) {
(0, tslib_1.__extends)(VolumeRepresentationControls, _super);
function VolumeRepresentationControls() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { action: void 0 };
_this.remove = function () { return _this.plugin.managers.volume.hierarchy.remove([_this.props.representation], true); };
_this.toggleVisible = function (e) {
e.preventDefault();
e.currentTarget.blur();
_this.plugin.managers.volume.hierarchy.toggleVisibility([_this.props.representation]);
};
_this.toggleUpdate = function () { return _this.setState({ action: _this.state.action === 'update' ? void 0 : 'update' }); };
_this.highlight = function (e) {
e.preventDefault();
if (!_this.props.representation.cell.parent)
return;
commands_1.PluginCommands.Interactivity.Object.Highlight(_this.plugin, { state: _this.props.representation.cell.parent, ref: _this.props.representation.cell.transform.ref });
};
_this.clearHighlight = function (e) {
e.preventDefault();
commands_1.PluginCommands.Interactivity.ClearHighlights(_this.plugin);
};
_this.focus = function () {
var _a;
var repr = _this.props.representation;
var objects = (_a = _this.props.representation.cell.obj) === null || _a === void 0 ? void 0 : _a.data.repr.renderObjects;
if (repr.cell.state.isHidden)
_this.plugin.managers.volume.hierarchy.toggleVisibility([_this.props.representation], 'show');
_this.plugin.managers.camera.focusRenderObjects(objects, { extraRadius: 1 });
};
return _this;
}
VolumeRepresentationControls.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.state.events.cell.stateUpdated, function (e) {
if (mol_state_1.State.ObjectEvent.isCell(e, _this.props.representation.cell))
_this.forceUpdate();
});
};
VolumeRepresentationControls.prototype.render = function () {
var _a, _b, _c;
var repr = this.props.representation.cell;
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: [(0, jsx_runtime_1.jsxs)(common_1.Button, (0, tslib_1.__assign)({ noOverflow: true, className: 'msp-control-button-label', title: ((_a = repr.obj) === null || _a === void 0 ? void 0 : _a.label) + ". Click to focus.", onClick: this.focus, onMouseEnter: this.highlight, onMouseLeave: this.clearHighlight, style: { textAlign: 'left' } }, { children: [(_b = repr.obj) === null || _b === void 0 ? void 0 : _b.label, (0, jsx_runtime_1.jsx)("small", (0, tslib_1.__assign)({ className: 'msp-25-lower-contrast-text', style: { float: 'right' } }, { children: (_c = repr.obj) === null || _c === void 0 ? void 0 : _c.description }), void 0)] }), void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: repr.state.isHidden ? icons_1.VisibilityOffOutlinedSvg : icons_1.VisibilityOutlinedSvg, toggleState: false, onClick: this.toggleVisible, title: (repr.state.isHidden ? 'Show' : 'Hide') + " component", small: true, className: 'msp-form-control', flex: true }, void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.DeleteOutlinedSvg, onClick: this.remove, title: 'Remove', small: true }, void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.MoreHorizSvg, onClick: this.toggleUpdate, title: 'Actions', toggleState: this.state.action === 'update' }, void 0)] }), void 0), this.state.action === 'update' && !!repr.parent && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ style: { marginBottom: '6px' }, className: 'msp-accent-offset' }, { children: (0, jsx_runtime_1.jsx)(update_transform_1.UpdateTransformControl, { state: repr.parent, transform: repr.transform, customHeader: 'none', noMargin: true }, void 0) }), void 0)] }, void 0);
};
return VolumeRepresentationControls;
}(base_1.PurePluginUIComponent));
//# sourceMappingURL=volume.js.map