Bug 138493 Exception in synchronize view
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ChangeSetLabelProvider.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ChangeSetLabelProvider.java
index db32c23..05d064e 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ChangeSetLabelProvider.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/mappings/ChangeSetLabelProvider.java
@@ -15,18 +15,16 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.resources.mapping.ResourceTraversal;
-import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
 import org.eclipse.team.core.diff.IDiffTree;
 import org.eclipse.team.internal.ccvs.core.mapping.ChangeSetModelProvider;
 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
 import org.eclipse.team.internal.ccvs.ui.ICVSUIConstants;
 import org.eclipse.team.internal.ccvs.ui.subscriber.CVSParticipantLabelDecorator;
 import org.eclipse.team.internal.core.subscribers.*;
-import org.eclipse.team.internal.ui.TeamUIPlugin;
 import org.eclipse.team.internal.ui.mapping.ResourceModelLabelProvider;
 import org.eclipse.team.internal.ui.synchronize.ChangeSetCapability;
 import org.eclipse.team.ui.mapping.ITeamContentProviderManager;
@@ -36,8 +34,6 @@
 
 public class ChangeSetLabelProvider extends ResourceModelLabelProvider {
 
-	private Image changeSetImage;
-	private Font boldFont;
 	private CVSParticipantLabelDecorator decorator;
 
 	public void init(ICommonContentExtensionSite site) {
@@ -86,20 +82,10 @@
 	}
 
 	private Image getChangeSetImage() {
-		if (changeSetImage == null) {
-			ImageDescriptor imageDescriptor = CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_CHANGELOG);
-			if (imageDescriptor != null)
-				changeSetImage = imageDescriptor.createImage();
-		}
-		return changeSetImage;
+		return getImageManager().getImage(CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_CHANGELOG));
 	}
 	
 	public void dispose() {
-		if (changeSetImage != null) {
-			changeSetImage.dispose();
-		}
-		if (boldFont != null)
-			boldFont.dispose();
 		if (decorator != null)
 			decorator.dispose();
 		super.dispose();
@@ -217,15 +203,7 @@
 	public Font getFont(Object element) {
 		element = internalGetElement(element);
 	    if (element instanceof ActiveChangeSet && isDefaultActiveSet((ActiveChangeSet)element)) {
-	    	if (boldFont == null) {
-				Font defaultFont = JFaceResources.getDefaultFont();
-				FontData[] data = defaultFont.getFontData();
-				for (int i = 0; i < data.length; i++) {
-					data[i].setStyle(SWT.BOLD);
-				}				
-				boldFont = new Font(TeamUIPlugin.getStandardDisplay(), data);
-			}
-			return boldFont;
+			return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);
 	    }
 		return super.getFont(element);
 	}
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceModelLabelProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceModelLabelProvider.java
index a4aa9ec..ed65b0c 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceModelLabelProvider.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/mapping/ResourceModelLabelProvider.java
@@ -21,6 +21,7 @@
 import org.eclipse.team.core.mapping.IResourceDiffTree;
 import org.eclipse.team.core.mapping.ISynchronizationContext;
 import org.eclipse.team.internal.ui.*;
+import org.eclipse.team.internal.ui.synchronize.ImageManager;
 import org.eclipse.team.ui.mapping.ITeamContentProviderManager;
 import org.eclipse.team.ui.mapping.SynchronizationLabelProvider;
 import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
@@ -45,7 +46,7 @@
 	
 	private ILabelProvider provider = new WorkbenchLabelProvider();
 	private ResourceModelContentProvider contentProvider;
-	private Image compressedFolderImage;
+	private ImageManager localImageManager;
 
 	public void init(ICommonContentExtensionSite site) {
 		ITreeContentProvider aContentProvider = site.getExtension().getContentProvider();
@@ -58,8 +59,8 @@
 	
 	public void dispose() {
 		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
-		if (compressedFolderImage != null)
-			compressedFolderImage.dispose();
+		if (localImageManager != null)
+			localImageManager.dispose();
 		super.dispose();
 	}
 
@@ -186,9 +187,7 @@
 	
 	protected Image getDelegateImage(Object elementOrPath) {
 		if (getConfiguration() != null && getTraversalCalculator().isCompressedFolder(elementOrPath)) {
-			if (compressedFolderImage == null)
-				compressedFolderImage = TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COMPRESSED_FOLDER).createImage();
-			return compressedFolderImage;
+			return getImageManager().getImage(TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_COMPRESSED_FOLDER));
 		}
 		return super.getDelegateImage(internalGetElement(elementOrPath));
 	}
