floatLineComponent.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { PropertyChangedEvent } from "../../propertyChangedEvent";
  4. import { LockObject } from "../tabs/propertyGrids/lockObject";
  5. interface IFloatLineComponentProps {
  6. label: string;
  7. target: any;
  8. propertyName: string;
  9. lockObject?: LockObject;
  10. onChange?: (newValue: number) => void;
  11. isInteger?: boolean;
  12. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  13. additionalClass?: string;
  14. step?: string,
  15. digits?: number
  16. }
  17. export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
  18. private _localChange = false;
  19. private _store: number;
  20. constructor(props: IFloatLineComponentProps) {
  21. super(props);
  22. let currentValue = this.props.target[this.props.propertyName];
  23. this.state = { value: currentValue ? (this.props.isInteger ? currentValue.toFixed(0) : currentValue.toFixed(this.props.digits || 3)) : "0" };
  24. this._store = currentValue;
  25. }
  26. componentWillUnmount() {
  27. this.unlock();
  28. }
  29. shouldComponentUpdate(nextProps: IFloatLineComponentProps, nextState: { value: string }) {
  30. if (this._localChange) {
  31. this._localChange = false;
  32. return true;
  33. }
  34. const newValue = nextProps.target[nextProps.propertyName];
  35. const newValueString = newValue ? this.props.isInteger ? newValue.toFixed(0) : newValue.toFixed(this.props.digits || 3) : "0";
  36. if (newValueString !== nextState.value) {
  37. nextState.value = newValueString;
  38. return true;
  39. }
  40. return false;
  41. }
  42. raiseOnPropertyChanged(newValue: number, previousValue: number) {
  43. if (this.props.onChange) {
  44. this.props.onChange(newValue);
  45. }
  46. if (!this.props.onPropertyChangedObservable) {
  47. return;
  48. }
  49. this.props.onPropertyChangedObservable.notifyObservers({
  50. object: this.props.target,
  51. property: this.props.propertyName,
  52. value: newValue,
  53. initialValue: previousValue
  54. });
  55. }
  56. updateValue(valueString: string) {
  57. if (/[^0-9\.\-]/g.test(valueString)) {
  58. return;
  59. }
  60. let valueAsNumber: number;
  61. if (this.props.isInteger) {
  62. valueAsNumber = parseInt(valueString);
  63. } else {
  64. valueAsNumber = parseFloat(valueString);
  65. }
  66. this._localChange = true;
  67. this.setState({ value: valueString });
  68. if (isNaN(valueAsNumber)) {
  69. return;
  70. }
  71. this.raiseOnPropertyChanged(valueAsNumber, this._store);
  72. this.props.target[this.props.propertyName] = valueAsNumber;
  73. this._store = valueAsNumber;
  74. }
  75. lock() {
  76. if (this.props.lockObject) {
  77. this.props.lockObject.lock = true;
  78. }
  79. }
  80. unlock() {
  81. if (this.props.lockObject) {
  82. this.props.lockObject.lock = false;
  83. }
  84. }
  85. render() {
  86. return (
  87. <div className={this.props.additionalClass ? this.props.additionalClass + " floatLine" : "floatLine"}>
  88. <div className="label">
  89. {this.props.label}
  90. </div>
  91. <div className="value">
  92. <input type="number" step={this.props.step || "0.01"} className="numeric-input" value={this.state.value} onBlur={() => this.unlock()} onFocus={() => this.lock()} onChange={evt => this.updateValue(evt.target.value)} />
  93. </div>
  94. </div>
  95. );
  96. }
  97. }