Bug 475357 MUILabel setIconURI does not work for MPart

Remove usage of ICON_URI_FOR_PART in Part's TransientData.
Use Part's icon over Part Descriptor's icon if both are set.
Added Test Cases for StackRenderer.

Initial contibution for this bug by Fabian Miehe
<fabian.miehe@airbus.com>.

Change-Id: I7da142bbde01ee31c96dd30457b169c8b2a0e1e2
Signed-off-by: Benedikt Kuntz <benedikt.kuntz@airbus.com>
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java
index 75abeb0..22650c8 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/SWTPartRenderer.java
@@ -46,7 +46,6 @@
 
 public abstract class SWTPartRenderer extends AbstractPartRenderer {
 
-	private static final String ICON_URI_FOR_PART = "IconUriForPart"; //$NON-NLS-1$
 	private static final String ADORN_ICON_IMAGE_KEY = "previouslyAdorned"; //$NON-NLS-1$
 
 	private String pinURI = "platform:/plugin/org.eclipse.e4.ui.workbench.renderers.swt/icons/full/ovr16/pinned_ovr.png"; //$NON-NLS-1$
@@ -241,23 +240,18 @@
 	private String getIconURI(MUILabel element) {
 		if (element instanceof MPart) {
 			MPart part = (MPart) element;
-			String iconURI = (String) part.getTransientData().get(
-					ICON_URI_FOR_PART);
-			if (iconURI != null) {
-				return iconURI;
+			String iconURI = part.getIconURI();
+
+			if (iconURI == null) {
+				MPartDescriptor desc = modelService.getPartDescriptor(part.getElementId());
+				iconURI = desc != null ? desc.getIconURI() : null;
 			}
-
-			MPartDescriptor desc = modelService.getPartDescriptor(part
-					.getElementId());
-			iconURI = desc != null && desc.getIconURI() != null ? desc
-					.getIconURI() : element.getIconURI();
-			part.getTransientData().put(ICON_URI_FOR_PART, iconURI);
-
 			return iconURI;
 		}
 		return element.getIconURI();
 	}
 
+
 	/**
 	 * @param element
 	 * @param image
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java
index 213e495..f2f8599 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java
@@ -251,9 +251,7 @@
 		List<CTabItem> itemsToSet = getItemsToSet(part);
 		for (CTabItem item : itemsToSet) {
 			if (key.equals(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY)) {
-				this.imageChanged = true;
-				item.setImage(getImage(part));
-				this.imageChanged = false;
+				changePartTabImage(part, item);
 			} else if (key.equals(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY)) {
 				String newTip = getToolTip(part);
 				item.setToolTipText(getToolTip(newTip));
@@ -581,7 +579,7 @@
 			cti.setText(getLabel(part, part.getLocalizedLabel()));
 			break;
 		case UIEvents.UILabel.ICONURI:
-			cti.setImage(getImage(part));
+			changePartTabImage(part, cti);
 			break;
 		case UIEvents.UILabel.TOOLTIP:
 		case UIEvents.UILabel.LOCALIZED_TOOLTIP:
@@ -597,6 +595,12 @@
 		}
 	}
 
+	private void changePartTabImage(MPart part, CTabItem item) {
+		this.imageChanged = true;
+		item.setImage(getImage(part));
+		this.imageChanged = false;
+	}
+
 	@PreDestroy
 	public void contextDisposed() {
 		super.contextDisposed(eventBroker);
diff --git a/tests/org.eclipse.e4.ui.tests/icons/pinned_ovr.png b/tests/org.eclipse.e4.ui.tests/icons/pinned_ovr.png
new file mode 100644
index 0000000..645d395
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.tests/icons/pinned_ovr.png
Binary files differ
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRendererTest.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRendererTest.java
index 273fc2d..964143a 100644
--- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRendererTest.java
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRendererTest.java
@@ -16,6 +16,7 @@
 package org.eclipse.e4.ui.workbench.renderers.swt;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -28,6 +29,7 @@
 import org.eclipse.e4.core.contexts.IEclipseContext;
 import org.eclipse.e4.ui.internal.workbench.swt.CSSConstants;
 import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
 import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
@@ -37,13 +39,18 @@
 import org.eclipse.e4.ui.tests.rules.WorkbenchContextRule;
 import org.eclipse.e4.ui.workbench.UIEvents;
 import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.swt.custom.CTabFolder;
 import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.graphics.Image;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
 public class StackRendererTest {
 
+	private static final String PART_DESC_ICON = "platform:/plugin/org.eclipse.e4.ui.tests/icons/pinned_ovr.png";
+	private static final String PART_ICON = "platform:/plugin/org.eclipse.e4.ui.tests/icons/filenav_nav.png";
+
 	@Rule
 	public WorkbenchContextRule contextRule = new WorkbenchContextRule();
 
@@ -56,7 +63,8 @@
 	@Inject
 	private MApplication application;
 
-	private MPart part;
+	private MPart part1;
+	private MPart part2;
 	private CTabItemStylingMethodsListener executedMethodsListener;
 	private MPartStack partStack;
 
@@ -64,16 +72,24 @@
 	public void setUp() throws Exception {
 		MWindow window = ems.createModelElement(MWindow.class);
 		partStack = ems.createModelElement(MPartStack.class);
-		part = ems.createModelElement(MPart.class);
-		part.setLabel("some title");
 
 		application.getChildren().add(window);
 		application.setSelectedElement(window);
 
-		window.getChildren().add(partStack);
-		partStack.getChildren().add(part);
+		MPartDescriptor partDescriptor = ems.createModelElement(MPartDescriptor.class);
+		partDescriptor.setElementId("myelementid");
+		partDescriptor.setLabel("some title");
+		partDescriptor.setIconURI(PART_DESC_ICON);
+		application.getDescriptors().add(partDescriptor);
 
-		executedMethodsListener = new CTabItemStylingMethodsListener(part);
+		part1 = ems.createPart(partDescriptor);
+		part2 = ems.createPart(partDescriptor);
+
+		window.getChildren().add(partStack);
+		partStack.getChildren().add(part1);
+		partStack.getChildren().add(part2);
+
+		executedMethodsListener = new CTabItemStylingMethodsListener(part1);
 
 		context.set(IStylingEngine.class, (IStylingEngine) Proxy.newProxyInstance(getClass().getClassLoader(),
 				new Class<?>[] { IStylingEngine.class }, executedMethodsListener));
@@ -86,7 +102,7 @@
 			throws Exception {
 		// given
 		HashMap<String, Object> params = new HashMap<>();
-		params.put(UIEvents.EventTags.ELEMENT, part);
+		params.put(UIEvents.EventTags.ELEMENT, part1);
 		params.put(UIEvents.EventTags.NEW_VALUE, CSSConstants.CSS_BUSY_CLASS);
 		params.put(UIEvents.EventTags.OLD_VALUE, null);
 
@@ -106,7 +122,7 @@
 	public void testTabStateHandlerWhenSelectionChangedEvent() throws Exception {
 		// given
 		MPlaceholder placeHolder = ems.createModelElement(MPlaceholder.class);
-		placeHolder.setRef(part);
+		placeHolder.setRef(part1);
 
 		HashMap<String, Object> params = new HashMap<>();
 		params.put(UIEvents.EventTags.ELEMENT, partStack);
@@ -125,6 +141,33 @@
 						.getMethodExecutionCount("setClassnameAndId(.+)"));
 	}
 
+	@Test
+	public void testBug475357_IconChanges() throws Exception {
+		part1.setIconURI(PART_DESC_ICON);
+		CTabItem item = ((CTabFolder) partStack.getWidget()).getItem(0);
+		Image image = item.getImage();
+
+		part1.setIconURI(PART_ICON);
+		assertNotEquals(item.getImage(), image);
+	}
+
+	@Test
+	public void testBug475357_PartIconOverridesDescriptor() throws Exception {
+
+		// check that Renderer uses Part's icon over PartDescriptor's icon
+		CTabItem item = ((CTabFolder) partStack.getWidget()).getItem(1);
+		Image descImage = item.getImage();
+
+		part2.setIconURI(PART_ICON);
+		Image partIcon = item.getImage();
+		assertNotEquals(partIcon, descImage);
+
+		part2.setIconURI(null);
+		Image ovrwriteIcon = item.getImage();
+		assertNotEquals(ovrwriteIcon, partIcon);
+		assertEquals(ovrwriteIcon, descImage);
+	}
+
 	// helper functions
 	private static class CTabItemStylingMethodsListener implements
 			InvocationHandler {