molstar
Version:
A comprehensive macromolecular library.
288 lines • 18.4 kB
JavaScript
import { __assign, __extends } from "tslib";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Loci } from '../../mol-model/loci';
import { StructureMeasurementParams } from '../../mol-plugin-state/manager/structure/measurement';
import { PluginCommands } from '../../mol-plugin/commands';
import { angleLabel, dihedralLabel, distanceLabel, lociLabel } from '../../mol-theme/label';
import { CollapsableControls, PurePluginUIComponent } from '../base';
import { ActionMenu } from '../controls/action-menu';
import { Button, ExpandGroup, IconButton, ToggleButton } from '../controls/common';
import { AddSvg, ArrowDownwardSvg, ArrowUpwardSvg, DeleteOutlinedSvg, HelpOutlineSvg, Icon, MoreHorizSvg, PencilRulerSvg, SetSvg, TuneSvg, VisibilityOffOutlinedSvg, VisibilityOutlinedSvg } from '../controls/icons';
import { ParameterControls } from '../controls/parameters';
import { UpdateTransformControl } from '../state/update-transform';
import { ToggleSelectionModeButton } from './selection';
// TODO details, options (e.g. change text for labels)
var StructureMeasurementsControls = /** @class */ (function (_super) {
__extends(StructureMeasurementsControls, _super);
function StructureMeasurementsControls() {
return _super !== null && _super.apply(this, arguments) || this;
}
StructureMeasurementsControls.prototype.defaultState = function () {
return {
isCollapsed: false,
header: 'Measurements',
brand: { accent: 'gray', svg: PencilRulerSvg }
};
};
StructureMeasurementsControls.prototype.renderControls = function () {
return _jsxs(_Fragment, { children: [_jsx(MeasurementControls, {}, void 0), _jsx(MeasurementList, {}, void 0)] }, void 0);
};
return StructureMeasurementsControls;
}(CollapsableControls));
export { StructureMeasurementsControls };
var MeasurementList = /** @class */ (function (_super) {
__extends(MeasurementList, _super);
function MeasurementList() {
return _super !== null && _super.apply(this, arguments) || this;
}
MeasurementList.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.managers.structure.measurement.behaviors.state, function () {
_this.forceUpdate();
});
};
MeasurementList.prototype.renderGroup = function (cells, header) {
var group = [];
for (var _a = 0, cells_1 = cells; _a < cells_1.length; _a++) {
var cell = cells_1[_a];
if (cell.obj)
group.push(_jsx(MeasurementEntry, { cell: cell }, cell.obj.id));
}
return group.length ? _jsx(ExpandGroup, __assign({ header: header, initiallyExpanded: true }, { children: group }), void 0) : null;
};
MeasurementList.prototype.render = function () {
var measurements = this.plugin.managers.structure.measurement.state;
return _jsxs("div", __assign({ style: { marginTop: '6px' } }, { children: [this.renderGroup(measurements.labels, 'Labels'), this.renderGroup(measurements.distances, 'Distances'), this.renderGroup(measurements.angles, 'Angles'), this.renderGroup(measurements.dihedrals, 'Dihedrals')] }), void 0);
};
return MeasurementList;
}(PurePluginUIComponent));
export { MeasurementList };
var MeasurementControls = /** @class */ (function (_super) {
__extends(MeasurementControls, _super);
function MeasurementControls() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { isBusy: false, action: void 0 };
_this.measureDistance = function () {
var loci = _this.plugin.managers.structure.selection.additionsHistory;
_this.plugin.managers.structure.measurement.addDistance(loci[0].loci, loci[1].loci);
};
_this.measureAngle = function () {
var loci = _this.plugin.managers.structure.selection.additionsHistory;
_this.plugin.managers.structure.measurement.addAngle(loci[0].loci, loci[1].loci, loci[2].loci);
};
_this.measureDihedral = function () {
var loci = _this.plugin.managers.structure.selection.additionsHistory;
_this.plugin.managers.structure.measurement.addDihedral(loci[0].loci, loci[1].loci, loci[2].loci, loci[3].loci);
};
_this.addLabel = function () {
var loci = _this.plugin.managers.structure.selection.additionsHistory;
_this.plugin.managers.structure.measurement.addLabel(loci[0].loci);
};
_this.selectAction = function (item) {
_this.toggleAdd();
if (!item)
return;
(item === null || item === void 0 ? void 0 : item.value)();
};
_this.toggleAdd = function () { return _this.setState({ action: _this.state.action === 'add' ? void 0 : 'add' }); };
_this.toggleOptions = function () { return _this.setState({ action: _this.state.action === 'options' ? void 0 : 'options' }); };
return _this;
}
MeasurementControls.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.selection.events.additionsHistoryUpdated, function () {
_this.forceUpdate();
});
this.subscribe(this.plugin.behaviors.state.isBusy, function (v) {
_this.setState({ isBusy: v });
});
};
Object.defineProperty(MeasurementControls.prototype, "selection", {
get: function () {
return this.plugin.managers.structure.selection;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MeasurementControls.prototype, "actions", {
get: function () {
var history = this.selection.additionsHistory;
var ret = [
{ kind: 'item', label: "Label " + (history.length === 0 ? ' (1 selection required)' : ' (1st selection)'), value: this.addLabel, disabled: history.length === 0 },
{ kind: 'item', label: "Distance " + (history.length < 2 ? ' (2 selections required)' : ' (top 2 selections)'), value: this.measureDistance, disabled: history.length < 2 },
{ kind: 'item', label: "Angle " + (history.length < 3 ? ' (3 selections required)' : ' (top 3 selections)'), value: this.measureAngle, disabled: history.length < 3 },
{ kind: 'item', label: "Dihedral " + (history.length < 4 ? ' (4 selections required)' : ' (top 4 selections)'), value: this.measureDihedral, disabled: history.length < 4 },
];
return ret;
},
enumerable: false,
configurable: true
});
MeasurementControls.prototype.highlight = function (loci) {
this.plugin.managers.interactivity.lociHighlights.highlightOnly({ loci: loci }, false);
};
MeasurementControls.prototype.moveHistory = function (e, direction) {
this.plugin.managers.structure.selection.modifyHistory(e, direction, 4);
};
MeasurementControls.prototype.focusLoci = function (loci) {
this.plugin.managers.camera.focusLoci(loci);
};
MeasurementControls.prototype.historyEntry = function (e, idx) {
var _this = this;
var history = this.plugin.managers.structure.selection.additionsHistory;
return _jsxs("div", __assign({ className: 'msp-flex-row' }, { children: [_jsxs(Button, __assign({ noOverflow: true, title: 'Click to focus. Hover to highlight.', onClick: function () { return _this.focusLoci(e.loci); }, style: { width: 'auto', textAlign: 'left' }, onMouseEnter: function () { return _this.highlight(e.loci); }, onMouseLeave: function () { return _this.plugin.managers.interactivity.lociHighlights.clearHighlights(); } }, { children: [idx, ". ", _jsx("span", { dangerouslySetInnerHTML: { __html: e.label } }, void 0)] }), void 0), history.length > 1 && _jsx(IconButton, { svg: ArrowUpwardSvg, small: true, className: 'msp-form-control', onClick: function () { return _this.moveHistory(e, 'up'); }, flex: '20px', title: 'Move up' }, void 0), history.length > 1 && _jsx(IconButton, { svg: ArrowDownwardSvg, small: true, className: 'msp-form-control', onClick: function () { return _this.moveHistory(e, 'down'); }, flex: '20px', title: 'Move down' }, void 0), _jsx(IconButton, { svg: DeleteOutlinedSvg, small: true, className: 'msp-form-control', onClick: function () { return _this.plugin.managers.structure.selection.modifyHistory(e, 'remove'); }, flex: true, title: 'Remove' }, void 0)] }), e.id);
};
MeasurementControls.prototype.add = function () {
var history = this.plugin.managers.structure.selection.additionsHistory;
var entries = [];
for (var i = 0, _i = Math.min(history.length, 4); i < _i; i++) {
entries.push(this.historyEntry(history[i], i + 1));
}
return _jsxs(_Fragment, { children: [_jsx(ActionMenu, { items: this.actions, onSelect: this.selectAction }, void 0), entries.length > 0 && _jsx("div", __assign({ className: 'msp-control-offset' }, { children: entries }), void 0), entries.length === 0 && _jsx("div", __assign({ className: 'msp-control-offset msp-help-text' }, { children: _jsxs("div", __assign({ className: 'msp-help-description' }, { children: [_jsx(Icon, { svg: HelpOutlineSvg, inline: true }, void 0), "Add one or more selections (toggle ", _jsx(ToggleSelectionModeButton, { inline: true }, void 0), " mode)"] }), void 0) }), void 0)] }, void 0);
};
MeasurementControls.prototype.render = function () {
return _jsxs(_Fragment, { children: [_jsxs("div", __assign({ className: 'msp-flex-row' }, { children: [_jsx(ToggleButton, { icon: AddSvg, label: 'Add', toggle: this.toggleAdd, isSelected: this.state.action === 'add', disabled: this.state.isBusy, className: 'msp-btn-apply-simple' }, void 0), _jsx(ToggleButton, { icon: TuneSvg, label: '', title: 'Options', toggle: this.toggleOptions, isSelected: this.state.action === 'options', disabled: this.state.isBusy, style: { flex: '0 0 40px', padding: 0 } }, void 0)] }), void 0), this.state.action === 'add' && this.add(), this.state.action === 'options' && _jsx(MeasurementsOptions, {}, void 0)] }, void 0);
};
return MeasurementControls;
}(PurePluginUIComponent));
export { MeasurementControls };
var MeasurementsOptions = /** @class */ (function (_super) {
__extends(MeasurementsOptions, _super);
function MeasurementsOptions() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { isDisabled: false };
_this.changed = function (options) {
_this.plugin.managers.structure.measurement.setOptions(options);
};
return _this;
}
MeasurementsOptions.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.managers.structure.measurement.behaviors.state, function () {
_this.forceUpdate();
});
this.subscribe(this.plugin.behaviors.state.isBusy, function (v) {
_this.setState({ isDisabled: v });
});
};
MeasurementsOptions.prototype.render = function () {
var measurements = this.plugin.managers.structure.measurement.state;
return _jsx("div", __assign({ className: 'msp-control-offset' }, { children: _jsx(ParameterControls, { params: StructureMeasurementParams, values: measurements.options, onChangeValues: this.changed, isDisabled: this.state.isDisabled }, void 0) }), void 0);
};
return MeasurementsOptions;
}(PurePluginUIComponent));
var MeasurementEntry = /** @class */ (function (_super) {
__extends(MeasurementEntry, _super);
function MeasurementEntry() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showUpdate: false };
_this.delete = function () {
PluginCommands.State.RemoveObject(_this.plugin, { state: _this.props.cell.parent, ref: _this.props.cell.transform.parent, removeParentGhosts: true });
};
_this.toggleVisibility = function (e) {
e.preventDefault();
PluginCommands.State.ToggleVisibility(_this.plugin, { state: _this.props.cell.parent, ref: _this.props.cell.transform.parent });
e.currentTarget.blur();
};
_this.highlight = function () {
var _a;
var selections = _this.selections;
if (!selections)
return;
_this.plugin.managers.interactivity.lociHighlights.clearHighlights();
for (var _b = 0, _c = _this.lociArray; _b < _c.length; _b++) {
var loci = _c[_b];
_this.plugin.managers.interactivity.lociHighlights.highlight({ loci: loci }, false);
}
_this.plugin.managers.interactivity.lociHighlights.highlight({ loci: (_a = _this.props.cell.obj) === null || _a === void 0 ? void 0 : _a.data.repr.getLoci() }, false);
};
_this.clearHighlight = function () {
_this.plugin.managers.interactivity.lociHighlights.clearHighlights();
};
_this.toggleUpdate = function () { return _this.setState({ showUpdate: !_this.state.showUpdate }); };
_this.focus = function () {
var selections = _this.selections;
if (!selections)
return;
var sphere = Loci.getBundleBoundingSphere({ loci: _this.lociArray });
if (sphere) {
_this.plugin.managers.camera.focusSphere(sphere);
}
};
_this.selectAction = function (item) {
if (!item)
return;
_this.setState({ showUpdate: false });
(item === null || item === void 0 ? void 0 : item.value)();
};
return _this;
}
MeasurementEntry.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.state.events.cell.stateUpdated, function (e) {
_this.forceUpdate();
});
};
Object.defineProperty(MeasurementEntry.prototype, "selections", {
get: function () {
var _a;
return (_a = this.props.cell.obj) === null || _a === void 0 ? void 0 : _a.data.sourceData;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MeasurementEntry.prototype, "lociArray", {
get: function () {
var selections = this.selections;
if (!selections)
return [];
if (selections.infos)
return [selections.infos[0].loci];
if (selections.pairs)
return selections.pairs[0].loci;
if (selections.triples)
return selections.triples[0].loci;
if (selections.quads)
return selections.quads[0].loci;
return [];
},
enumerable: false,
configurable: true
});
Object.defineProperty(MeasurementEntry.prototype, "label", {
get: function () {
var selections = this.selections;
if (!selections)
return '<empty>';
if (selections.infos)
return lociLabel(selections.infos[0].loci, { condensed: true });
if (selections.pairs)
return distanceLabel(selections.pairs[0], { condensed: true, unitLabel: this.plugin.managers.structure.measurement.state.options.distanceUnitLabel });
if (selections.triples)
return angleLabel(selections.triples[0], { condensed: true });
if (selections.quads)
return dihedralLabel(selections.quads[0], { condensed: true });
return '<empty>';
},
enumerable: false,
configurable: true
});
Object.defineProperty(MeasurementEntry.prototype, "actions", {
get: function () {
var _this = this;
this.props.cell.sourceRef;
return [ActionMenu.Item('Select This', function () { return _this.plugin.managers.structure.selection.fromSelections(_this.props.cell.sourceRef); }, { icon: SetSvg })];
},
enumerable: false,
configurable: true
});
MeasurementEntry.prototype.render = function () {
var cell = this.props.cell;
var obj = cell.obj;
if (!obj)
return null;
return _jsxs(_Fragment, { children: [_jsxs("div", __assign({ className: 'msp-flex-row', onMouseEnter: this.highlight, onMouseLeave: this.clearHighlight }, { children: [_jsx("button", __assign({ className: 'msp-form-control msp-control-button-label msp-no-overflow', title: 'Click to focus. Hover to highlight.', onClick: this.focus, style: { width: 'auto', textAlign: 'left' } }, { children: _jsx("span", { dangerouslySetInnerHTML: { __html: this.label } }, void 0) }), void 0), _jsx(IconButton, { svg: cell.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg, toggleState: false, small: true, className: 'msp-form-control', onClick: this.toggleVisibility, flex: true, title: cell.state.isHidden ? 'Show' : 'Hide' }, void 0), _jsx(IconButton, { svg: DeleteOutlinedSvg, small: true, className: 'msp-form-control', onClick: this.delete, flex: true, title: 'Delete', toggleState: false }, void 0), _jsx(IconButton, { svg: MoreHorizSvg, className: 'msp-form-control', onClick: this.toggleUpdate, flex: true, title: 'Actions', toggleState: this.state.showUpdate }, void 0)] }), obj.id), this.state.showUpdate && cell.parent && _jsx(_Fragment, { children: _jsxs("div", __assign({ className: 'msp-accent-offset' }, { children: [_jsx(ActionMenu, { items: this.actions, onSelect: this.selectAction, noOffset: true }, void 0), _jsx(ExpandGroup, __assign({ header: 'Options', noOffset: true }, { children: _jsx(UpdateTransformControl, { state: cell.parent, transform: cell.transform, customHeader: 'none', autoHideApply: true }, void 0) }), void 0)] }), void 0) }, void 0)] }, void 0);
};
return MeasurementEntry;
}(PurePluginUIComponent));
//# sourceMappingURL=measurements.js.map