aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx')
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
new file mode 100644
index 000000000..d595a499e
--- /dev/null
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -0,0 +1,179 @@
+import { TextField, InputAdornment } from '@mui/material';
+import { Doc } from '../../../../fields/Doc';
+import React = require('react');
+import TaskAltIcon from '@mui/icons-material/TaskAlt';
+import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
+import { isNumber } from 'lodash';
+export interface IInputProps {
+ label?: JSX.Element;
+ lowerBound: number;
+ dataDoc: Doc;
+ prop: string;
+ step: number;
+ unit: string;
+ upperBound: number;
+ value: number | string | Array<number | string>;
+ correctValue?: number;
+ showIcon?: boolean;
+ effect?: (val: number) => any;
+ radianEquivalent?: boolean;
+ small?: boolean;
+ mode?: string;
+ update?: boolean;
+ labelWidth?: string;
+}
+
+interface IState {
+ tempValue: string | number | (string | number)[];
+ tempRadianValue: number;
+ width: string;
+ margin: string;
+}
+
+export default class InputField extends React.Component<IInputProps, IState> {
+ constructor(props: any) {
+ super(props);
+ this.state = {
+ tempValue: this.props.mode != 'Freeform' && !this.props.showIcon ? 0 : this.props.value,
+ tempRadianValue: this.props.mode != 'Freeform' && !this.props.showIcon ? 0 : (Number(this.props.value) * Math.PI) / 180,
+ width: this.props.small ? '6em' : '7em',
+ margin: this.props.small ? '0px' : '10px',
+ };
+ }
+
+ epsilon: number = 0.01;
+
+ componentDidMount(): void {
+ this.setState({ tempValue: Number(this.props.value) });
+ }
+
+ componentDidUpdate(prevProps: Readonly<IInputProps>, prevState: Readonly<IState>, snapshot?: any): void {
+ if (prevProps.value != this.props.value && isNumber(this.props.value) && !isNaN(this.props.value)) {
+ if (this.props.mode == 'Freeform') {
+ if (isNumber(this.state.tempValue) && Math.abs(this.state.tempValue - Number(this.props.value)) > 1) {
+ this.setState({ tempValue: Number(this.props.value) });
+ }
+ }
+ }
+ if (prevProps.update != this.props.update) {
+ this.externalUpdate();
+ }
+ }
+
+ externalUpdate = () => {
+ this.setState({ tempValue: Number(this.props.value) });
+ this.setState({ tempRadianValue: (Number(this.props.value) * Math.PI) / 180 });
+ };
+
+ onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+ let value = event.target.value == '' ? 0 : Number(event.target.value);
+ if (value > this.props.upperBound) {
+ value = this.props.upperBound;
+ } else if (value < this.props.lowerBound) {
+ value = this.props.lowerBound;
+ }
+ if (this.props.prop != '') {
+ this.props.dataDoc[this.props.prop] = value;
+ }
+ this.setState({ tempValue: event.target.value == '' ? event.target.value : value });
+ this.setState({ tempRadianValue: (value * Math.PI) / 180 });
+ if (this.props.effect) {
+ this.props.effect(value);
+ }
+ };
+
+ onChangeRadianValue = (event: React.ChangeEvent<HTMLInputElement>) => {
+ let value = event.target.value === '' ? 0 : Number(event.target.value);
+ if (value > 2 * Math.PI) {
+ value = 2 * Math.PI;
+ } else if (value < 0) {
+ value = 0;
+ }
+ if (this.props.prop != '') {
+ this.props.dataDoc[this.props.prop] = (value * 180) / Math.PI;
+ }
+ this.setState({ tempValue: (value * 180) / Math.PI });
+ this.setState({ tempRadianValue: value });
+ if (this.props.effect) {
+ this.props.effect((value * 180) / Math.PI);
+ }
+ };
+
+ render() {
+ return (
+ <div
+ style={{
+ display: 'flex',
+ lineHeight: '1.5',
+ textAlign: 'right',
+ alignItems: 'center',
+ }}>
+ {this.props.label && (
+ <div
+ style={{
+ marginTop: '0.3em',
+ marginBottom: '-0.5em',
+ width: this.props.labelWidth ?? '2em',
+ }}>
+ {this.props.label}
+ </div>
+ )}
+ <TextField
+ type="number"
+ variant="standard"
+ value={this.state.tempValue}
+ onChange={this.onChange}
+ sx={{
+ height: '1em',
+ width: this.state.width,
+ marginLeft: this.state.margin,
+ zIndex: 'modal',
+ }}
+ inputProps={{
+ step: this.props.step,
+ min: this.props.lowerBound,
+ max: this.props.upperBound,
+ type: 'number',
+ }}
+ InputProps={{
+ startAdornment: (
+ <InputAdornment position="start">
+ {Math.abs(Number(this.props.value) - (this.props.correctValue ?? 0)) < this.epsilon && this.props.showIcon && <TaskAltIcon color={'success'} />}
+ {Math.abs(Number(this.props.value) - (this.props.correctValue ?? 0)) >= this.epsilon && this.props.showIcon && <ErrorOutlineIcon color={'error'} />}
+ </InputAdornment>
+ ),
+ endAdornment: <InputAdornment position="end">{this.props.unit}</InputAdornment>,
+ }}
+ />
+ {this.props.radianEquivalent && (
+ <div style={{ marginTop: '0.3em', marginBottom: '-0.5em', width: '1em' }}>
+ <p>≈</p>
+ </div>
+ )}
+ {this.props.radianEquivalent && (
+ <TextField
+ type="number"
+ variant="standard"
+ value={this.state.tempRadianValue}
+ onChange={this.onChangeRadianValue}
+ sx={{
+ height: '1em',
+ width: this.state.width,
+ marginLeft: this.state.margin,
+ zIndex: 'modal',
+ }}
+ inputProps={{
+ step: Math.PI / 8,
+ min: 0,
+ max: 2 * Math.PI,
+ type: 'number',
+ }}
+ InputProps={{
+ endAdornment: <InputAdornment position="end">rad</InputAdornment>,
+ }}
+ />
+ )}
+ </div>
+ );
+ }
+}