From f63695b96f50a0d189d5d9dcc4dc79d267f58ca1 Mon Sep 17 00:00:00 2001 From: hneemann Date: Mon, 25 Jan 2021 12:58:57 +0100 Subject: [PATCH] improved float dragging --- .../de/neemann/digital/core/IntFormat.java | 23 +++++++++++++++---- .../digital/draw/shapes/InputShape.java | 13 +++++++---- .../neemann/digital/core/IntFormatTest.java | 22 ++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/neemann/digital/core/IntFormat.java b/src/main/java/de/neemann/digital/core/IntFormat.java index a18597e46..05021a41f 100644 --- a/src/main/java/de/neemann/digital/core/IntFormat.java +++ b/src/main/java/de/neemann/digital/core/IntFormat.java @@ -508,14 +508,27 @@ public enum IntFormat { } @Override - public long dragValue(long initial, int bits, double inc) { - double dif = Math.signum(inc) * (Math.exp(Math.abs(inc * 10)) - 1); + public long dragValue(long initialInt, int bits, double inc) { + double initial; if (bits == 32) - return Float.floatToIntBits((float) (Float.intBitsToFloat((int) initial) + dif)); + initial = Float.intBitsToFloat((int) initialInt); else if (bits == 64) - return Double.doubleToLongBits(Double.longBitsToDouble(initial) + dif); + initial = Double.longBitsToDouble(initialInt); else - return initial; + return HEX_FORMATTER.dragValue(initialInt, bits, inc); + + if (!Double.isFinite(initial)) + initial = 0; + + double fac = Math.exp(Math.abs(inc) * 15) / 1000; + double delta = Math.abs(initial == 0 ? 1 : initial) * fac * Math.signum(inc); + double exp = Math.pow(10, Math.floor(Math.log10(Math.abs(delta)))); + double val = Math.round((initial + delta) / exp) * exp; + + if (bits == 32) + return Float.floatToIntBits((float) val); + else + return Double.doubleToLongBits(val); } } diff --git a/src/main/java/de/neemann/digital/draw/shapes/InputShape.java b/src/main/java/de/neemann/digital/draw/shapes/InputShape.java index 5d2abc21f..ecec001da 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/InputShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/InputShape.java @@ -181,11 +181,14 @@ public class InputShape implements Shape { startValue = value.getValue(); lastValueSet = startValue; } else { - double inc = ((double) (startPos.y - posOnScreen.y)) / SLIDER_HEIGHT; - long val = formatter.dragValue(startValue, value.getBits(), inc); - if (val != lastValueSet) { - modelSync.modify(() -> value.setValue(val)); - lastValueSet = val; + int dy = startPos.y - posOnScreen.y; + if (dy != 0) { + double inc = ((double) dy) / SLIDER_HEIGHT; + long val = formatter.dragValue(startValue, value.getBits(), inc); + if (val != lastValueSet) { + modelSync.modify(() -> value.setValue(val)); + lastValueSet = val; + } } } } diff --git a/src/test/java/de/neemann/digital/core/IntFormatTest.java b/src/test/java/de/neemann/digital/core/IntFormatTest.java index a26598ae5..61ba5e6c6 100644 --- a/src/test/java/de/neemann/digital/core/IntFormatTest.java +++ b/src/test/java/de/neemann/digital/core/IntFormatTest.java @@ -29,6 +29,7 @@ public class IntFormatTest extends TestCase { } public void testBin() { + assertFalse(IntFormat.bin.dependsOnAttributes()); ValueFormatter vf = IntFormat.bin.createFormatter(null); assertEquals("0b1", vf.formatToView(new Value(1, 1))); assertEquals("0b01", vf.formatToView(new Value(1, 2))); @@ -39,6 +40,9 @@ public class IntFormatTest extends TestCase { } public void testDec() { + assertFalse(IntFormat.dec.dependsOnAttributes()); + assertFalse(IntFormat.decSigned.dependsOnAttributes()); + assertEquals("3", IntFormat.dec.createFormatter(null).formatToView(new Value(-1, 2))); assertEquals("-1", IntFormat.decSigned.createFormatter(null).formatToView(new Value(-1, 2))); } @@ -125,6 +129,7 @@ public class IntFormatTest extends TestCase { } public void testStrLen() { + assertFalse(IntFormat.hex.dependsOnAttributes()); ValueFormatter vf = IntFormat.hex.createFormatter(null); assertEquals(6, vf.strLen(16)); assertEquals(6, vf.strLen(15)); @@ -165,4 +170,21 @@ public class IntFormatTest extends TestCase { assertEquals(5, vf.strLen(9)); assertEquals(6, vf.strLen(10)); } + + + public void testDragFloat() { + assertFalse(IntFormat.floating.dependsOnAttributes()); + ValueFormatter f = IntFormat.floating.createFormatter(null); + checkFloatDrag(f, 1f, 1.001f, 0.004); + checkFloatDrag(f, 1f, 1.002f, 0.04); + checkFloatDrag(f, 1f, 1.4f, 0.4); + checkFloatDrag(f, 1f, 3000f, 1); + checkFloatDrag(f, 1f, -3000f, -1); + } + + private void checkFloatDrag(ValueFormatter f, float initial, float expected, double inc) { + long d = f.dragValue(Float.floatToIntBits(initial), 32, inc); + float result = Float.intBitsToFloat((int) d); + assertEquals(expected, result, 1e-5); + } }