--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.ui.gfx;\r
+\r
+import java.util.concurrent.ConcurrentHashMap;\r
+import java.util.concurrent.ConcurrentMap;\r
+\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.swt.graphics.Image;\r
+\r
+/**\r
+ * ImageCache caches SWT images and does clean dispose.<br>\r
+ * Based on "eclipse - building commercial-quality plug-ins" book's chapter\r
+ * 7.7's example.<br>\r
+ * \r
+ * @author Marko Luukkainen\r
+ * \r
+ * @deprecated Please avoid using this class if at all possible. From a resource\r
+ * management point-of-view this class does not fit well into a\r
+ * dynamic OSGi component world. Instead, use JFace\r
+ * {@link ResourceManager} and particularly\r
+ * {@link LocalResourceManager}. You can create one in your local\r
+ * context (a view, editor, bundle activator, etc.) with\r
+ * <code>new LocalResourceManager(JFaceResources.getResources())</code>\r
+ * . Remember to dispose your LocalResourceManager when its owner is\r
+ * disposed. Images can be loaded using\r
+ * {@link LocalResourceManager#createImage(ImageDescriptor)}.\r
+ * \r
+ */\r
+public class ImageCache {\r
+\r
+ /** A singleton cache instance */\r
+ private static final ImageCache imageCache = new ImageCache();\r
+\r
+ /** Descriptor to image mapping */\r
+ private final ConcurrentMap<ImageDescriptor, Image> images = new ConcurrentHashMap<ImageDescriptor, Image>();\r
+\r
+ private final ConcurrentMap<ImageDescriptor, Object> locks = new ConcurrentHashMap<ImageDescriptor, Object>();\r
+\r
+ /**\r
+ * Retrieves and caches the specified image.\r
+ * \r
+ * @param imageDescriptor the ImageDescriptor of the Image\r
+ * @return Image valid image or <code>null</code>if the image could not be\r
+ * created\r
+ */\r
+ public Image getImage(ImageDescriptor imageDescriptor) {\r
+ if (imageDescriptor == null)\r
+ return null;\r
+\r
+ Image image = images.get(imageDescriptor);\r
+ if (image != null)\r
+ return image;\r
+\r
+ Object newLock = new Object();\r
+ Object loadLock = locks.putIfAbsent(imageDescriptor, newLock);\r
+ if (loadLock == null)\r
+ loadLock = newLock;\r
+\r
+ // Localized locking, don't lock the whole class while actually loading the image.\r
+ synchronized (loadLock) {\r
+ image = images.get(imageDescriptor);\r
+ if (image == null) {\r
+ boolean returnError = false;\r
+ image = imageDescriptor.createImage(returnError);\r
+ if (image != null) {\r
+ images.put(imageDescriptor, image);\r
+ }\r
+ }\r
+ }\r
+\r
+ locks.remove(imageDescriptor, loadLock);\r
+\r
+ return image;\r
+ }\r
+\r
+ public void dispose() {\r
+ // Do not synchronize while disposing image resources\r
+ Image[] imgs = null;\r
+ synchronized (images) {\r
+ imgs = images.values().toArray(new Image[images.size()]);\r
+ images.clear();\r
+ }\r
+ locks.clear();\r
+\r
+ for (Image img : imgs) {\r
+ img.dispose();\r
+ }\r
+ }\r
+\r
+ public static ImageCache getInstance() {\r
+ return imageCache;\r
+ }\r
+\r
+}\r