UNPKG

molstar

Version:

A comprehensive macromolecular library.

324 lines 21.2 kB
"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