/*
* @(#)Iconkit.java
*
* Project: JHotdraw - a GUI framework for technical drawings
* http://www.jhotdraw.org
* http://jhotdraw.sourceforge.net
* Copyright: (c) by the original author(s) and all contributors
* License: Lesser GNU Public License (LGPL)
* http://www.opensource.org/licenses/lgpl-license.html
*/
package org.jhotdraw.util;
import javax.swing.*;
import java.awt.*;
import java.awt.image.ImageProducer;
import java.net.URL;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import java.util.Hashtable;
/**
* The Iconkit class supports the sharing of images. It maintains
* a map of image names and their corresponding images.
*
* Iconkit also supports to load a collection of images in
* synchronized way.
* The resolution of a path name to an image is delegated to the DrawingEditor.
* <hr>
* <b>Design Patterns</b><P>
* <img src="images/red-ball-small.gif" width=6 height=6 alt=" o ">
* <b><a href=../pattlets/sld031.htm>Singleton</a></b><br>
* The Iconkit is a singleton.
* <hr>
*
* @version <$CURRENT_VERSION$>
*/
public class Iconkit {
/* Holds URLs as keys, and Images as values */
private Map fMap;
/* Holds URLs */
private Set fRegisteredImages;
private Component fComponent;
private final static int ID = 123;
private static Iconkit fgIconkit = null;
/**
* Constructs an Iconkit that uses the given editor to
* resolve image path names.
*/
public Iconkit(Component component) {
fMap = new Hashtable(53);
fRegisteredImages = CollectionsFactory.current().createSet();
fComponent = component;
fgIconkit = this;
}
/**
* Gets the single instance
*/
public static Iconkit instance() {
return fgIconkit;
}
/*********************************************************************
*
* Basic methods for image/icon retrieval.
*
********************************************************************/
/**
* Just gets the image pointed to by the URL and doesn't store
* it in cache.
*/
public Image loadImageUncachedURL(URL url) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
try {
return toolkit.createImage((ImageProducer) url.getContent());
}
catch (Exception ex) {
return null;
}
}
/**
* Just gets the file but doesn't store it in cache.
*/
public Image loadImageUncached(String fileName) {
return loadImageUncachedURL(getResourceURL(fileName));
}
/**
* Loads an image URL with the given name, caches it, and
* optionally waits for it to finish loading.
*/
public Image loadImageURL(URL url, boolean waitForLoad) {
if (fMap.containsKey(url)) {
return (Image) fMap.get(url);
}
Image image = loadImageUncachedURL(url);
if (image != null) {
fMap.put(url, image);
if (waitForLoad) {
waitForLoadedImage(image);
}
}
return image;
}
/**
* Loads an image file with the given name, caches it, and
* optionally waits for it to finish loading.
*/
public Image loadImage(String fileName, boolean waitForLoad) {
return loadImageURL(getResourceURL(fileName), waitForLoad);
}
/**
* Loads an image URL with the given name and caches it
*/
public Image loadImageURL(URL url) {
return loadImageURL(url, false);
}
/**
* Loads an image with the given fileName and caches it.
*/
public Image loadImage(String fileName) {
return loadImageURL(getResourceURL(fileName), false);
}
/**
* Blocks while image loads and returns a completely loaded
* version of image.
*/
public Image waitForLoadedImage(Image image) {
if (image!=null) {
ImageIcon icon = new ImageIcon(image);
// icon.getImage forces the wait to happen
image = icon.getImage();
}
return image;
}
/**
* To translate between a resource and a URL
*/
private URL getResourceURL(String resourceName) {
return getClass().getResource(resourceName);
}
/**
* Registers a URL that is then loaded together with
* the other registered images by loadRegisteredImages.
* @see #loadRegisteredImages
*/
public void registerImageURL(URL url) {
fRegisteredImages.add(url);
}
/**
* Registers the URL for the image resource
* @see #registerImageURL
*/
public void registerImage(String fileName) {
registerImageURL(getResourceURL(fileName));
}
/**
* Loads all registered images.
* If component is null, the component supplied in the
* constructor will be used.
* @see #registerImage
* @see #registerImageURL
*/
public void loadRegisteredImages(Component component) {
if (fRegisteredImages.size() == 0)
return;
if (component == null) {
component = fComponent;
}
MediaTracker tracker = new MediaTracker(component);
// register images with MediaTracker
Iterator iter = fRegisteredImages.iterator();
while (iter.hasNext()) {
URL url = (URL)iter.next();
if (! fMap.containsKey(url)) {
tracker.addImage(loadImageURL(url), ID);
}
}
fRegisteredImages.clear();
// block until all images are loaded
try {
tracker.waitForAll();
}
catch (Exception e) {
// ignore: do nothing
}
}
/*********************************************************************
*
* Deprecated methods
*
********************************************************************/
/**
* Gets the image with the given fileName. If the image can't
* be found it tries it again after registering the image and
* loading all the registered images.
*
* @deprecated use loadImage instead
*/
public Image getImage(String fileName) {
return loadImage(fileName, true);
}
/**
* Registers and loads an image.
* If component is null, the component supplied in the
* constructor will be used.
*
* @deprecated use loadImage instead
*/
public Image registerAndLoadImage(Component component, String fileName) {
registerImage(fileName);
loadRegisteredImages(component);
return loadImage(fileName, true);
}
/**
* Loads an image but does not put in in the cache.
*
* @deprecated use loadImageUncached instead
*/
public Image loadImageResource(String fileName) {
return loadImageUncached(fileName);
}
}