Bug 573695 - Dynamic scaling in freeze state causes rendering glitches

Change-Id: If51f14715bf35b3c4560ee0b87b4a42177c190d3
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
diff --git a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/freeze/CompositeFreezeLayerHideShowTest.java b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/freeze/CompositeFreezeLayerHideShowTest.java
index f2301fa..9d19cea 100644
--- a/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/freeze/CompositeFreezeLayerHideShowTest.java
+++ b/org.eclipse.nebula.widgets.nattable.core.test/src/org/eclipse/nebula/widgets/nattable/freeze/CompositeFreezeLayerHideShowTest.java
@@ -33,6 +33,8 @@
 import org.eclipse.nebula.widgets.nattable.hideshow.command.ShowAllColumnsCommand;
 import org.eclipse.nebula.widgets.nattable.hideshow.command.ShowAllRowsCommand;
 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.FixedScalingDpiConverter;
+import org.eclipse.nebula.widgets.nattable.layer.command.ConfigureScalingCommand;
 import org.eclipse.nebula.widgets.nattable.layer.event.RowDeleteEvent;
 import org.eclipse.nebula.widgets.nattable.layer.event.RowInsertEvent;
 import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
@@ -101,6 +103,9 @@ public Rectangle getClientArea() {
             }
 
         });
+
+        this.compositeFreezeLayer.doCommand(
+                new ConfigureScalingCommand(new FixedScalingDpiConverter(96)));
     }
 
     @Test
@@ -1656,7 +1661,62 @@ public void testFreezeHideShowRowPositionViewportRegionBottomEdge() {
         reset();
     }
 
