Updated Table(TableColumn, TableItem), Tree(TreeColumn, TreeItem)
,ToolBar/ToolItem classes for image refresh on DPI

Change-Id: Ibffe4a7890c83e43752f83f1d2b86b94f1f5abc2
Signed-off-by: Niraj Modi <niraj.modi@in.ibm.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
index cf0decb..63197d6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
@@ -933,7 +933,7 @@
 		 * the coordinates may be slightly off. The workaround is to restrict
 		 * coordinates to the allowed bounds.
 		 */
-		Rectangle b = image.getBoundsInPixels();
+		Rectangle b = image.getBounds(image.currentDeviceZoom);
 		int errX = src.x + src.width - b.width;
 		int errY = src.y + src.height - b.height;
 		if (errX != 0 || errY != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
index c66e18b..5fe0275 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
@@ -12,6 +12,7 @@
 
 
 import java.io.*;
+import java.util.*;
 
 import org.eclipse.swt.*;
 import org.eclipse.swt.internal.*;
@@ -134,9 +135,17 @@
 	private ImageDataProvider imageDataProvider;
 
 	/**
-	 * Attribute to cache current device zoom level
+	 * Style flag used to differentiate normal, gray-scale and disabled images based
+	 * on image data providers. Without this, a normal and a disabled image of the
+	 * same image data provider would be considered equal.
 	 */
-	private int currentDeviceZoom = 100;
+	private int styleFlag = SWT.IMAGE_COPY;
+
+	/**
+	 * Attribute to cache current device zoom level
+	 * @since 3.107
+	 */
+	public int currentDeviceZoom = 100;
 
 	/**
 	 * width of the image
@@ -251,6 +260,7 @@
 	this.dataAt100 = srcImage.dataAt100;
 	this.imageDataProvider = srcImage.imageDataProvider;
 	this.imageFileNameProvider = srcImage.imageFileNameProvider;
+	this.styleFlag = srcImage.styleFlag | flag;
 	this.currentDeviceZoom = srcImage.currentDeviceZoom;
 	switch (flag) {
 		case SWT.IMAGE_COPY: {
@@ -294,7 +304,8 @@
 			break;
 		}
 		case SWT.IMAGE_DISABLE: {
-			ImageData data = srcImage.getImageDataAtCurrentZoom();
+			ImageData data = srcImage.getImageData(srcImage.currentDeviceZoom);
+//			System.out.println(srcImage.currentDeviceZoom + " : " + data.width + "::" + data.height + ":::" + rect.toString());
 			PaletteData palette = data.palette;
 			RGB[] rgbs = new RGB[3];
 			rgbs[0] = device.getSystemColor(SWT.COLOR_BLACK).getRGB();
@@ -751,7 +762,7 @@
 public boolean setZoom (int zoom) {
 	boolean refreshed = false;
 	StringBuilder sb = new StringBuilder();
-	sb.append("Image:refreshImageForZoom() Current[" + currentDeviceZoom + "] to new[");
+	sb.append("Image:setZoom() From[" + currentDeviceZoom + "] To[");
 
 	if (imageFileNameProvider != null) {
 		if (zoom != currentDeviceZoom) {
@@ -800,10 +811,10 @@
 		}
 	} else {
 		// Cache data at 100% zoom before refresh.
-//		if (dataAt100 == null && currentDeviceZoom == 100) {
-//			dataAt100 = getImageDataAtCurrentZoom();
-//			System.out.println("Cached dataAt100: " + dataAt100);
-//		}
+		if (dataAt100 == null && currentDeviceZoom == 100) {
+			dataAt100 = getImageDataAtCurrentZoom();
+			System.out.println("Cached dataAt100: " + dataAt100);
+		}
 		if (zoom != currentDeviceZoom) {
 			ImageData resizedData = null;
 			if (dataAt100 != null) {
@@ -822,7 +833,11 @@
 		}
 	}
 	sb.append(currentDeviceZoom + "] >> " + refreshed);
-	if (refreshed) System.out.println(sb.toString());
+	if (refreshed) {
+		// Reset width and height to -1, which invokes getBoundsInPixelsFromNative
+		width = height = -1;
+		System.out.println(sb.toString());
+	}
 	return refreshed;
 }
 
@@ -1194,11 +1209,11 @@
 	if (object == this) return true;
 	if (!(object instanceof Image)) return false;
 	Image image = (Image) object;
-	if (device != image.device || transparentPixel != image.transparentPixel) return false;
+	if (device != image.device || transparentPixel != image.transparentPixel || currentDeviceZoom != image.currentDeviceZoom) return false;
 	if (imageDataProvider != null && image.imageDataProvider != null) {
-		return imageDataProvider.equals (image.imageDataProvider);
+		return (styleFlag == image.styleFlag) && imageDataProvider.equals (image.imageDataProvider);
 	} else if (imageFileNameProvider != null && image.imageFileNameProvider != null) {
-		return imageFileNameProvider.equals (image.imageFileNameProvider);
+		return (styleFlag == image.styleFlag) && imageFileNameProvider.equals (image.imageFileNameProvider);
 	} else {
 		return handle == image.handle;
 	}
@@ -1736,7 +1751,7 @@
 	if (imageDataProvider != null) {
 		return imageDataProvider.hashCode();
 	} else if (imageFileNameProvider != null) {
-		return imageFileNameProvider.hashCode();
+		return Objects.hash(imageFileNameProvider, styleFlag, transparentPixel, currentDeviceZoom);
 	} else {
 		return (int)/*64*/handle;
 	}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
