diff options
Diffstat (limited to 'src')
3 files changed, 186 insertions, 6 deletions
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx index 35a7ee346..5b9d8f415 100644 --- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx @@ -4,8 +4,6 @@ import React = require('react'); import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { observer } from 'mobx-react'; import "./PhysicsSimulationBox.scss"; -import Weight from "./PhysicsSimulationWeight"; -import Wall from "./PhysicsSimulationWall" import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { CheckBox } from "../search/CheckBox"; import PauseIcon from "@mui/icons-material/Pause"; @@ -33,9 +31,8 @@ import { Stack, } from "@mui/material"; import Typography from "@mui/material/Typography"; -import React, { useEffect, useState } from "react"; import "./App.scss"; -import { InputField } from "./InputField"; +import { InputField } from "./PhysicsSimulationInputField"; import questions from "./PhysicsSimulationQuestions.json"; import tutorials from "./PhysicsSimulationTutorial.json"; import { IWallProps, Wall } from "./Wall"; diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx new file mode 100644 index 000000000..91b0ad84c --- /dev/null +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx @@ -0,0 +1,184 @@ +import { useState, useEffect } from "react"; +import { TextField, InputAdornment } from "@mui/material"; + +import TaskAltIcon from "@mui/icons-material/TaskAlt"; +import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"; +export interface IInputProps { + label?: JSX.Element; + lowerBound: number; + changeValue: (val: number) => any; + 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; +} + +export const InputField = (props: IInputProps) => { + const { + changeValue, + correctValue, + effect, + label, + lowerBound, + mode, + radianEquivalent, + showIcon, + small, + step, + unit, + upperBound, + value, + update, + labelWidth, + } = props; + let epsilon: number = 0.01; + + let width = small ? "6em" : "7em"; + let margin = small ? "0px" : "10px"; + + const [tempValue, setTempValue] = useState<any>( + mode != "Freeform" && !showIcon ? 0 : value + ); + + const [tempRadianValue, setTempRadianValue] = useState( + mode != "Freeform" && !showIcon ? 0 : (Number(value) * Math.PI) / 180 + ); + + useEffect(() => { + if (mode == "Freeform") { + if (Math.abs(tempValue - Number(value)) > 1) { + setTempValue(Number(value)); + } + } + }, [value]); + + const externalUpdate = () => { + changeValue(Number(value)); + setTempValue(Number(value)); + setTempRadianValue((Number(value) * Math.PI) / 180); + }; + + useEffect(() => { + externalUpdate(); + }, [update]); + + const onChange = (event: React.ChangeEvent<HTMLInputElement>) => { + let value = event.target.value == "" ? 0 : Number(event.target.value); + if (value > upperBound) { + value = upperBound; + } else if (value < lowerBound) { + value = lowerBound; + } + changeValue(value); + setTempValue(event.target.value == "" ? event.target.value : value); + setTempRadianValue((value * Math.PI) / 180); + if (effect) { + effect(value); + } + }; + + const 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; + } + changeValue((value * 180) / Math.PI); + setTempValue((value * 180) / Math.PI); + setTempRadianValue(value); + if (effect) { + effect((value * 180) / Math.PI); + } + }; + + return ( + <div + style={{ + display: "flex", + lineHeight: "1.5", + textAlign: "right", + alignItems: "center", + }} + > + {label && ( + <div + style={{ + marginTop: "0.3em", + marginBottom: "-0.5em", + width: labelWidth ?? "2em", + }} + > + {label} + </div> + )} + <TextField + type="number" + variant="standard" + value={tempValue} + onChange={onChange} + sx={{ + height: "1em", + width: { width }, + marginLeft: { margin }, + zIndex: "modal", + }} + inputProps={{ + step: step, + min: lowerBound, + max: upperBound, + type: "number", + }} + InputProps={{ + startAdornment: ( + <InputAdornment position="start"> + {Math.abs(Number(value) - (correctValue ?? 0)) < epsilon && + showIcon && <TaskAltIcon color={"success"} />} + {Math.abs(Number(value) - (correctValue ?? 0)) >= epsilon && + showIcon && <ErrorOutlineIcon color={"error"} />} + </InputAdornment> + ), + endAdornment: <InputAdornment position="end">{unit}</InputAdornment>, + }} + /> + {radianEquivalent && ( + <div + style={{ marginTop: "0.3em", marginBottom: "-0.5em", width: "1em" }} + > + <p>≈</p> + </div> + )} + {radianEquivalent && ( + <TextField + type="number" + variant="standard" + value={tempRadianValue} + onChange={onChangeRadianValue} + sx={{ + height: "1em", + width: { width }, + marginLeft: { margin }, + zIndex: "modal", + }} + inputProps={{ + step: Math.PI / 8, + min: 0, + max: 2 * Math.PI, + type: "number", + }} + InputProps={{ + endAdornment: <InputAdornment position="end">rad</InputAdornment>, + }} + /> + )} + </div> + ); +}; diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx index c24438e19..3feec1ecb 100644 --- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx +++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx @@ -1,8 +1,7 @@ import { Doc } from '../../../../fields/Doc'; import React = require('react'); -import { useEffect, useState } from "react"; import { IWallProps } from "./PhysicsSimulationWall"; -import "./Weight.scss"; +import "./PhysicsSimulationWeight.scss"; export interface IForce { description: string; |