jsketcher/web/app/sketcher/components/ConstraintEditor.jsx

135 lines
3.6 KiB
JavaScript

import React, {useCallback, useContext, useEffect, useState} from 'react';
import NumberControl from "ui/components/controls/NumberControl";
import Stack from "ui/components/Stack";
import ButtonGroup from "ui/components/controls/ButtonGroup";
import Button from "ui/components/controls/Button";
import {useStream} from "ui/effects";
import CheckboxControl from "ui/components/controls/CheckboxControl";
import Window from "ui/components/Window";
import Field from "ui/components/controls/Field";
import Label from "ui/components/controls/Label";
import {EMPTY_OBJECT} from "gems/objects";
import {SketcherAppContext} from "./SketcherAppContext";
export function ConstraintEditor() {
const req = useStream(ctx => ctx.ui.$constraintEditRequest);
const [values, setValues] = useState(null);
useEffect(() => {
setValues(req && {...req.constraint.constants});
return () => {
if (req) {
viewer.unHighlight(req.constraint.objects);
viewer.refresh();
}
}
}, [req]);
const {viewer} = useContext(SketcherAppContext);
const setValue = (name, value) => {
setValues({...values, [name]: value});
};
if (!req || !values) {
return null;
}
const {constraint, onCancel, onApply} = req;
const highlight = () => {
viewer.highlight(constraint.objects, true);
viewer.refresh();
};
const unHighlight = () => {
viewer.unHighlightAll();
viewer.refresh();
};
const apply = () => {
Object.keys(constraint.schema.constants).map(name => {
const val = values[name];
if (val !== undefined) {
constraint.updateConstant(name, val + '');
}
});
onApply();
};
return <Window initWidth={250} initLeft={5} initTop={5} title={constraint.schema.name} onClose={onCancel}
onEnterPressed={onApply}
onEscapePressed={onCancel}
onMouseEnter={highlight}
onMouseLeave={unHighlight}>
<Stack>
{constraint.constantKeys
.filter(key => !constraint.schema.constants[key].readOnly)
.sort().map(name => {
const def = constraint.schema.constants[name];
const presentation = def.presentation || EMPTY_OBJECT;
const type = presentation.type || def.type;
const onChange = value => setValue(name, (presentation.transformIn||transformInByType(type))(value));
const val = (presentation.transformOut||transformOutByType(type))(values[name]);
return <Field key={presentation.label||name}>
<Label>{name}</Label>
{
(() => {
if (type === 'number') {
return <NumberControl value={val} onChange={onChange}/>
} else if (type === 'boolean') {
return <CheckboxControl value={val} onChange={onChange}/>
} else {
return <span>{val}</span>;
}
})()
}
</Field>
})}
<ButtonGroup>
<Button onClick={onCancel}>CANCEL</Button>
<Button type='accent' onClick={apply}>APPLY</Button>
</ButtonGroup>
</Stack>
</Window>;
}
export function showConstraintEditorUI(rqStream, constraint, onApply) {
rqStream.next({
constraint,
onCancel: () => rqStream.next(null),
onApply: () => {
rqStream.next(null);
onApply();
}
});
}
const NO_TR = v => v;
function transformInByType(type) {
if ('boolean' === type) {
return value => value ? 'true' : 'false';
}
return NO_TR;
}
function transformOutByType(type) {
if ('boolean' === type) {
return value => value === 'true';
}
return NO_TR;
}