+    @Test
+    public void testFreezeColumnDynamicScale() {
+        this.compositeFreezeLayer.doCommand(
+                new FreezeColumnCommand(this.compositeFreezeLayer, 1));
+
+        assertEquals(2, this.freezeLayer.getColumnCount());
+        assertEquals(0, this.freezeLayer.getRowCount());
+        assertEquals(1, this.freezeLayer.getBottomRightPosition().columnPosition);
+        assertEquals(-1, this.freezeLayer.getBottomRightPosition().rowPosition);
+
+        assertEquals(3, this.viewportLayer.getColumnCount());
+        assertEquals(5, this.viewportLayer.getRowCount());
+        assertEquals(2, this.viewportLayer.getMinimumOriginColumnPosition());
+        assertEquals(0, this.viewportLayer.getMinimumOriginRowPosition());
+        assertEquals(200, this.viewportLayer.getMinimumOrigin().getX());
+        assertEquals(0, this.viewportLayer.getMinimumOrigin().getY());
+
+        this.compositeFreezeLayer.doCommand(
+                new ConfigureScalingCommand(new FixedScalingDpiConverter(144)));
+
+        assertEquals(300, this.viewportLayer.getMinimumOrigin().getX());
+        assertEquals(0, this.viewportLayer.getMinimumOrigin().getY());
+
+        reset();
+    }
+
+    @Test
+    public void testFreezeRowDynamicScale() {
+        this.compositeFreezeLayer.doCommand(
+                new FreezeRowCommand(this.compositeFreezeLayer, 1));
+
+        assertEquals(0, this.freezeLayer.getColumnCount());
+        assertEquals(2, this.freezeLayer.getRowCount());
+        assertEquals(-1, this.freezeLayer.getBottomRightPosition().columnPosition);
+        assertEquals(1, this.freezeLayer.getBottomRightPosition().rowPosition);
+
+        assertEquals(5, this.viewportLayer.getColumnCount());
+        assertEquals(3, this.viewportLayer.getRowCount());
+        assertEquals(0, this.viewportLayer.getMinimumOriginColumnPosition());
+        assertEquals(2, this.viewportLayer.getMinimumOriginRowPosition());
+        assertEquals(0, this.viewportLayer.getMinimumOrigin().getX());
+        assertEquals(40, this.viewportLayer.getMinimumOrigin().getY());
+
+        this.compositeFreezeLayer.doCommand(
+                new ConfigureScalingCommand(new FixedScalingDpiConverter(144)));
+
+        assertEquals(0, this.viewportLayer.getMinimumOrigin().getX());
+        assertEquals(60, this.viewportLayer.getMinimumOrigin().getY());
+
+        reset();
+    }
+
     private void reset() {
+        this.compositeFreezeLayer.doCommand(
+                new ConfigureScalingCommand(new FixedScalingDpiConverter(96)));
+
         this.compositeFreezeLayer.doCommand(new UnFreezeGridCommand());
 
         assertEquals(0, this.freezeLayer.getColumnCount());
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ViewportLayer.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ViewportLayer.java
index 6406a0b..03299ca 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ViewportLayer.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/viewport/ViewportLayer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2020 Original authors and others.
+ * Copyright (c) 2012, 2021 Original authors and others.
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0
@@ -21,6 +21,7 @@
 import org.eclipse.nebula.widgets.nattable.group.command.ViewportSelectColumnGroupCommandHandler;
 import org.eclipse.nebula.widgets.nattable.group.command.ViewportSelectRowGroupCommandHandler;
 import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
+import org.eclipse.nebula.widgets.nattable.layer.IDpiConverter;
 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
 import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
 import org.eclipse.nebula.widgets.nattable.layer.command.ConfigureScalingCommand;
@@ -124,6 +125,9 @@ public class ViewportLayer extends AbstractLayerTransform implements IUniqueInde
 
     private MoveViewportRunnable edgeHoverRunnable;
 
+    private IDpiConverter horizontalDpiConverter;
+    private IDpiConverter verticalDpiConverter;
+
     public ViewportLayer(IUniqueIndexLayer underlyingLayer) {
         super(underlyingLayer);
         this.scrollableLayer = underlyingLayer;
@@ -1118,6 +1122,46 @@ public boolean doCommand(ILayerCommand command) {
         } else if (command instanceof ConfigureScalingCommand) {
             invalidateHorizontalStructure();
             invalidateVerticalStructure();
+
+            int originDpiX = 0;
+            int originDpiY = 0;
+            int minimumDpiX = 0;
+            int minimumDpiY = 0;
+            int savedDpiX = 0;
+            int savedDpiY = 0;
+            if (this.horizontalDpiConverter != null) {
+                originDpiX = this.horizontalDpiConverter.convertDpiToPixel(this.origin.getX());
+                savedDpiX = this.horizontalDpiConverter.convertDpiToPixel(this.savedOrigin.getX());
+
+                if (this.minimumOrigin.getX() > 0) {
+                    minimumDpiX = this.horizontalDpiConverter.convertDpiToPixel(this.minimumOrigin.getX());
+                }
+            }
+
+            if (this.verticalDpiConverter != null) {
+                originDpiY = this.verticalDpiConverter.convertDpiToPixel(this.origin.getY());
+                savedDpiY = this.verticalDpiConverter.convertDpiToPixel(this.savedOrigin.getY());
+
+                if (this.minimumOrigin.getY() > 0) {
+                    minimumDpiY = this.verticalDpiConverter.convertDpiToPixel(this.minimumOrigin.getY());
+                }
+            }
+
+            this.horizontalDpiConverter = ((ConfigureScalingCommand) command).getHorizontalDpiConverter();
+            this.verticalDpiConverter = ((ConfigureScalingCommand) command).getVerticalDpiConverter();
+
+            this.origin = new PixelCoordinate(
+                    this.horizontalDpiConverter.convertPixelToDpi(originDpiX),
+                    this.verticalDpiConverter.convertPixelToDpi(originDpiY));
+            this.savedOrigin = new PixelCoordinate(
+                    this.horizontalDpiConverter.convertPixelToDpi(savedDpiX),
+                    this.verticalDpiConverter.convertPixelToDpi(savedDpiY));
+
+            if (minimumDpiX > 0 || minimumDpiY > 0) {
+                this.minimumOrigin = new PixelCoordinate(
+                        this.horizontalDpiConverter.convertPixelToDpi(minimumDpiX),
+                        this.verticalDpiConverter.convertPixelToDpi(minimumDpiY));
+            }
         }
         return super.doCommand(command);
     }