Skip to content

Commit

Permalink
Merge pull request #561 from Shallowmallow/NumberStepperFloat
Browse files Browse the repository at this point in the history
Making number steppers working with decimal numbers
  • Loading branch information
ianharrigan authored Jan 8, 2024
2 parents ac1499a + 3c48fd8 commit dd0fd80
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
6 changes: 4 additions & 2 deletions haxe/ui/components/NumberStepper.hx
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,8 @@ private class ValueHelper {
if (max != null && parsedValue > max) {
valid = false;
}
if (step != null && parsedValue % step != 0) {

if (step != null && MathUtil.fmodulo(parsedValue, step) != 0) {
valid = false;
parsedValue = MathUtil.roundToNearest(parsedValue, step);
}
Expand Down Expand Up @@ -500,6 +500,7 @@ private class ValueHelper {
}
} else {
newValue += step;
newValue = MathUtil.roundToNearest(newValue, step);
}

if (max != null && newValue > max) {
Expand All @@ -525,6 +526,7 @@ private class ValueHelper {
}
} else {
newValue -= step;
newValue = MathUtil.roundToNearest(newValue, step);
}

if (min != null && newValue < min) {
Expand Down
33 changes: 31 additions & 2 deletions haxe/ui/util/MathUtil.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,47 @@ package haxe.ui.util;
class MathUtil {
public static inline var MAX_INT:Int = 2147483647; // 2**31 - 1
public static inline var MIN_INT:Int = -2147483648;
public static inline var SIGNIFICANT_DECIMAL_DIGITS:Int = 7; // 32 bit floats have 24 bits precision log10(2**24) ≈ 7.225 (for 64 bits it's 15)

public static inline function distance(x1:Float, y1:Float, x2:Float, y2:Float):Float {
return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

public static inline function precision(v:Float):Int {
var e = 1;
var p = 0;
while (Math.round(v * e) / e != v) {
e *= 10;
p++;
}
return p;
}

public static inline function fmodulo(v1:Float, v2:Float):Float {
if (!Math.isFinite(v1) || !Math.isFinite(v2)) {
return Math.NaN;
}
var p = Std.int(Math.min(SIGNIFICANT_DECIMAL_DIGITS, Math.max(precision(v1), precision(v2))));
var e = 1;
for ( i in 0...p) {
e *= 10;
}
var i1 = Math.round(v1 * e);
var i2 = Math.round(v2 * e);
return round(i1 % i2 / e, p);
}

public static inline function round(v:Float, precision:Int = 0):Float {
return Math.round(v * Math.pow(10, precision)) / Math.pow(10, precision);
return Math.fround(v * Math.pow(10, precision)) / Math.pow(10, precision);
}

public static inline function roundToNearest(v:Float, n:Float):Float {
if (!Math.isFinite(v) || !Math.isFinite(n)) {
return Math.NaN;
}
var p = Std.int(Math.min(SIGNIFICANT_DECIMAL_DIGITS, Math.max(precision(v), precision(n))));
var inv = 1.0 / n;
return Math.fround(v * inv) / inv;
return round(Math.fround(v * inv) / inv, p);
}

public static inline function clamp(v:Null<Float>, min:Null<Float>, max:Null<Float>):Float {
Expand Down

0 comments on commit dd0fd80

Please sign in to comment.