[508246] Defer image creation to workaround #265265

Legacy properties tabs are discovered at plug-in startup, but if this
happens in a non-UI thread we should avoid allocating SWT images at that
time, as under Linux it can cause deadlocks (see #265265).

Bug: 508246
Change-Id: I4de08f25d6246322d0fec240db48bf2d747b52d1
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
diff --git a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/EEFPropertiesUiLegacyPlugin.java b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/EEFPropertiesUiLegacyPlugin.java
index 8bc865d..742c4b1 100644
--- a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/EEFPropertiesUiLegacyPlugin.java
+++ b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/EEFPropertiesUiLegacyPlugin.java
@@ -185,6 +185,7 @@
 			registry.removeListener(this.tabbedPropertySectionsListener);
 			registry.removeListener(this.tabbedPropertyContributorListener);
 			this.tabbedPropertyTabsListener = null;
+			this.tabbedPropertyTabsRegistry.dispose();
 			this.tabbedPropertyTabsRegistry = null;
 			this.tabbedPropertySectionsListener = null;
 			this.tabbedPropertySectionsRegistry = null;
diff --git a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabItemDescriptor.java b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabItemDescriptor.java
index 13b9b1a..5c97c63 100644
--- a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabItemDescriptor.java
+++ b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabItemDescriptor.java
@@ -13,6 +13,7 @@
 import org.eclipse.eef.properties.ui.api.AbstractEEFTabDescriptor;
 import org.eclipse.eef.properties.ui.legacy.internal.EEFPropertiesUiLegacyPlugin;
 import org.eclipse.eef.properties.ui.legacy.internal.extension.IItemDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.swt.graphics.Image;
 
 /**
@@ -52,7 +53,14 @@
 	private boolean indented;
 
 	/**
-	 * If an image is provided, the icon image is displayed on the tab when the tab is active.
+	 * Image descriptor used to delay the actual {@link Image} creation until really needed. <code>null</code> if no
+	 * image specified if it was already created (in which case the 'image' field will be non-null).
+	 */
+	private ImageDescriptor imageDesc;
+
+	/**
+	 * If an image is provided, the icon image is displayed on the tab when the tab is active. Only allocated on first
+	 * demandn using imageDesc.
 	 */
 	private Image image;
 
@@ -71,11 +79,11 @@
 	 *            The afterTab
 	 * @param indented
 	 *            Is indented
-	 * @param image
-	 *            The image
+	 * @param imageDesc
+	 *            The image descriptor
 	 */
 	public LegacyPropertyTabItemDescriptor(String contributorId, String label, String category, String afterTab, String id, boolean indented,
-			Image image) {
+			ImageDescriptor imageDesc) {
 		setSectionDescriptors(
 				EEFPropertiesUiLegacyPlugin.getImplementation().getTabbedPropertySectionsRegistry().getPropertySections(contributorId, id));
 		this.contributorId = contributorId;
@@ -84,7 +92,7 @@
 		this.label = label;
 		this.afterTab = afterTab;
 		this.indented = indented;
-		this.image = image;
+		this.imageDesc = imageDesc;
 	}
 
 	/**
@@ -156,6 +164,20 @@
 	 */
 	@Override
 	public Image getImage() {
+		if (this.image == null && this.imageDesc != null) {
+			this.image = this.imageDesc.createImage();
+			this.imageDesc = null;
+		}
 		return this.image;
 	}
+
+	/**
+	 * Disposes this descriptor.
+	 */
+	public void dispose() {
+		if (image != null) {
+			image.dispose();
+			image = null;
+		}
+	}
 }
diff --git a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabRegistry.java b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabRegistry.java
index f98daef..78f5570 100644
--- a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabRegistry.java
+++ b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabRegistry.java
@@ -264,4 +264,15 @@
 	public void clear() {
 		this.id2descriptors.clear();
 	}
+
+	/**
+	 * Disposes this registry.
+	 */
+	public void dispose() {
+		for (IItemDescriptor desc : id2descriptors.values()) {
+			if (desc instanceof LegacyPropertyTabItemDescriptor) {
+				((LegacyPropertyTabItemDescriptor) desc).dispose();
+			}
+		}
+	}
 }
diff --git a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabsRegistryEventListener.java b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabsRegistryEventListener.java
index 3bf427b..bb8d9b2 100644
--- a/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabsRegistryEventListener.java
+++ b/plugins/org.eclipse.eef.properties.ui.legacy/src/org/eclipse/eef/properties/ui/legacy/internal/extension/impl/LegacyPropertyTabsRegistryEventListener.java
@@ -16,7 +16,7 @@
 import org.eclipse.eef.properties.ui.legacy.internal.EEFPropertiesUiLegacyPlugin;
 import org.eclipse.eef.properties.ui.legacy.internal.Messages;
 import org.eclipse.eef.properties.ui.legacy.internal.extension.AbstractRegistryEventListener;
-import org.eclipse.swt.graphics.Image;
+import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 
 /**
@@ -140,14 +140,13 @@
 				String indentedString = propertyTab.getAttribute(INDENTED_ATTR);
 				boolean indented = indentedString != null && "true".equals(indentedString); //$NON-NLS-1$
 				String imageString = propertyTab.getAttribute(IMAGE_ATTR);
-				Image image = null;
+				ImageDescriptor imageDesc = null;
 				if (imageString != null) {
-					image = AbstractUIPlugin.imageDescriptorFromPlugin(propertyTab.getDeclaringExtension().getNamespaceIdentifier(), imageString)
-							.createImage();
+					imageDesc = AbstractUIPlugin.imageDescriptorFromPlugin(propertyTab.getDeclaringExtension().getNamespaceIdentifier(), imageString);
 				}
 
 				LegacyPropertyTabItemDescriptor legacyPropertyTab = new LegacyPropertyTabItemDescriptor(contributorId, label, category, afterTab, id,
-						indented, image);
+						indented, imageDesc);
 				this.propertyTabRegistry.add(legacyPropertyTab);
 			}
 		}