molstar
Version:
A comprehensive macromolecular library.
863 lines • 77.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScriptControl = exports.ConvertedControl = exports.ConditionedControl = exports.ObjectListControl = exports.MappedControl = exports.GroupControl = exports.MultiSelectControl = exports.FileListControl = exports.FileControl = exports.UrlControl = exports.Mat4Control = exports.Vec3Control = exports.OffsetColorListControl = exports.ColorListControl = exports.ColorControl = exports.BoundedIntervalControl = exports.IntervalControl = exports.ValueRefControl = exports.SelectControl = exports.PureSelectControl = exports.TextControl = exports.NumberRangeControl = exports.NumberInputControl = exports.LineGraphControl = exports.BoolControl = exports.SimpleParam = exports.ParamHelp = exports.ParameterMappingControl = exports.ParameterControls = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
var React = (0, tslib_1.__importStar)(require("react"));
var linear_algebra_1 = require("../../mol-math/linear-algebra");
var color_1 = require("../../mol-util/color");
var lists_1 = require("../../mol-util/color/lists");
var memoize_1 = require("../../mol-util/memoize");
var number_1 = require("../../mol-util/number");
var param_definition_1 = require("../../mol-util/param-definition");
var string_1 = require("../../mol-util/string");
var base_1 = require("../base");
var action_menu_1 = require("./action-menu");
var color_2 = require("./color");
var common_1 = require("./common");
var icons_1 = require("./icons");
var legend_1 = require("./legend");
var line_graph_component_1 = require("./line-graph/line-graph-component");
var slider_1 = require("./slider");
var assets_1 = require("../../mol-util/assets");
var ParameterControls = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ParameterControls, _super);
function ParameterControls() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (params) {
var _a;
var _b, _c;
(_c = (_b = _this.props).onChange) === null || _c === void 0 ? void 0 : _c.call(_b, params, _this.props.values);
if (_this.props.onChangeValues) {
var values = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, _this.props.values), (_a = {}, _a[params.name] = params.value, _a));
_this.props.onChangeValues(values, _this.props.values);
}
};
_this.paramGroups = (0, memoize_1.memoizeLatest)(function (params) { return classifyParams(params); });
return _this;
}
ParameterControls.prototype.renderGroup = function (group) {
var _a;
if (group.length === 0)
return null;
var values = this.props.values;
var ctrls = null;
var category = void 0;
for (var _i = 0, group_1 = group; _i < group_1.length; _i++) {
var _b = group_1[_i], key = _b[0], p = _b[1], Control = _b[2];
if ((_a = p.hideIf) === null || _a === void 0 ? void 0 : _a.call(p, values))
continue;
if (!ctrls)
ctrls = [];
category = p.category;
ctrls.push((0, jsx_runtime_1.jsx)(Control, { param: p, onChange: this.onChange, onEnter: this.props.onEnter, isDisabled: this.props.isDisabled, name: key, value: values[key] }, key));
}
if (!ctrls)
return null;
if (category) {
return [(0, jsx_runtime_1.jsx)(common_1.ExpandGroup, (0, tslib_1.__assign)({ header: category }, { children: ctrls }), category)];
}
return ctrls;
};
ParameterControls.prototype.renderPart = function (groups) {
var parts = null;
for (var _i = 0, groups_1 = groups; _i < groups_1.length; _i++) {
var g = groups_1[_i];
var ctrls = this.renderGroup(g);
if (!ctrls)
continue;
if (!parts)
parts = [];
for (var _a = 0, ctrls_1 = ctrls; _a < ctrls_1.length; _a++) {
var c = ctrls_1[_a];
parts.push(c);
}
}
return parts;
};
ParameterControls.prototype.render = function () {
var groups = this.paramGroups(this.props.params);
var essentials = this.renderPart(groups.essentials);
var advanced = this.renderPart(groups.advanced);
if (essentials && advanced) {
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [essentials, (0, jsx_runtime_1.jsx)(common_1.ExpandGroup, (0, tslib_1.__assign)({ header: 'Advanced Options' }, { children: advanced }), void 0)] }, void 0);
}
else if (essentials) {
return essentials;
}
else {
return advanced;
}
};
return ParameterControls;
}(React.PureComponent));
exports.ParameterControls = ParameterControls;
var ParameterMappingControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ParameterMappingControl, _super);
function ParameterMappingControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.setSettings = function (p, old) {
var _a;
var values = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, old), (_a = {}, _a[p.name] = p.value, _a));
var t = _this.props.mapping.update(values, _this.plugin);
_this.props.mapping.apply(t, _this.plugin);
};
return _this;
}
ParameterMappingControl.prototype.componentDidMount = function () {
var _this = this;
this.subscribe(this.plugin.events.canvas3d.settingsUpdated, function () { return _this.forceUpdate(); });
};
ParameterMappingControl.prototype.render = function () {
var t = this.props.mapping.getTarget(this.plugin);
var values = this.props.mapping.getValues(t, this.plugin);
var params = this.props.mapping.params(this.plugin);
return (0, jsx_runtime_1.jsx)(ParameterControls, { params: params, values: values, onChange: this.setSettings }, void 0);
};
return ParameterMappingControl;
}(base_1.PluginUIComponent));
exports.ParameterMappingControl = ParameterMappingControl;
function classifyParams(params) {
function addParam(k, p, group) {
var ctrl = controlFor(p);
if (!ctrl)
return;
if (!p.category)
group.params[0].push([k, p, ctrl]);
else {
if (!group.map)
group.map = new Map();
var c = group.map.get(p.category);
if (!c) {
c = [];
group.map.set(p.category, c);
group.params.push(c);
}
c.push([k, p, ctrl]);
}
}
function sortGroups(x, y) {
var a = x[0], b = y[0];
if (!a || !a[1].category)
return -1;
if (!b || !b[1].category)
return 1;
return a[1].category < b[1].category ? -1 : 1;
}
var keys = Object.keys(params);
var essentials = { params: [[]], map: void 0 };
var advanced = { params: [[]], map: void 0 };
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var k = keys_1[_i];
var p = params[k];
if (p.isHidden)
continue;
if (p.isEssential)
addParam(k, p, essentials);
else
addParam(k, p, advanced);
}
essentials.params.sort(sortGroups);
advanced.params.sort(sortGroups);
return { essentials: essentials.params, advanced: advanced.params };
}
function controlFor(param) {
switch (param.type) {
case 'value': return void 0;
case 'boolean': return BoolControl;
case 'number': return typeof param.min !== 'undefined' && typeof param.max !== 'undefined'
? NumberRangeControl : NumberInputControl;
case 'converted': return ConvertedControl;
case 'conditioned': return ConditionedControl;
case 'multi-select': return MultiSelectControl;
case 'color': return color_2.CombinedColorControl;
case 'color-list': return param.offsets ? OffsetColorListControl : ColorListControl;
case 'vec3': return Vec3Control;
case 'mat4': return Mat4Control;
case 'url': return UrlControl;
case 'file': return FileControl;
case 'file-list': return FileListControl;
case 'select': return SelectControl;
case 'value-ref': return ValueRefControl;
case 'data-ref': return void 0;
case 'text': return TextControl;
case 'interval': return typeof param.min !== 'undefined' && typeof param.max !== 'undefined'
? BoundedIntervalControl : IntervalControl;
case 'group': return GroupControl;
case 'mapped': return MappedControl;
case 'line-graph': return LineGraphControl;
case 'script': return ScriptControl;
case 'object-list': return ObjectListControl;
default:
var _ = param;
console.warn(_ + " has no associated UI component");
return void 0;
}
}
var ParamHelp = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ParamHelp, _super);
function ParamHelp() {
return _super !== null && _super.apply(this, arguments) || this;
}
ParamHelp.prototype.render = function () {
var _a = this.props, legend = _a.legend, description = _a.description;
var Legend = legend && (0, legend_1.legendFor)(legend);
return (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-help-text' }, { children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-help-description' }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.HelpOutlineSvg, inline: true }, void 0), description] }), void 0), Legend && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-help-legend' }, { children: (0, jsx_runtime_1.jsx)(Legend, { legend: legend }, void 0) }), void 0)] }, void 0) }), void 0);
};
return ParamHelp;
}(React.PureComponent));
exports.ParamHelp = ParamHelp;
function renderSimple(options) {
var props = options.props, state = options.state, control = options.control, toggleHelp = options.toggleHelp, addOn = options.addOn;
var _className = [];
if (props.param.shortLabel)
_className.push('msp-control-label-short');
if (props.param.twoColumns)
_className.push('msp-control-col-2');
var className = _className.join(' ');
var label = props.param.label || (0, string_1.camelCaseToWords)(props.name);
var help = props.param.help
? props.param.help(props.value)
: { description: props.param.description, legend: props.param.legend };
var hasHelp = help.description || help.legend;
var desc = label + (hasHelp ? '. Click for help.' : '');
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.ControlRow, { className: className, title: desc, label: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [label, hasHelp &&
(0, jsx_runtime_1.jsx)("button", (0, tslib_1.__assign)({ className: 'msp-help msp-btn-link msp-btn-icon msp-control-group-expander', onClick: toggleHelp, title: desc || (state.showHelp ? 'Hide' : 'Show') + " help", style: { background: 'transparent', textAlign: 'left', padding: '0' } }, { children: (0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_1.HelpOutlineSvg }, void 0) }), void 0)] }, void 0), control: control }, void 0), hasHelp && state.showHelp && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: (0, jsx_runtime_1.jsx)(ParamHelp, { legend: help.legend, description: help.description }, void 0) }), void 0), addOn] }, void 0);
}
var SimpleParam = /** @class */ (function (_super) {
(0, tslib_1.__extends)(SimpleParam, _super);
function SimpleParam() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showHelp: false };
_this.toggleHelp = function () { return _this.setState({ showHelp: !_this.state.showHelp }); };
return _this;
}
SimpleParam.prototype.update = function (value) {
this.props.onChange({ param: this.props.param, name: this.props.name, value: value });
};
SimpleParam.prototype.renderAddOn = function () { return null; };
SimpleParam.prototype.render = function () {
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderAddOn()
});
};
return SimpleParam;
}(React.PureComponent));
exports.SimpleParam = SimpleParam;
var BoolControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(BoolControl, _super);
function BoolControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onClick = function (e) { _this.update(!_this.props.value); e.currentTarget.blur(); };
return _this;
}
BoolControl.prototype.renderControl = function () {
return (0, jsx_runtime_1.jsxs)("button", (0, tslib_1.__assign)({ onClick: this.onClick, disabled: this.props.isDisabled }, { children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: this.props.value ? icons_1.CheckSvg : icons_1.ClearSvg }, void 0), this.props.value ? 'On' : 'Off'] }), void 0);
};
return BoolControl;
}(SimpleParam));
exports.BoolControl = BoolControl;
var LineGraphControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(LineGraphControl, _super);
function LineGraphControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = {
isExpanded: false,
isOverPoint: false,
message: _this.props.param.defaultValue.length + " points",
};
_this.onHover = function (point) {
_this.setState({ isOverPoint: !_this.state.isOverPoint });
if (point) {
_this.setState({ message: "(" + point[0].toFixed(2) + ", " + point[1].toFixed(2) + ")" });
return;
}
_this.setState({ message: _this.props.value.length + " points" });
};
_this.onDrag = function (point) {
_this.setState({ message: "(" + point[0].toFixed(2) + ", " + point[1].toFixed(2) + ")" });
};
_this.onChange = function (value) {
_this.props.onChange({ name: _this.props.name, param: _this.props.param, value: value });
};
_this.toggleExpanded = function (e) {
_this.setState({ isExpanded: !_this.state.isExpanded });
e.currentTarget.blur();
};
return _this;
}
LineGraphControl.prototype.render = function () {
var label = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.ControlRow, { label: label, control: (0, jsx_runtime_1.jsx)("button", (0, tslib_1.__assign)({ onClick: this.toggleExpanded, disabled: this.props.isDisabled }, { children: "" + this.state.message }), void 0) }, void 0), (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset', style: { display: this.state.isExpanded ? 'block' : 'none' } }, { children: (0, jsx_runtime_1.jsx)(line_graph_component_1.LineGraphComponent, { data: this.props.param.defaultValue, onChange: this.onChange, onHover: this.onHover, onDrag: this.onDrag }, void 0) }), void 0)] }, void 0);
};
return LineGraphControl;
}(React.PureComponent));
exports.LineGraphControl = LineGraphControl;
var NumberInputControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(NumberInputControl, _super);
function NumberInputControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { value: '0' };
_this.update = function (value) {
var p = (0, number_1.getPrecision)(_this.props.param.step || 0.01);
value = parseFloat(value.toFixed(p));
_this.props.onChange({ param: _this.props.param, name: _this.props.name, value: value });
};
return _this;
}
NumberInputControl.prototype.render = function () {
var placeholder = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
var label = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
var p = (0, number_1.getPrecision)(this.props.param.step || 0.01);
return (0, jsx_runtime_1.jsx)(common_1.ControlRow, { title: this.props.param.description, label: label, control: (0, jsx_runtime_1.jsx)(common_1.TextInput, { numeric: true, value: parseFloat(this.props.value.toFixed(p)), onEnter: this.props.onEnter, placeholder: placeholder, isDisabled: this.props.isDisabled, onChange: this.update }, void 0) }, void 0);
};
return NumberInputControl;
}(React.PureComponent));
exports.NumberInputControl = NumberInputControl;
var NumberRangeControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(NumberRangeControl, _super);
function NumberRangeControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (v) { _this.update(v); };
return _this;
}
NumberRangeControl.prototype.renderControl = function () {
var value = typeof this.props.value === 'undefined' ? this.props.param.defaultValue : this.props.value;
return (0, jsx_runtime_1.jsx)(slider_1.Slider, { value: value, min: this.props.param.min, max: this.props.param.max, step: this.props.param.step, onChange: this.onChange, onChangeImmediate: this.props.param.immediateUpdate ? this.onChange : void 0, disabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0);
};
return NumberRangeControl;
}(SimpleParam));
exports.NumberRangeControl = NumberRangeControl;
var TextControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(TextControl, _super);
function TextControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (e) {
var value = e.target.value;
if (value !== _this.props.value) {
_this.update(value);
}
};
_this.onKeyPress = function (e) {
if ((e.keyCode === 13 || e.charCode === 13 || e.key === 'Enter')) {
if (_this.props.onEnter)
_this.props.onEnter();
}
e.stopPropagation();
};
return _this;
}
TextControl.prototype.renderControl = function () {
var placeholder = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
return (0, jsx_runtime_1.jsx)("input", { type: 'text', value: this.props.value || '', placeholder: placeholder, onChange: this.onChange, onKeyPress: this.props.onEnter ? this.onKeyPress : void 0, disabled: this.props.isDisabled }, void 0);
};
return TextControl;
}(SimpleParam));
exports.TextControl = TextControl;
var PureSelectControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(PureSelectControl, _super);
function PureSelectControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (e) {
if (typeof _this.props.param.defaultValue === 'number') {
_this.update(parseInt(e.target.value, 10));
}
else {
_this.update(e.target.value);
}
};
return _this;
}
PureSelectControl.prototype.update = function (value) {
this.props.onChange({ param: this.props.param, name: this.props.name, value: value });
};
PureSelectControl.prototype.render = function () {
var _this = this;
var isInvalid = this.props.value !== void 0 && !this.props.param.options.some(function (e) { return e[0] === _this.props.value; });
return (0, jsx_runtime_1.jsxs)("select", (0, tslib_1.__assign)({ className: 'msp-form-control', title: this.props.title, value: this.props.value !== void 0 ? this.props.value : this.props.param.defaultValue, onChange: this.onChange, disabled: this.props.isDisabled }, { children: [isInvalid && (0, jsx_runtime_1.jsx)("option", (0, tslib_1.__assign)({ value: this.props.value }, { children: "[Invalid] " + this.props.value }), this.props.value), this.props.param.options.map(function (_a) {
var value = _a[0], label = _a[1];
return (0, jsx_runtime_1.jsx)("option", (0, tslib_1.__assign)({ value: value }, { children: label }), value);
})] }), void 0);
};
return PureSelectControl;
}(React.PureComponent));
exports.PureSelectControl = PureSelectControl;
var SelectControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(SelectControl, _super);
function SelectControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showHelp: false, showOptions: false };
_this.onSelect = function (item) {
if (!item || item.value === _this.props.value) {
_this.setState({ showOptions: false });
}
else {
_this.setState({ showOptions: false }, function () {
_this.props.onChange({ param: _this.props.param, name: _this.props.name, value: item.value });
});
}
};
_this.toggle = function () { return _this.setState({ showOptions: !_this.state.showOptions }); };
_this.cycle = function () {
var options = _this.props.param.options;
var current = options.findIndex(function (o) { return o[0] === _this.props.value; });
var next = current === options.length - 1 ? 0 : current + 1;
_this.props.onChange({ param: _this.props.param, name: _this.props.name, value: options[next][0] });
};
_this.items = (0, memoize_1.memoizeLatest)(function (param) { return action_menu_1.ActionMenu.createItemsFromSelectOptions(param.options); });
_this.toggleHelp = function () { return _this.setState({ showHelp: !_this.state.showHelp }); };
return _this;
}
SelectControl.prototype.renderControl = function () {
var _a;
var items = this.items(this.props.param);
var current = this.props.value !== undefined ? action_menu_1.ActionMenu.findItem(items, this.props.value) : void 0;
var label = current
? current.label
: typeof this.props.value === 'undefined'
? (((_a = action_menu_1.ActionMenu.getFirstItem(items)) === null || _a === void 0 ? void 0 : _a.label) || '') + " [Default]"
: "[Invalid] " + this.props.value;
var toggle = this.props.param.cycle ? this.cycle : this.toggle;
var textAlign = this.props.param.cycle ? 'center' : 'left';
var icon = this.props.param.cycle
? (this.props.value === 'on' ? icons_1.CheckSvg
: this.props.value === 'off' ? icons_1.ClearSvg : void 0)
: void 0;
return (0, jsx_runtime_1.jsx)(common_1.ToggleButton, { disabled: this.props.isDisabled, style: { textAlign: textAlign, overflow: 'hidden', textOverflow: 'ellipsis' }, label: label, title: label, icon: icon, toggle: toggle, isSelected: this.state.showOptions }, void 0);
};
SelectControl.prototype.renderAddOn = function () {
if (!this.state.showOptions)
return null;
var items = this.items(this.props.param);
var current = action_menu_1.ActionMenu.findItem(items, this.props.value);
return (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: items, current: current, onSelect: this.onSelect }, void 0);
};
SelectControl.prototype.render = function () {
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderAddOn()
});
};
return SelectControl;
}(React.PureComponent));
exports.SelectControl = SelectControl;
var ValueRefControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ValueRefControl, _super);
function ValueRefControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showHelp: false, showOptions: false };
_this.onSelect = function (item) {
if (!item || item.value === _this.props.value) {
_this.setState({ showOptions: false });
}
else {
_this.setState({ showOptions: false }, function () {
_this.props.onChange({ param: _this.props.param, name: _this.props.name, value: { ref: item.value } });
});
}
};
_this.toggle = function () { return _this.setState({ showOptions: !_this.state.showOptions }); };
_this.items = (0, memoize_1.memoizeLatest)(function (param) { return action_menu_1.ActionMenu.createItemsFromSelectOptions(param.getOptions()); });
_this.toggleHelp = function () { return _this.setState({ showHelp: !_this.state.showHelp }); };
return _this;
}
ValueRefControl.prototype.renderControl = function () {
var _a;
var items = this.items(this.props.param);
var current = this.props.value.ref ? action_menu_1.ActionMenu.findItem(items, this.props.value.ref) : void 0;
var label = current
? current.label
: "[Ref] " + ((_a = this.props.value.ref) !== null && _a !== void 0 ? _a : '');
return (0, jsx_runtime_1.jsx)(common_1.ToggleButton, { disabled: this.props.isDisabled, style: { textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis' }, label: label, title: label, toggle: this.toggle, isSelected: this.state.showOptions }, void 0);
};
ValueRefControl.prototype.renderAddOn = function () {
if (!this.state.showOptions)
return null;
var items = this.items(this.props.param);
var current = action_menu_1.ActionMenu.findItem(items, this.props.value.ref);
return (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: items, current: current, onSelect: this.onSelect }, void 0);
};
ValueRefControl.prototype.render = function () {
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderAddOn()
});
};
return ValueRefControl;
}(React.PureComponent));
exports.ValueRefControl = ValueRefControl;
var IntervalControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(IntervalControl, _super);
function IntervalControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { isExpanded: false };
_this.components = {
0: param_definition_1.ParamDefinition.Numeric(0, { step: _this.props.param.step }, { label: 'Min' }),
1: param_definition_1.ParamDefinition.Numeric(0, { step: _this.props.param.step }, { label: 'Max' })
};
_this.componentChange = function (_a) {
var name = _a.name, value = _a.value;
var v = (0, tslib_1.__spreadArray)([], _this.props.value, true);
v[+name] = value;
_this.change(v);
};
_this.toggleExpanded = function (e) {
_this.setState({ isExpanded: !_this.state.isExpanded });
e.currentTarget.blur();
};
return _this;
}
IntervalControl.prototype.change = function (value) {
this.props.onChange({ name: this.props.name, param: this.props.param, value: value });
};
IntervalControl.prototype.render = function () {
var v = this.props.value;
var label = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
var p = (0, number_1.getPrecision)(this.props.param.step || 0.01);
var value = "[" + v[0].toFixed(p) + ", " + v[1].toFixed(p) + "]";
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.ControlRow, { label: label, control: (0, jsx_runtime_1.jsx)("button", (0, tslib_1.__assign)({ onClick: this.toggleExpanded, disabled: this.props.isDisabled }, { children: value }), void 0) }, void 0), this.state.isExpanded && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: (0, jsx_runtime_1.jsx)(ParameterControls, { params: this.components, values: v, onChange: this.componentChange, onEnter: this.props.onEnter }, void 0) }), void 0)] }, void 0);
};
return IntervalControl;
}(React.PureComponent));
exports.IntervalControl = IntervalControl;
var BoundedIntervalControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(BoundedIntervalControl, _super);
function BoundedIntervalControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (v) { _this.update(v); };
return _this;
}
BoundedIntervalControl.prototype.renderControl = function () {
return (0, jsx_runtime_1.jsx)(slider_1.Slider2, { value: this.props.value, min: this.props.param.min, max: this.props.param.max, step: this.props.param.step, onChange: this.onChange, disabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0);
};
return BoundedIntervalControl;
}(SimpleParam));
exports.BoundedIntervalControl = BoundedIntervalControl;
var ColorControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ColorControl, _super);
function ColorControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.onChange = function (e) {
_this.update((0, color_1.Color)(parseInt(e.target.value)));
};
return _this;
}
ColorControl.prototype.stripStyle = function () {
return {
background: color_1.Color.toStyle(this.props.value),
position: 'absolute',
bottom: '0',
height: '4px',
right: '0',
left: '0'
};
};
ColorControl.prototype.renderControl = function () {
return (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ style: { position: 'relative' } }, { children: [(0, jsx_runtime_1.jsxs)("select", (0, tslib_1.__assign)({ value: this.props.value, onChange: this.onChange }, { children: [(0, color_2.ColorValueOption)(this.props.value), (0, color_2.ColorOptions)()] }), void 0), (0, jsx_runtime_1.jsx)("div", { style: this.stripStyle() }, void 0)] }), void 0);
};
return ColorControl;
}(SimpleParam));
exports.ColorControl = ColorControl;
function colorEntryToStyle(e, includeOffset) {
if (includeOffset === void 0) { includeOffset = false; }
if (Array.isArray(e)) {
if (includeOffset)
return color_1.Color.toStyle(e[0]) + " " + (100 * e[1]).toFixed(2) + "%";
return color_1.Color.toStyle(e[0]);
}
return color_1.Color.toStyle(e);
}
var colorGradientInterpolated = (0, memoize_1.memoize1)(function (colors) {
var styles = colors.map(function (c) { return colorEntryToStyle(c, true); });
return "linear-gradient(to right, " + styles.join(', ') + ")";
});
var colorGradientBanded = (0, memoize_1.memoize1)(function (colors) {
var n = colors.length;
var styles = [colorEntryToStyle(colors[0]) + " " + 100 * (1 / n) + "%"];
// TODO: does this need to support offsets?
for (var i = 1, il = n - 1; i < il; ++i) {
styles.push(colorEntryToStyle(colors[i]) + " " + 100 * (i / n) + "%", colorEntryToStyle(colors[i]) + " " + 100 * ((i + 1) / n) + "%");
}
styles.push(colorEntryToStyle(colors[n - 1]) + " " + 100 * ((n - 1) / n) + "%");
return "linear-gradient(to right, " + styles.join(', ') + ")";
});
function colorStripStyle(list, right) {
if (right === void 0) { right = '0'; }
return {
background: colorGradient(list.colors, list.kind === 'set'),
position: 'absolute',
bottom: '0',
height: '4px',
right: right,
left: '0'
};
}
function colorGradient(colors, banded) {
return banded ? colorGradientBanded(colors) : colorGradientInterpolated(colors);
}
function createColorListHelpers() {
var addOn = function (l) {
var preset = (0, lists_1.getColorListFromName)(l[0]);
return (0, jsx_runtime_1.jsx)("div", { style: colorStripStyle({ kind: preset.type !== 'qualitative' ? 'interpolate' : 'set', colors: preset.list }) }, void 0);
};
return {
ColorPresets: {
all: action_menu_1.ActionMenu.createItemsFromSelectOptions(lists_1.ColorListOptions, { addOn: addOn }),
scale: action_menu_1.ActionMenu.createItemsFromSelectOptions(lists_1.ColorListOptionsScale, { addOn: addOn }),
set: action_menu_1.ActionMenu.createItemsFromSelectOptions(lists_1.ColorListOptionsSet, { addOn: addOn })
},
ColorsParam: param_definition_1.ParamDefinition.ObjectList({ color: param_definition_1.ParamDefinition.Color(0x0) }, function (_a) {
var color = _a.color;
return color_1.Color.toHexString(color).toUpperCase();
}),
OffsetColorsParam: param_definition_1.ParamDefinition.ObjectList({ color: param_definition_1.ParamDefinition.Color(0x0), offset: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: 1, step: 0.01 }) }, function (_a) {
var color = _a.color, offset = _a.offset;
return color_1.Color.toHexString(color).toUpperCase() + " [" + offset.toFixed(2) + "]";
}),
IsInterpolatedParam: param_definition_1.ParamDefinition.Boolean(false, { label: 'Interpolated' })
};
}
var _colorListHelpers;
function ColorListHelpers() {
if (_colorListHelpers)
return _colorListHelpers;
_colorListHelpers = createColorListHelpers();
return _colorListHelpers;
}
var ColorListControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(ColorListControl, _super);
function ColorListControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showHelp: false, show: void 0 };
_this.toggleEdit = function () { return _this.setState({ show: _this.state.show === 'edit' ? void 0 : 'edit' }); };
_this.togglePresets = function () { return _this.setState({ show: _this.state.show === 'presets' ? void 0 : 'presets' }); };
_this.selectPreset = function (item) {
if (!item)
return;
_this.setState({ show: void 0 });
var preset = (0, lists_1.getColorListFromName)(item.value);
_this.update({ kind: preset.type !== 'qualitative' ? 'interpolate' : 'set', colors: preset.list });
};
_this.colorsChanged = function (_a) {
var value = _a.value;
_this.update({
kind: _this.props.value.kind,
colors: value.map(function (c) { return c.color; })
});
};
_this.isInterpolatedChanged = function (_a) {
var value = _a.value;
_this.update({ kind: value ? 'interpolate' : 'set', colors: _this.props.value.colors });
};
_this.toggleHelp = function () { return _this.setState({ showHelp: !_this.state.showHelp }); };
return _this;
}
ColorListControl.prototype.update = function (value) {
this.props.onChange({ param: this.props.param, name: this.props.name, value: value });
};
ColorListControl.prototype.renderControl = function () {
var value = this.props.value;
// TODO: fix the button right offset
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", (0, tslib_1.__assign)({ onClick: this.toggleEdit, style: { position: 'relative', paddingRight: '33px' } }, { children: [value.colors.length === 1 ? '1 color' : value.colors.length + " colors", (0, jsx_runtime_1.jsx)("div", { style: colorStripStyle(value, '33px') }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.BookmarksOutlinedSvg, onClick: this.togglePresets, toggleState: this.state.show === 'presets', title: 'Color Presets', style: { padding: 0, position: 'absolute', right: 0, top: 0, width: '32px' } }, void 0)] }, void 0);
};
ColorListControl.prototype.renderColors = function () {
if (!this.state.show)
return null;
var _a = ColorListHelpers(), ColorPresets = _a.ColorPresets, ColorsParam = _a.ColorsParam, IsInterpolatedParam = _a.IsInterpolatedParam;
var preset = ColorPresets[this.props.param.presetKind];
if (this.state.show === 'presets')
return (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: preset, onSelect: this.selectPreset }, void 0);
var values = this.props.value.colors.map(function (color) { return ({ color: color }); });
return (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: [(0, jsx_runtime_1.jsx)(ObjectListControl, { name: 'colors', param: ColorsParam, value: values, onChange: this.colorsChanged, isDisabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0), (0, jsx_runtime_1.jsx)(BoolControl, { name: 'isInterpolated', param: IsInterpolatedParam, value: this.props.value.kind === 'interpolate', onChange: this.isInterpolatedChanged, isDisabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0)] }), void 0);
};
ColorListControl.prototype.render = function () {
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderColors()
});
};
return ColorListControl;
}(React.PureComponent));
exports.ColorListControl = ColorListControl;
var OffsetColorListControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(OffsetColorListControl, _super);
function OffsetColorListControl() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { showHelp: false, show: void 0 };
_this.toggleEdit = function () { return _this.setState({ show: _this.state.show === 'edit' ? void 0 : 'edit' }); };
_this.togglePresets = function () { return _this.setState({ show: _this.state.show === 'presets' ? void 0 : 'presets' }); };
_this.selectPreset = function (item) {
if (!item)
return;
_this.setState({ show: void 0 });
var preset = (0, lists_1.getColorListFromName)(item.value);
_this.update({ kind: preset.type !== 'qualitative' ? 'interpolate' : 'set', colors: preset.list });
};
_this.colorsChanged = function (_a) {
var value = _a.value;
var colors = value.map(function (c) { return [c.color, c.offset]; });
colors.sort(function (a, b) { return a[1] - b[1]; });
_this.update({ kind: _this.props.value.kind, colors: colors });
};
_this.isInterpolatedChanged = function (_a) {
var value = _a.value;
_this.update({ kind: value ? 'interpolate' : 'set', colors: _this.props.value.colors });
};
_this.toggleHelp = function () { return _this.setState({ showHelp: !_this.state.showHelp }); };
return _this;
}
OffsetColorListControl.prototype.update = function (value) {
this.props.onChange({ param: this.props.param, name: this.props.name, value: value });
};
OffsetColorListControl.prototype.renderControl = function () {
var value = this.props.value;
// TODO: fix the button right offset
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", (0, tslib_1.__assign)({ onClick: this.toggleEdit, style: { position: 'relative', paddingRight: '33px' } }, { children: [value.colors.length === 1 ? '1 color' : value.colors.length + " colors", (0, jsx_runtime_1.jsx)("div", { style: colorStripStyle(value, '33px') }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(common_1.IconButton, { svg: icons_1.BookmarksOutlinedSvg, onClick: this.togglePresets, toggleState: this.state.show === 'presets', title: 'Color Presets', style: { padding: 0, position: 'absolute', right: 0, top: 0, width: '32px' } }, void 0)] }, void 0);
};
OffsetColorListControl.prototype.renderColors = function () {
if (!this.state.show)
return null;
var _a = ColorListHelpers(), ColorPresets = _a.ColorPresets, OffsetColorsParam = _a.OffsetColorsParam, IsInterpolatedParam = _a.IsInterpolatedParam;
var preset = ColorPresets[this.props.param.presetKind];
if (this.state.show === 'presets')
return (0, jsx_runtime_1.jsx)(action_menu_1.ActionMenu, { items: preset, onSelect: this.selectPreset }, void 0);
var colors = this.props.value.colors;
var values = colors.map(function (color, i) {
if (Array.isArray(color))
return { color: color[0], offset: color[1] };
return { color: color, offset: i / colors.length };
});
values.sort(function (a, b) { return a.offset - b.offset; });
return (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: [(0, jsx_runtime_1.jsx)(ObjectListControl, { name: 'colors', param: OffsetColorsParam, value: values, onChange: this.colorsChanged, isDisabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0), (0, jsx_runtime_1.jsx)(BoolControl, { name: 'isInterpolated', param: IsInterpolatedParam, value: this.props.value.kind === 'interpolate', onChange: this.isInterpolatedChanged, isDisabled: this.props.isDisabled, onEnter: this.props.onEnter }, void 0)] }), void 0);
};
OffsetColorListControl.prototype.render = function () {
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderColors()
});
};
return OffsetColorListControl;
}(React.PureComponent));
exports.OffsetColorListControl = OffsetColorListControl;
var Vec3Control = /** @class */ (function (_super) {
(0, tslib_1.__extends)(Vec3Control, _super);
function Vec3Control() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { isExpanded: false };
_this.components = {
0: param_definition_1.ParamDefinition.Numeric(0, { step: _this.props.param.step }, { label: (_this.props.param.fieldLabels && _this.props.param.fieldLabels.x) || 'X' }),
1: param_definition_1.ParamDefinition.Numeric(0, { step: _this.props.param.step }, { label: (_this.props.param.fieldLabels && _this.props.param.fieldLabels.y) || 'Y' }),
2: param_definition_1.ParamDefinition.Numeric(0, { step: _this.props.param.step }, { label: (_this.props.param.fieldLabels && _this.props.param.fieldLabels.z) || 'Z' })
};
_this.componentChange = function (_a) {
var name = _a.name, value = _a.value;
var v = linear_algebra_1.Vec3.copy(linear_algebra_1.Vec3.zero(), _this.props.value);
v[+name] = value;
_this.change(v);
};
_this.toggleExpanded = function (e) {
_this.setState({ isExpanded: !_this.state.isExpanded });
e.currentTarget.blur();
};
return _this;
}
Vec3Control.prototype.change = function (value) {
this.props.onChange({ name: this.props.name, param: this.props.param, value: value });
};
Vec3Control.prototype.render = function () {
var v = this.props.value;
var label = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
var p = (0, number_1.getPrecision)(this.props.param.step || 0.01);
var value = "[" + v[0].toFixed(p) + ", " + v[1].toFixed(p) + ", " + v[2].toFixed(p) + "]";
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.ControlRow, { label: label, control: (0, jsx_runtime_1.jsx)("button", (0, tslib_1.__assign)({ onClick: this.toggleExpanded, disabled: this.props.isDisabled }, { children: value }), void 0) }, void 0), this.state.isExpanded && (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: (0, jsx_runtime_1.jsx)(ParameterControls, { params: this.components, values: v, onChange: this.componentChange, onEnter: this.props.onEnter }, void 0) }), void 0)] }, void 0);
};
return Vec3Control;
}(React.PureComponent));
exports.Vec3Control = Vec3Control;
var Mat4Control = /** @class */ (function (_super) {
(0, tslib_1.__extends)(Mat4Control, _super);
function Mat4Control() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { isExpanded: false };
_this.components = {
json: param_definition_1.ParamDefinition.Text(JSON.stringify((0, linear_algebra_1.Mat4)()), { description: 'JSON array with 4x4 matrix in a column major (j * 4 + i indexing) format' })
};
_this.componentChange = function (_a) {
var name = _a.name, value = _a.value;
var v = linear_algebra_1.Mat4.copy((0, linear_algebra_1.Mat4)(), _this.props.value);
if (name === 'json') {
linear_algebra_1.Mat4.copy(v, JSON.parse(value));
}
else {
v[+name] = value;
}
_this.change(v);
};
_this.toggleExpanded = function (e) {
_this.setState({ isExpanded: !_this.state.isExpanded });
e.currentTarget.blur();
};
return _this;
}
Mat4Control.prototype.change = function (value) {
this.props.onChange({ name: this.props.name, param: this.props.param, value: value });
};
Mat4Control.prototype.changeValue = function (idx) {
var _this = this;
return function (v) {
var m = linear_algebra_1.Mat4.copy((0, linear_algebra_1.Mat4)(), _this.props.value);
m[idx] = v;
_this.change(m);
};
};
Object.defineProperty(Mat4Control.prototype, "grid", {
get: function () {
var v = this.props.value;
var rows = [];
for (var i = 0; i < 4; i++) {
var row = [];
for (var j = 0; j < 4; j++) {
row.push((0, jsx_runtime_1.jsx)(common_1.TextInput, { numeric: true, delayMs: 50, value: linear_algebra_1.Mat4.getValue(v, i, j), onChange: this.changeValue(4 * j + i), className: 'msp-form-control', blurOnEnter: true, isDisabled: this.props.isDisabled }, j));
}
rows.push((0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-flex-row' }, { children: row }), i));
}
return (0, jsx_runtime_1.jsx)("div", (0, tslib_1.__assign)({ className: 'msp-parameter-matrix' }, { children: rows }), void 0);
},
enumerable: false,
configurable: true
});
Mat4Control.prototype.render = function () {
var v = {
json: JSON.stringify(this.props.value)
};
var label = this.props.param.label || (0, string_1.camelCaseToWords)(this.props.name);
return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(common_1.ControlRow, { label: label, control: (0, jsx_runtime_1.jsx)("button", (0, tslib_1.__assign)({ onClick: this.toggleExpanded, disabled: this.props.isDisabled }, { children: '4\u00D74 Matrix' }), void 0) }, void 0), this.state.isExpanded && (0, jsx_runtime_1.jsxs)("div", (0, tslib_1.__assign)({ className: 'msp-control-offset' }, { children: [this.grid, (0, jsx_runtime_1.jsx)(ParameterControls, { params: this.components, values: v, onChange: this.componentChange, onEnter: this.props.onEnter }, void 0)] }), void 0)] }, void 0);
};
return Mat4Control;
}(React.PureComponent));
exports.Mat4Control = Mat4Control;
var UrlControl = /** @class */ (function (_super) {
(0, tslib_1.__extends)(UrlControl, _super);
function UrlCo