11import { Label } from 'app/components/Label' ;
22import { ControlledInput } from 'app/components/ControlledInput' ;
33import { FaMinus , FaPlus } from 'react-icons/fa' ;
4- import { IMPERIAL_UNITS , METRIC_UNITS } from 'app/constants' ;
5- import store from 'app/store' ;
64import Button from 'app/components/Button' ;
5+ import { toFixedIfNecessary } from 'app/lib/rounding' ;
76
87interface JogInputProps {
98 label : string ;
@@ -12,47 +11,70 @@ interface JogInputProps {
1211}
1312
1413export const JogInput = ( { label, currentValue, onChange } : JogInputProps ) => {
15- const units = store . get ( 'workspace.units' , METRIC_UNITS ) ;
1614 const getStep = ( increment = false ) => {
1715 let step ;
16+ const digitCount = Math . floor ( currentValue ) . toString ( ) . length ; // number of whole digits
17+ const split = currentValue . toString ( ) . split ( '.' ) ;
18+ const digitCountDecimal = split [ 1 ] ? split [ 1 ] . length : 0 ; // number of digits after the decimal point
19+ const x = Number ( '1' . padEnd ( digitCount , '0' ) ) ; // ex. currentValue = 234, x = 100
20+ const y = Number ( '1' . padEnd ( digitCount - 1 , '0' ) ) ; // ex. currentValue = 234, y = 10
21+ const xD = Number ( '0.' + '1' . padStart ( digitCountDecimal , '0' ) ) ; // ex. currentValue = 0.02, x = 0.01
22+ const yD = Number ( '0.' + '1' . padStart ( digitCountDecimal + 1 , '0' ) ) ; // ex. currentValue = 0.02, x = 0.001
1823
1924 if ( currentValue === 0 ) {
2025 if ( ! increment ) {
21- return 0 ;
26+ return 0 ; // don't decrease less than 0
27+ }
28+ return 0.1 ; // add 0.1
29+ } else if ( currentValue < 1 || ( ! increment && currentValue === 1 ) ) {
30+ if ( ! increment && currentValue - xD < xD ) {
31+ // ex. 0.01 - 0.01 < 0.01
32+ step = yD ; // ex. currentValue = 0.01, step = 0.001
33+ } else {
34+ step = xD ; // ex. currentValue = 0.02, step = 0.01
2235 }
23- return 0.1 ;
24- }
25- if ( currentValue < 0.1 ) {
26- step = 0.01 ;
27- } else if ( currentValue < 1 ) {
28- step = 0.1 ;
29- } else if ( currentValue < 10 ) {
30- step = 1 ;
31- } else if ( currentValue < 100 ) {
32- step = 10 ;
33- } else if ( currentValue < 1000 ) {
34- step = 100 ;
35- } else if ( currentValue < 10000 ) {
36- step = 1000 ;
3736 } else {
38- step = 10000 ;
39- }
40-
41- if ( ! increment && currentValue - step <= 0 ) {
42- if ( step !== 0.001 ) {
43- step /= 10 ;
37+ if ( ! increment && currentValue - x < x ) {
38+ // ex. 110 - 100 < 100
39+ step = y ; // ex. currentValue = 110, step = 10
4440 } else {
45- return 0 ;
41+ step = x ; // ex. currentValue = 210, step = 100
4642 }
4743 }
44+
45+ if ( step < 0.001 ) {
46+ return 0 ; // make sure it can't go lower than 0.001
47+ }
4848 return step ;
4949 } ;
5050
51- const formatNewValue = ( newValue : number ) => {
52- if ( units === IMPERIAL_UNITS ) {
53- return Number ( newValue . toFixed ( 3 ) ) ;
51+ // rounds the values
52+ const formatNewValue = ( newValue : number , increment = false ) => {
53+ // sometimes js math messes up the value. ex. 0.7 when pressing + will give you 0.799999999.
54+ // this causes problems for this rounding scheme.
55+ // so we need to round to 4 decimal places first to get rid of any infinite decimals.
56+ // I chose 4 because it's 1 more than our max decimal places, so it shouldn't affect the number we want to display.
57+ newValue = Number ( newValue . toFixed ( 4 ) ) ;
58+ if ( newValue < 1 ) {
59+ return toFixedIfNecessary ( newValue , 3 ) ; // round to max 3 decimal places
60+ } else if ( newValue < 10 ) {
61+ return toFixedIfNecessary ( newValue , 2 ) ; // round to max 2 decimal places
5462 } else {
55- return Number ( newValue . toFixed ( 3 ) ) ;
63+ const digitCount = newValue . toFixed ( 0 ) . length ;
64+ const x = Number ( '1' . padEnd ( digitCount - 1 , '0' ) ) ; // ex. newValue = 100, x = 10
65+ const lower = Number ( '1' . padEnd ( digitCount , '0' ) ) ; // 10, 100, 1000, etc
66+ const higher = Number ( '2' . padEnd ( digitCount , '0' ) ) ; // 20, 200, 2000, etc
67+
68+ if ( newValue >= lower && newValue < higher ) {
69+ // ex. >= 100 && < 200
70+ return increment
71+ ? Math . floor ( newValue / x ) * x // ex. 115->120
72+ : Math . ceil ( newValue / x ) * x ; // ex. 115->110
73+ } else {
74+ // ex. increment: 45.1->55, 45.5->56
75+ // ex. decrement: 45.1->35, 45.5->36
76+ return Math . round ( newValue / x ) * x ;
77+ }
5678 }
5779 } ;
5880
@@ -82,7 +104,9 @@ export const JogInput = ({ label, currentValue, onChange }: JogInputProps) => {
82104 type = "button"
83105 onClick = { ( e ) => {
84106 e . preventDefault ( ) ;
85- onChange ( formatNewValue ( currentValue + getStep ( true ) ) ) ;
107+ onChange (
108+ formatNewValue ( currentValue + getStep ( true ) , true ) ,
109+ ) ;
86110 } }
87111 size = "mini"
88112 icon = { < FaPlus /> }
0 commit comments