@@ -216,4 +215,16 @@
 		if (f != null)
 			label.setFont(f);
 	}
+	
+	protected ImageManager getImageManager() {
+		ISynchronizationContext context = getContext();
+		if (context != null) {
+			return ImageManager.getImageManager(context);
+		}
+		if (localImageManager == null) {
+			localImageManager = new ImageManager();
+		}
+		return localImageManager;
+	}
+
 }
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/ImageManager.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/ImageManager.java
new file mode 100644
index 0000000..ab24e67
--- /dev/null
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/ImageManager.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.ui.synchronize;
+
+import java.util.*;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.team.core.ICache;
+import org.eclipse.team.core.ICacheListener;
+import org.eclipse.team.core.mapping.ISynchronizationContext;
+import org.eclipse.team.internal.ui.TeamUIPlugin;
+
+public class ImageManager {
+	
+	private static final String PROP_IMAGE_MANAGER = TeamUIPlugin.ID + ".imageManager"; //$NON-NLS-1$
+	
+	// Cache for images that have been overlayed
+	private Map fgImageCache = new HashMap(10);
+	
+	// Contains direction images
+	private CompareConfiguration compareConfig = new CompareConfiguration();
+	
+	private boolean disposed = false;
+	
+	public synchronized static ImageManager getImageManager(ISynchronizationContext context) {
+		ImageManager manager = (ImageManager)context.getCache().get(PROP_IMAGE_MANAGER);
+		if (manager == null) {
+			final ImageManager newRegistry = new ImageManager();
+			context.getCache().put(PROP_IMAGE_MANAGER, newRegistry);
+			context.getCache().addCacheListener(new ICacheListener() {
+				public void cacheDisposed(ICache cache) {
+					newRegistry.dispose();
+				}
+			});
+			manager = newRegistry;
+		}
+		return manager;
+	}
+	
+	public Image getImage(ImageDescriptor descriptor) {
+		if (descriptor == null || disposed)
+			return null;
+		Image image = (Image)fgImageCache.get(descriptor);
+		if (image == null) {
+			image = descriptor.createImage();
+			fgImageCache.put(descriptor, image);
+		}
+		return image;
+	}
+	
+	public void dispose() {
+		disposed = true;
+		compareConfig.dispose();
+		if (fgImageCache != null) {
+			Iterator it = fgImageCache.values().iterator();
+			while (it.hasNext()) {
+				Image element = (Image) it.next();
+				element.dispose();
+			}
+		}
+	}
+
+	public Image getImage(Image base, int compareKind) {
+		if (disposed)
+			return null;
+		return compareConfig.getImage(base, compareKind);
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/AbstractSynchronizeLabelProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/AbstractSynchronizeLabelProvider.java
index 913d3a9..9873ebd 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/AbstractSynchronizeLabelProvider.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/AbstractSynchronizeLabelProvider.java
@@ -11,10 +11,7 @@
 package org.eclipse.team.ui.synchronize;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.compare.CompareConfiguration;
 import org.eclipse.compare.structuremergeviewer.Differencer;
@@ -26,16 +23,16 @@
 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.viewers.*;
 import org.eclipse.osgi.util.NLS;
-import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.team.core.diff.IDiff;
 import org.eclipse.team.core.diff.IThreeWayDiff;
+import org.eclipse.team.core.mapping.ISynchronizationContext;
 import org.eclipse.team.core.synchronize.SyncInfo;
 import org.eclipse.team.internal.ui.*;
+import org.eclipse.team.internal.ui.synchronize.ImageManager;
 import org.eclipse.team.ui.ISharedImages;
 import org.eclipse.team.ui.TeamUI;
-import org.eclipse.team.ui.mapping.ITeamContentProviderDescriptor;
-import org.eclipse.team.ui.mapping.ITeamContentProviderManager;
+import org.eclipse.team.ui.mapping.*;
 
 /**
  * A label provider wrapper that adds synchronization image and/or text decorations
@@ -45,14 +42,7 @@
  */
 public abstract class AbstractSynchronizeLabelProvider implements ILabelProvider {
 	
-	// Cache for images that have been overlayed
-	private Map fgImageCache = new HashMap(10);
-	
-	// Font used to display busy elements
-	private Font busyFont;
-	
-	// Contains direction images
-	private CompareConfiguration compareConfig = new CompareConfiguration();
+	private ImageManager localImageManager;
 	
 	/* (non-Javadoc)
 	 * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
@@ -102,14 +92,7 @@
 		Image base = modelLabelProvider.getImage(internalGetElement(element));
 		if (base == null && element instanceof ModelProvider) {
 			ModelProvider mp = (ModelProvider) element;
-			base = (Image)fgImageCache.get(mp);
-			if (base == null) {
-				ImageDescriptor desc = getImageDescriptor(mp);
-				if (desc != null) {
-					base = desc.createImage();
-					fgImageCache.put(mp, base);
-				}
-			}
+			base = getImageManager().getImage(getImageDescriptor(mp));
 		}
 		return base;
 	}
@@ -158,7 +141,7 @@
 				}
 			}
 		}	
-		return compareConfig.getImage(base, compareKind);
+		return getImageManager().getImage(base, compareKind);
 	}
 	
 	/* (non-Javadoc)
@@ -220,17 +203,8 @@
 	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
 	 */
 	public void dispose() {
-		compareConfig.dispose();
-		if(busyFont != null) {
-			busyFont.dispose();
-		}
-		if (fgImageCache != null) {
-			Iterator it = fgImageCache.values().iterator();
-			while (it.hasNext()) {
-				Image element = (Image) it.next();
-				element.dispose();
-			}
-		}
+		if (localImageManager != null)
+			localImageManager.dispose();
 	}
 
 	/* (non-Javadoc)
@@ -320,12 +294,7 @@
 				locationInts[i] = ((Integer) locations.get(i)).intValue();
 			}
 			ImageDescriptor overlay = new OverlayIcon(base, overlayImages, locationInts, new Point(base.getBounds().width, base.getBounds().height));
-			Image conflictDecoratedImage = (Image) fgImageCache.get(overlay);
-			if (conflictDecoratedImage == null) {
-				conflictDecoratedImage = overlay.createImage();
-				fgImageCache.put(overlay, conflictDecoratedImage);
-			}
-			return conflictDecoratedImage;
+			return getImageManager().getImage(overlay);
 		}
 		return base;
 	}
@@ -424,15 +393,26 @@
 	 */
 	public Font getFont(Object element) {
 		if(isBusy(internalGetElement(element))) {
-			if (busyFont == null) {
-				Font defaultFont = JFaceResources.getDefaultFont();
-				FontData[] data = defaultFont.getFontData();
-				for (int i = 0; i < data.length; i++) {
-					data[i].setStyle(SWT.ITALIC);
-				}				
-				busyFont = new Font(TeamUIPlugin.getStandardDisplay(), data);
-			}
-			return busyFont;
+			return JFaceResources.getFontRegistry().getItalic(JFaceResources.DEFAULT_FONT);
+		}
+		return null;
+	}
+	
+	private ImageManager getImageManager() {
+		ISynchronizationContext context = getContext();
+		if (context != null) {
+			return ImageManager.getImageManager(context);
+		}
+		if (localImageManager == null) {
+			localImageManager = new ImageManager();
+		}
+		return localImageManager;
+	}
+
+	private ISynchronizationContext getContext() {
+		if (this instanceof SynchronizationLabelProvider) {
+			SynchronizationLabelProvider slp = (SynchronizationLabelProvider) this;
+			return slp.getContext();
 		}
 		return null;
 	}