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.tsx183
1 files changed, 183 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..5e5a60edd
--- /dev/null
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -0,0 +1,183 @@
+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";
+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 && !isNaN(this.props.value)) {
+ if (this.props.mode == "Freeform") {
+ if (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>
+ )
+ }
+};