diff --git a/src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java b/src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java index ced0a85..0b59cac 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java +++ b/src/main/java/com/flowingcode/vaadin/addons/imagecrop/Crop.java @@ -34,7 +34,7 @@ * @param width the width of the cropped area * @param height the height of the cropped area */ -public record Crop(String unit, int x, int y, int width, int height) { +public record Crop(String unit, double x, double y, double width, double height) { /** * Returns a string representation of the Crop object. diff --git a/src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java b/src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java index fa05a70..3181f1e 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java +++ b/src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java @@ -223,9 +223,9 @@ public void setCrop(Crop crop) { *
* Once the image has loaded, the crop is normalized to a percentage of the * image's natural size, so the returned unit is {@code %} even when - * {@link #setCrop(Crop)} was given a {@code px} crop. Because {@link Crop} holds - * integer values, those percentages are rounded to whole units, which on a large - * image is coarser than the configured pixel values. + * {@link #setCrop(Crop)} was given a {@code px} crop. The percentages keep their + * fractional part, so passing the returned crop back to {@link #setCrop(Crop)} + * does not move the selection. * * @return the crop dimensions */ diff --git a/src/test/java/com/flowingcode/vaadin/addons/imagecrop/test/ImageCropTest.java b/src/test/java/com/flowingcode/vaadin/addons/imagecrop/test/ImageCropTest.java index faac7c7..4baec3c 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/imagecrop/test/ImageCropTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/imagecrop/test/ImageCropTest.java @@ -21,7 +21,6 @@ import com.vaadin.flow.component.UI; import com.vaadin.flow.server.streams.DownloadHandler; import com.vaadin.flow.server.streams.DownloadResponse; - public class ImageCropTest { private ImageCrop imageCrop; @@ -89,6 +88,20 @@ public void testSetAndGetCrop() { assertEquals(expectedCrop, imageCrop.getCrop()); } + @Test + public void testGetCropKeepsSubPercentPrecision() { + // the client syncs the crop as a "%" crop with fractional values; on a + // 4000px-wide image 1% is 40px, so dropping the fraction moves the selection + Crop expectedCrop = new Crop("%", 12.3456, 7.89, 33.3333, 50.125); + imageCrop.setCrop(expectedCrop); + + Crop crop = imageCrop.getCrop(); + assertEquals(expectedCrop, crop); + + imageCrop.setCrop(crop); + assertEquals(crop, imageCrop.getCrop()); + } + @Test public void testSetAndGetAspect() { Double expectedAspect = 16.0 / 9.0;