index e5c7374..0624868 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
@@ -43,7 +43,7 @@
 		index++;
 	}
 	if (count == 0) {
-		Rectangle rect = image.getBoundsInPixels ();
+		Rectangle rect = image.getBounds (image.currentDeviceZoom);
 		OS.ImageList_SetIconSize (handle, rect.width, rect.height);
 	}
 	set (index, image, count);
@@ -359,7 +359,7 @@
 			* Note that the image size has to match the image list icon size.
 			*/
 			long /*int*/ hBitmap = 0, hMask = 0;
-			ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
+			ImageData data = image.getImageData (image.currentDeviceZoom);
 			switch (data.getTransparencyType ()) {
 				case SWT.TRANSPARENCY_ALPHA:
 					/*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
index 0936214..848a7b7 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
@@ -5238,6 +5238,33 @@
 	OS.SendMessage (handle, OS.LVM_SCROLL, 0, dy);
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Reset ImageList
+	if (headerImageList != null) {
+		headerImageList.dispose();
+		headerImageList = null;
+	}
+	if (imageList != null) {
+		imageList.dispose();
+		imageList = null;
+	}
+
+	// Refresh columns
+	for (TableColumn tableColumn : getColumns()) {
+		refreshed |= tableColumn.setZoom (zoom);
+	}
+
+	// Refresh items
+	for (TableItem item : getItems()) {
+		refreshed |= item.setZoom (zoom);
+	}
+
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 /**
  * Shows the column.  If the column is already showing in the receiver,
  * this method simply returns.  Otherwise, the columns are scrolled until
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java
index d67088a..9ef831c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableColumn.java
@@ -822,6 +822,18 @@
 	}
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Refresh the image
+	if (image != null) {
+		refreshed = image.setZoom (zoom);
+		setImage (image);
+	}
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 void updateToolTip (int index) {
 	long /*int*/ hwndHeaderToolTip = parent.headerToolTipHandle;
 	if (hwndHeaderToolTip != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableItem.java
index b671cbe..0236aec 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TableItem.java
@@ -1264,4 +1264,16 @@
 	setText (0, string);
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Refresh the image
+	if (image != null) {
+		refreshed = image.setZoom (zoom);
+		setImage (image);
+	}
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolBar.java
index 71a727f..aa0955d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolBar.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolBar.java
@@ -192,10 +192,29 @@
 public boolean setZoom(int zoom) {
 	boolean refreshed = (this.currentDeviceZoom == zoom);
 	this.currentDeviceZoom = zoom;
+	// Reset ImageList
+	if (imageList != null) {
+		imageList.dispose();
+		imageList = null;
+	}
+	if (hotImageList != null) {
+		hotImageList.dispose();
+		hotImageList = null;
+	}
+	if (disabledImageList != null) {
+		disabledImageList.dispose();
+		disabledImageList = null;
+	}
+
 	// Refresh image on DPI change
 	for (ToolItem item : _getItems ()) {
 		refreshed |=item.setZoom (zoom);
 	}
+	setImageList (imageList);
+	setDisabledImageList (disabledImageList);
+	setHotImageList (hotImageList);
+
+	layoutItems ();
 	return refreshed;
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
index 43a09b1..e35cb06 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
@@ -725,11 +725,37 @@
 public boolean setZoom (int zoom) {
 	boolean refreshed = (this.currentDeviceZoom == zoom);
 	this.currentDeviceZoom = zoom;
+	int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
 	// Refresh the image
 	if (image != null) {
+		Rectangle bounds = image.getBounds(zoom);
+		if (parent.getImageList() == null) {
+			parent.setImageList (display.getImageListToolBar (listStyle, bounds.width, bounds.height));
+		}
+		if (parent.getDisabledImageList() == null) {
+			parent.setDisabledImageList (display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height));
+		}
+		if (parent.getHotImageList() == null) {
+			parent.setHotImageList (display.getImageListToolBarHot (listStyle, bounds.width, bounds.height));
+		}
 		refreshed = image.setZoom (zoom);
+		parent.getImageList().add(image);
+
+		if (disabledImage != null) {
+			refreshed = disabledImage.setZoom (zoom);
+		}
+		else {
+			disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE);
+		}
+		parent.getDisabledImageList().add(disabledImage != null ? disabledImage : disabledImage2);
+
+		if (hotImage != null) {
+			refreshed = hotImage.setZoom (zoom);
+		}
+		parent.getHotImageList().add(hotImage != null ? hotImage : image);
 		setImage (image);
 	}
+
 	return refreshed;
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
index e9f88b3..e31f862 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java
@@ -3649,7 +3649,7 @@
 int imageIndex (Image image, int index) {
 	if (image == null) return OS.I_IMAGENONE;
 	if (imageList == null) {
-		Rectangle bounds = image.getBoundsInPixels ();
+		Rectangle bounds = image.getBounds (image.currentDeviceZoom);
 		imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
 	}
 	int imageIndex = imageList.indexOf (image);
@@ -3673,7 +3673,7 @@
 int imageIndexHeader (Image image) {
 	if (image == null) return OS.I_IMAGENONE;
 	if (headerImageList == null) {
-		Rectangle bounds = image.getBoundsInPixels ();
+		Rectangle bounds = image.getBounds (image.currentDeviceZoom);
 		headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
 		int index = headerImageList.indexOf (image);
 		if (index == -1) index = headerImageList.add (image);
@@ -5189,6 +5189,32 @@
 	updateScrollBar ();
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Reset ImageList
+	if (headerImageList != null) {
+		headerImageList.dispose();
+		headerImageList = null;
+	}
+	if (imageList != null) {
+		imageList.dispose();
+		imageList = null;
+	}
+
+	// Refresh columns
+	for (TreeColumn treeColumn : getColumns()) {
+		refreshed |= treeColumn.setZoom (zoom);
+	}
+
+	// Refresh items
+	for (TreeItem item : getItems()) {
+		refreshed |= item.setZoom (zoom);
+	}
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 void showItem (long /*int*/ hItem) {
 	/*
 	* Bug in Windows.  When TVM_ENSUREVISIBLE is used to ensure
@@ -7729,9 +7755,9 @@
 							GCData data = new GCData();
 							data.device = display;
 							GC gc = GC.win32_new (nmcd.hdc, data);
-							int y = Math.max (0, (nmcd.bottom - columns[i].image.getBoundsInPixels().height) / 2);
+							int y = Math.max (0, (nmcd.bottom - columns[i].image.getBounds(columns[i].image.currentDeviceZoom).height) / 2);
 							gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y));
-							x += columns[i].image.getBoundsInPixels().width + 12;
+							x += columns[i].image.getBounds(columns[i].image.currentDeviceZoom).width + 12;
 							gc.dispose ();
 						}
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeColumn.java
index eafad93..73d65bb 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeColumn.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeColumn.java
@@ -743,6 +743,18 @@
 	parent.setScrollWidth ();
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Refresh the image
+	if (image != null) {
+		refreshed = image.setZoom (zoom);
+		setImage (image);
+	}
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 void updateToolTip (int index) {
 	long /*int*/ hwndHeaderToolTip = parent.headerToolTipHandle;
 	if (hwndHeaderToolTip != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeItem.java
index 7484c28..5d2d993 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TreeItem.java
@@ -1820,6 +1820,22 @@
 	setText (0, string);
 }
 
+@Override
+public boolean setZoom (int zoom) {
+	boolean refreshed = (this.currentDeviceZoom == zoom);
+	// Refresh the image
+	if (image != null) {
+		refreshed = image.setZoom (zoom);
+		setImage (image);
+	}
+	// Refresh the child item
+	for (TreeItem item : getItems()) {
+		refreshed |= item.setZoom (zoom);
+	}
+	this.currentDeviceZoom = zoom;
+	return refreshed;
+}
+
 /*public*/ void sort () {
 	checkWidget ();
 	if ((parent.style & SWT.VIRTUAL) != 0) return;
diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet373.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet373.java
index 979ddef..bc83856 100644
--- a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet373.java
+++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet373.java
@@ -56,7 +56,7 @@
 		default:

 			path = IMAGE_PATH_100;

 		}

-		System.out.println("ImageFileNameProvider: " + zoom + " : " + path);

+		System.out.println("Snippet373: ImageFileNameProvider: " + zoom + " : " + path);

 		return path;

 	};

 

@@ -64,6 +64,12 @@
 		System.setProperty("swt.autoScale", "quarter");

 		Display display = new Display();

 		final Image eclipse = new Image(display, filenameProvider);

+		final Image eclipseToolBar1 = new Image(display, filenameProvider);

+		final Image eclipseToolBar2 = new Image(display, filenameProvider);

+		final Image eclipseTableHeader = new Image(display, filenameProvider);

+		final Image eclipseTableItem = new Image(display, filenameProvider);

+		final Image eclipseTree1 = new Image(display, filenameProvider);

+		final Image eclipseTree2 = new Image(display, filenameProvider);

 		final Image eclipseCTab1 = new Image(display, filenameProvider);

 		final Image eclipseCTab2 = new Image(display, filenameProvider);

 

@@ -71,8 +77,8 @@
 		shell.setImage(eclipse);

 		shell.setText("DynamicDPI @ " + DPIUtil.getDeviceZoom() );

 		shell.setLayout(new RowLayout(SWT.VERTICAL));

-		shell.setLocation(100, 200);

-		shell.setSize(400, 400);

+		shell.setLocation(100, 100);

+		shell.setSize(500, 500);

 

 		// Menu

 		Menu bar = new Menu (shell, SWT.BAR);

@@ -153,7 +159,7 @@
 		for (int i=0; i<2; i++) {

 			int style = i % 2 == 1 ? SWT.DROP_DOWN : SWT.PUSH;

 			ToolItem toolItem = new ToolItem (toolBar, style);

-			toolItem.setImage (eclipse);

+			toolItem.setImage ((i % 2 == 0) ? eclipseToolBar1 : eclipseToolBar2);

 			toolItem.setEnabled(i % 2 == 0);

 		}

 		toolBar.pack ();

@@ -191,6 +197,42 @@
 			}

 		});

 

+		// Table

+		Table table = new Table (shell, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);

+		table.setLinesVisible (true);

+		table.setHeaderVisible (true);

+		String titles[] = {"Title 1"};

+		for (int i=0; i<titles.length; i++) {

+			TableColumn column = new TableColumn (table, SWT.NONE);

+			column.setText (titles [i]);

+			column.setImage(eclipseTableHeader);

+		}

+		for (int i = 0; i < 1; i++) {

+			TableItem item = new TableItem (table, SWT.NONE);

+			item.setText (0, "Data " + i);

+			item.setImage(0, eclipseTableItem);

+		}

+		for (int i=0; i<titles.length; i++) {

+			table.getColumn (i).pack ();

+		}

+

+		// Tree

+		final Tree tree = new Tree (shell, SWT.BORDER);

+		for (int i=0; i<1; i++) {

+			TreeItem iItem = new TreeItem (tree, 0);

+			iItem.setText ("TreeItem (0) -" + i);

+			iItem.setImage(eclipseTree1);

+			TreeItem jItem = null;

+			for (int j=0; j<1; j++) {

+				jItem = new TreeItem (iItem, 0);

+				jItem.setText ("TreeItem (1) -" + j);

+				jItem.setImage(eclipseTree2);

+				jItem.setExpanded(true);

+			}

+			tree.select(jItem);

+		}

+

+		// Shell Location

 		Monitor primary = display.getPrimaryMonitor();

 		Rectangle bounds = primary.getBounds();

 		Rectangle rect = shell.getBounds();