blob: fd480f6421558622680746380ff7752e17034fcb [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ddmuilib;
import com.android.ddmlib.Log;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
/**
* Class to load images stored in a jar file.
* All images are loaded from /images/<var>filename</var>
*
* Because Java requires to know the jar file in which to load the image from, a class is required
* when getting the instance. Instances are cached and associated to the class passed to
* {@link #getLoader(Class)}.
*
* {@link #getDdmUiLibLoader()} use {@link ImageLoader#getClass()} as the class. This is to be used
* to load images from ddmuilib.
*
* Loaded images are stored so that 2 calls with the same filename will return the same object.
* This also means that {@link Image} object returned by the loader should never be disposed.
*
*/
public class ImageLoader {
private static final String PATH = "/images/"; //$NON-NLS-1$
private final HashMap<String, Image> mLoadedImages = new HashMap<String, Image>();
private static final HashMap<Class<?>, ImageLoader> mInstances =
new HashMap<Class<?>, ImageLoader>();
private final Class<?> mClass;
/**
* Private constructor, creating an instance associated with a class.
* The class is used to identify which jar file the images are loaded from.
*/
private ImageLoader(Class<?> theClass) {
if (theClass == null) {
theClass = ImageLoader.class;
}
mClass = theClass;
}
/**
* Returns the {@link ImageLoader} instance to load images from ddmuilib.jar
*/
public static ImageLoader getDdmUiLibLoader() {
return getLoader(null);
}
/**
* Returns an {@link ImageLoader} to load images based on a given class.
*
* The loader will load images from the jar from which the class was loaded. using
* {@link Class#getResource(String)} and {@link Class#getResourceAsStream(String)}.
*
* Since all images are loaded using the path /images/<var>filename</var>, any class from the
* jar will work. However since the loader is cached and reused when the query provides the same
* class instance, and since the loader will also cache the loaded images, it is recommended
* to always use the same class for a given Jar file.
*
*/
public static ImageLoader getLoader(Class<?> theClass) {
ImageLoader instance = mInstances.get(theClass);
if (instance == null) {
instance = new ImageLoader(theClass);
mInstances.put(theClass, instance);
}
return instance;
}
/**
* Disposes all images for all instances.
* This should only be called when the program exits.
*/
public static void dispose() {
for (ImageLoader loader : mInstances.values()) {
loader.doDispose();
}
}
private synchronized void doDispose() {
for (Image image : mLoadedImages.values()) {
image.dispose();
}
mLoadedImages.clear();
}
/**
* Returns an {@link ImageDescriptor} for a given filename.
*
* This searches for an image located at /images/<var>filename</var>.
*
* @param filename the filename of the image to load.
*/
public ImageDescriptor loadDescriptor(String filename) {
URL url = mClass.getResource(PATH + filename);
// TODO cache in a map
return ImageDescriptor.createFromURL(url);
}
/**
* Returns an {@link Image} for a given filename.
*
* This searches for an image located at /images/<var>filename</var>.
*
* @param filename the filename of the image to load.
* @param display the Display object
*/
public synchronized Image loadImage(String filename, Display display) {
Image img = mLoadedImages.get(filename);
if (img == null) {
String tmp = PATH + filename;
InputStream imageStream = mClass.getResourceAsStream(tmp);
if (imageStream != null) {
img = new Image(display, imageStream);
mLoadedImages.put(filename, img);
}
if (img == null) {
throw new RuntimeException("Failed to load " + tmp);
}
}
return img;
}
/**
* Loads an image from a resource. This method used a class to locate the
* resources, and then load the filename from /images inside the resources.<br>
* Extra parameters allows for creation of a replacement image of the
* loading failed.
*
* @param display the Display object
* @param fileName the file name
* @param width optional width to create replacement Image. If -1, null be
* be returned if the loading fails.
* @param height optional height to create replacement Image. If -1, null be
* be returned if the loading fails.
* @param phColor optional color to create replacement Image. If null, Blue
* color will be used.
* @return a new Image or null if the loading failed and the optional
* replacement size was -1
*/
public Image loadImage(Display display, String fileName, int width, int height,
Color phColor) {
Image img = loadImage(fileName, display);
if (img == null) {
Log.w("ddms", "Couldn't load " + fileName);
// if we had the extra parameter to create replacement image then we
// create and return it.
if (width != -1 && height != -1) {
return createPlaceHolderArt(display, width, height,
phColor != null ? phColor : display
.getSystemColor(SWT.COLOR_BLUE));
}
// otherwise, just return null
return null;
}
return img;
}
/**
* Create place-holder art with the specified color.
*/
public static Image createPlaceHolderArt(Display display, int width,
int height, Color color) {
Image img = new Image(display, width, height);
GC gc = new GC(img);
gc.setForeground(color);
gc.drawLine(0, 0, width, height);
gc.drawLine(0, height - 1, width, -1);
gc.dispose();
return img;
}
}