com.jidesoft.icons.IconsFactory Maven / Gradle / Ivy
Show all versions of jide-oss Show documentation
/*
* @(#)IconsFactory.java
*
* Copyright 2002 JIDE Software Inc. All rights reserved.
*/
package com.jidesoft.icons;
import com.jidesoft.swing.JideSwingUtilities;
import com.jidesoft.utils.SecurityUtils;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;
/**
* IconsFactory
provides a consistent way to access icon resource in any application.
*
* Any application usually need to access image files. One way to do it is to put those image files in the installation
* and access them use direct file access. However this is not a good way because you have to know the full path to the
* image file. So a better way that most Java applications take is to bundle the image files with in the jar and use
* class loader to load them.
*
* For example, if a class Foo needs to access image files foo.gif and bar.png, we put the image files right below the
* source code under icons subfolder. See an example directory structure below.
*
* /src/com/jidesoft/Foo.java
* /icons/foo.gif
* /icons/bar.png
*
* When you compile the java class, you copy those images to class output directory like this.
*
* /classes/com/jidesoft/Foo.class
* /icons/foo.gif
* /icons/bar.png
*
* Notes: In IntelliJ IDEA's "Compile" tab of "Project Property" dialog, there is a way to set "Resource Pattern".
* Here is the setting on my computer - "?*.properties;?*.xml;?*.html;?*.tree;?*.gif;?*.png;?*.jpeg;?*.jpg;?*.vm;?*.xsd;?*.ilayout;?*.gz;?*.txt"
* for your reference. If so, all your images will get copies automatically to class output folder. Although I haven't
* tried, I believe most Java IDEs have the same or similar feature. This feature will make the usage of IconsFactory
* much easier.
*
* If you setup directory structure as above, you can now use IconsFactory to access the images like this.
*
* ImageIcon icon = IconsFactory.get(Foo.class, "icons/foo.gif");
*
* IconsFactory will cache the icon for you. So next time if you get the same icon, it will get from cache instead of
* reading from disk again.
*
* There are a few methods on IconsFactory to create difference variation from the original icon. For example, {@link
* #getDisabledImageIcon(Class, String)} will get the image icon with disabled effect.
*
* We also suggest you to use the template below to create a number of IconsFactory classes in your application. The
* idea is that you should have one for each functional area so that all your image files can be grouped into each
* functional area. All images used in that functional area should be put under the folder where this IconsFactory is.
* Here is an template.
*
* class TemplateIconsFactory {
* public static class Group1 {
* public static final String IMAGE1 = "icons/image11.png";
* public static final String IMAGE2 = "icons/image12.png";
* public static final String IMAGE3 = "icons/image13.png";
* }
*
* public static class Group2 {
* public static final String IMAGE1 = "icons/image21.png";
* public static final String IMAGE2 = "icons/image22.png";
* public static final String IMAGE3 = "icons/image23.png";
* }
*
* public static ImageIcon getImageIcon(String name) {
* if (name != null)
* return IconsFactory.getImageIcon(TemplateIconsFactory.class, name);
* else
* return null;
* }
*
* public static void main(String[] argv) {
* IconsFactory.generateHTML(TemplateIconsFactory.class);
* }
* }
*
* In your own IconsFactory, you can further divide images into different groups. The example above has two groups.
* There is also a convenient method getImageIcon() which takes just the icon name.
*
* In the template, we defined the image names as constants. When you have a lot of images, it's hard to remember all of
* them when writing code. If using the IconsFactory above, you can use
*
* ImageIcon icon = TemplateIconsFactory.getImageIcon(TemplateIconsFactory.Group1.IMAGE1);
*
* without saying the actual image file name. With the help of intelli-sense (or code completion) feature in most Java
* IDE, you will find it is much easier to find the icons you want. You can refer to JIDE Components Developer Guide to
* see a screenshot of what it looks like in IntelliJ IDEA.
*
* You probably also notice this is a main() method in this template. You can run it. When you run, you will see a
* message printed out like this.
*
* "File is generated at "... some directory ...\com.jidesoft.icons.TemplateIconsFactory.html".
* Please copy it to the same directory as TemplateIconsFactory.java"
*
* if you follow the instruction and copy the html file to the same location as the source code and open the html, you
* will see the all image files defined in this IconsFactory are listed nicely in the page.
*
* By default, all image files are loaded using ImageIO. However if you set system property "jide.useImageIO" to
* "false", we will disable the usage of ImageIO and use Toolkit.getDefaultToolkit().createImage method to create the
* image file.
*/
public class IconsFactory {
static Map _icons = new HashMap();
static Map _disableIcons = new HashMap();
static Map _brighterIcons = new HashMap();
static Map _tintedIcons = new HashMap();
public static ImageIcon EMPTY_ICON = new ImageIcon() {
private static final long serialVersionUID = 5081581607741629368L;
@Override
public int getIconHeight() {
return 16;
}
@Override
public int getIconWidth() {
return 16;
}
@Override
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
}
};
/**
* Gets ImageIcon by passing class and a relative image file path.
*
* Please note, getImageIcon will print out error message to stderr if image is not found. The reason we did so is
* because we want you to make sure all image files are there in your application. If you ever see the error
* message, you should correct it before shipping the product. But if you just want to test if the image file is
* there, you don't want any error message print out. If so, you can use {@link #findImageIcon(Class, String)}
* method. It will throw IOException when image is not found.
*
* We used this method to create all the icons we used in JIDE's code. If you ever want to use your own icon instead
* of JIDE's default icon, you just need to put it onto UIManager. For example, AutoFilterTableHeader uses an icon
* on the table header. This is how it was called.
IconsFactory.getImageIcon(AutoFilterTableHeader.class,
* "icons/filterYes_over.png")
*
* The key for this icon is "com.jidesoft.grid.AutoFilterTableHeader:icons/filterYes_over.png". So you can call the
* code below to register your own icon. UIManager.put("com.jidesoft.grid.AutoFilterTableHeader:icons/filterYes_over.png",
* your_new_icon);
*
* If you don't know what key to use, just put a breakpoint at this method, run it to inspect the id variable
* below.
*
* @param clazz the Class>
* @param fileName relative file name
* @return the ImageIcon
*/
public static ImageIcon getImageIcon(Class> clazz, String fileName) {
String id = clazz.getName() + ":" + fileName;
Object iconInUIDefaults = UIManager.getDefaults().get(id);
if (iconInUIDefaults instanceof ImageIcon) {
return (ImageIcon) iconInUIDefaults;
}
Icon saved = _icons.get(id);
if (saved != null)
return (ImageIcon) saved;
else {
ImageIcon icon = createImageIcon(clazz, fileName);
_icons.put(id, icon);
return icon;
}
}
/**
* Gets ImageIcon by passing class and a relative image file path.
*
* @param clazz the Class>
* @param fileName relative file name
* @return the ImageIcon
*
* @throws IOException when image file is not found.
*/
public static ImageIcon findImageIcon(Class> clazz, String fileName) throws IOException {
String id = clazz.getName() + ":" + fileName;
Object iconInUIDefaults = UIManager.getDefaults().get(id);
if (iconInUIDefaults instanceof ImageIcon) {
return (ImageIcon) iconInUIDefaults;
}
ImageIcon saved = _icons.get(id);
if (saved != null)
return saved;
else {
ImageIcon icon = createImageIconWithException(clazz, fileName);
_icons.put(id, icon);
return icon;
}
}
/**
* Gets a disabled version of ImageIcon by passing class and a relative image file path.
*
* @param clazz the Class>
* @param fileName relative file name
* @return the ImageIcon
*/
public static ImageIcon getDisabledImageIcon(Class> clazz, String fileName) {
String id = clazz.getName() + ":" + fileName;
ImageIcon saved = _disableIcons.get(id);
if (saved != null)
return saved;
else {
ImageIcon icon = createGrayImage(getImageIcon(clazz, fileName));
_disableIcons.put(id, icon);
return icon;
}
}
/**
* Gets a brighter ImageIcon by passing class and a relative image file path.
*
* @param clazz the Class>
* @param fileName relative file name
* @return the ImageIcon
*/
public static ImageIcon getBrighterImageIcon(Class> clazz, String fileName) {
String id = clazz.getName() + ":" + fileName + ":" + ColorFilter.getPercent();
ImageIcon saved = _brighterIcons.get(id);
if (saved != null)
return saved;
else {
ImageIcon icon = createBrighterImage(getImageIcon(clazz, fileName));
_brighterIcons.put(id, icon);
return icon;
}
}
/**
* Gets a brighter ImageIcon by passing class, a relative image file path and a percentage of brightness.
*
* @param clazz the Class>
* @param fileName relative file name
* @param percent percentage of brightness
* @return the ImageIcon
*/
public static ImageIcon getBrighterImageIcon(Class> clazz, String fileName, int percent) {
String id = clazz.getName() + ":" + fileName + ":" + percent;
ImageIcon saved = _brighterIcons.get(id);
if (saved != null)
return saved;
else {
ImageIcon icon = createBrighterImage(getImageIcon(clazz, fileName), percent);
_brighterIcons.put(id, icon);
return icon;
}
}
/**
* Gets a tinted ImageIcon by passing class, a relative image file path and a color.
*
* @param clazz the Class>
* @param fileName relative file name
* @param color the color
* @return the ImageIcon
*/
public static ImageIcon getTintedImageIcon(Class> clazz, String fileName, Color color) {
String id = clazz.getName() + ":" + fileName + ":" + color.toString();
ImageIcon saved = _tintedIcons.get(id);
if (saved != null)
return saved;
else {
ImageIcon icon = createTintedImage(getImageIcon(clazz, fileName), color);
_tintedIcons.put(id, icon);
return icon;
}
}
/**
* Creates a gray version from an input image. Usually gray icon indicates disabled. If input image is null, a blank
* ImageIcon will be returned.
*
* @param image image
* @return gray version of the image
*/
public static ImageIcon createGrayImage(Image image) {
if (image == null)
return EMPTY_ICON;
return new ImageIcon(GrayFilter.createDisabledImage(image));
}
/**
* Creates a gray version from an input ImageIcon. Usually gray icon indicates disabled. If input icon is null, a
* blank ImageIcon will be returned.
*
* @param icon image
* @return gray version of the image
*/
private static ImageIcon createGrayImage(ImageIcon icon) {
if (icon == null)
return EMPTY_ICON;
return new ImageIcon(GrayFilter.createDisabledImage(icon.getImage()));
}
/**
* Creates a gray version from an input image. Usually gray icon indicates disabled. If input icon is null, a blank
* ImageIcon will be returned.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background color.
* @param icon icon
* @return gray version of the image
*/
public static ImageIcon createGrayImage(Component c, Icon icon) {
if (icon == null)
return EMPTY_ICON;
int w = icon.getIconWidth(), h = icon.getIconHeight();
if ((w == 0) || (h == 0))
return EMPTY_ICON;
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(c, image.getGraphics(), 0, 0);
return new ImageIcon(GrayFilter.createDisabledImage(image));
}
/**
* Creates a brighter image from an input image. If input image is null, a blank ImageIcon will be returned.
*
* @param image image
* @return dimmed version of the image
*/
public static ImageIcon createBrighterImage(Image image) {
if (image == null)
return EMPTY_ICON;
return new ImageIcon(ColorFilter.createBrighterImage(image));
}
/**
* Creates a brighter image from an input image with a given percentage of brightness. If input image is null, a
* blank ImageIcon will be returned.
*
* @param image image
* @param percent percentage of brightness
* @return dimmed version of the image
*/
public static ImageIcon createBrighterImage(Image image, int percent) {
if (image == null)
return EMPTY_ICON;
return new ImageIcon(ColorFilter.createBrighterImage(image, percent));
}
/**
* Creates a gray version from an input image. Usually gray icon indicates disabled. If input icon is null, a blank
* ImageIcon will be returned.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background color.
* @param icon icon
* @return gray version of the image
*/
public static ImageIcon createBrighterImage(Component c, Icon icon) {
if (icon == null)
return EMPTY_ICON;
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(c, image.getGraphics(), 0, 0);
return new ImageIcon(ColorFilter.createBrighterImage(image));
}
/**
* Creates a gray version from an input image with a given percentage of brightness. Usually gray icon indicates
* disabled. If input icon is null, a blank ImageIcon will be returned.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background color.
* @param icon icon
* @param percent percentage of brightness
* @return gray version of the image
*/
public static ImageIcon createBrighterImage(Component c, Icon icon, int percent) {
if (icon == null)
return EMPTY_ICON;
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(c, image.getGraphics(), 0, 0);
return new ImageIcon(ColorFilter.createBrighterImage(image, percent));
}
/**
* Creates a brighten version from an input ImageIcon. If input icon is null, a blank ImageIcon will be returned.
*
* @param icon image
* @return dimmed version of the image
*/
public static ImageIcon createBrighterImage(ImageIcon icon) {
if (icon == null)
return EMPTY_ICON;
return new ImageIcon(ColorFilter.createBrighterImage(icon.getImage()));
}
/**
* Creates a brighter image from an input image with a given percentage of brightness. If input image is null, a
* blank ImageIcon will be returned.
*
* @param icon image
* @param percent percentage of brightness
* @return dimmed version of the image
*/
public static ImageIcon createBrighterImage(ImageIcon icon, int percent) {
if (icon == null)
return EMPTY_ICON;
return new ImageIcon(ColorFilter.createBrighterImage(icon.getImage(), percent));
}
/**
* Creates a tinted image from an input image with a given color. If input image is null, a blank ImageIcon will be
* returned.
*
* @param icon image
* @param color the color
* @return a tinted version of the image
*/
public static ImageIcon createTintedImage(ImageIcon icon, Color color) {
if (icon == null)
return EMPTY_ICON;
return new ImageIcon(TintFilter.createTintedImage(icon.getImage(), color, null));
}
/**
* Creates a gray version from an input image. Usually gray icon indicates disabled. If input image is null, a blank
* ImageIcon will be returned.
*
* @param image image
* @return gray version of the image
*/
public static ImageIcon createNegativeImage(Image image) {
if (image == null)
return EMPTY_ICON;
return new ImageIcon(MaskFilter.createNegativeImage(image));
}
/**
* Creates a version from an input image which replaces one color with another color.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background color.
* @param icon icon
* @param oldColor the old color to be replaced.
* @param newColor the new color that will replace the old color.
* @return the image after replacing the color.
*/
public static ImageIcon createMaskImage(Component c, Icon icon, Color oldColor, Color newColor) {
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(c, image.getGraphics(), 0, 0);
return new ImageIcon(MaskFilter.createImage(image, oldColor, newColor));
}
static final double DEGREE_90 = 90.0 * Math.PI / 180.0;
/**
* Creates a rotated version of the input image.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background
* color.
* @param icon the image to be rotated.
* @param rotatedAngle the rotated angle, in degree, clockwise. It could be any double but we will mod it with 360
* before using it.
* @return the image after rotating.
*/
public static ImageIcon createRotatedImage(Component c, Icon icon, double rotatedAngle) {
// convert rotatedAngle to a value from 0 to 360
double originalAngle = rotatedAngle % 360;
if (rotatedAngle != 0 && originalAngle == 0) {
originalAngle = 360.0;
}
// convert originalAngle to a value from 0 to 90
double angle = originalAngle % 90;
if (originalAngle != 0.0 && angle == 0.0) {
angle = 90.0;
}
double radian = Math.toRadians(angle);
int iw = icon.getIconWidth();
int ih = icon.getIconHeight();
int w;
int h;
if ((originalAngle >= 0 && originalAngle <= 90) || (originalAngle > 180 && originalAngle <= 270)) {
w = (int) Math.round((iw * Math.sin(DEGREE_90 - radian) + ih * Math.sin(radian)));
h = (int) Math.round((iw * Math.sin(radian) + ih * Math.sin(DEGREE_90 - radian)));
}
else {
w = (int) (ih * Math.sin(DEGREE_90 - radian) + iw * Math.sin(radian));
h = (int) (ih * Math.sin(radian) + iw * Math.sin(DEGREE_90 - radian));
}
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
Graphics2D g2d = (Graphics2D) g.create();
// calculate the center of the icon.
int cx = iw / 2;
int cy = ih / 2;
// account for images that have a center point in the middle of a pixel.
// for these images (not divisible by two) we need to account for the
// "down and to the right" bias of the graphics context.
int xOffset = iw % 2 != 0 && originalAngle >= 90 && originalAngle <= 180
? 1 : 0;
int yOffset = iw % 2 != 0 && originalAngle >= 180 && originalAngle < 360
? 1 : 0;
// move the graphics center point to the center of the icon.
g2d.translate(w / 2 + xOffset, h / 2 + yOffset);
// rotate the graphics about the center point of the icon
g2d.rotate(Math.toRadians(originalAngle));
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
icon.paintIcon(c, g2d, -cx, -cy);
g2d.dispose();
return new ImageIcon(image);
}
/**
* Creates a negative version from an input black image which basically replaces black pixel with white pixel.
*
* @param c The component to get properties useful for painting, e.g. the foreground or background color.
* @param icon icon
* @return the negative version of the image
*/
public static ImageIcon createNegativeImage(Component c, Icon icon) {
BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
icon.paintIcon(c, image.getGraphics(), 0, 0);
return new ImageIcon(MaskFilter.createNegativeImage(image));
}
private static ImageIcon createImageIcon(final Class> baseClass, final String file) {
try {
return createImageIconWithException(baseClass, file);
}
catch (IOException e) {
System.err.println(e.getLocalizedMessage());
return null;
}
}
private static ImageIcon createImageIconWithException(final Class> baseClass, final String file) throws IOException {
InputStream resource = baseClass.getResourceAsStream(file);
if (resource == null) {
throw new FileNotFoundException(file);
}
else {
Image image;
if ("true".equals(SecurityUtils.getProperty("jide.useImageIO", "true"))) {
image = ImageIO.read(resource);
}
else {
image = readImageIcon(baseClass, file, resource);
}
resource.close();
return new ImageIcon(image);
}
}
private static Image readImageIcon(Class clazz, String file, InputStream resource) throws IOException {
final byte[][] buffer = new byte[1][];
try {
BufferedInputStream in = new BufferedInputStream(resource);
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
buffer[0] = new byte[1024];
int n;
while ((n = in.read(buffer[0])) > 0) {
out.write(buffer[0], 0, n);
}
in.close();
out.flush();
buffer[0] = out.toByteArray();
}
catch (IOException ioe) {
throw ioe;
}
if (buffer[0] == null || buffer[0].length == 0) {
Package pkg = clazz.getPackage();
String pkgName = "";
if (pkg != null) {
pkgName = pkg.getName().replace('.', '/');
}
if (buffer[0] == null) {
throw new IOException("Warning: Resource " + pkgName + "/" + file + " not found.");
}
if (buffer[0].length == 0) {
throw new IOException("Warning: Resource " + pkgName + "/" + file + " is zero-length");
}
}
return Toolkit.getDefaultToolkit().createImage(buffer[0]);
}
/**
* Generates HTML that lists all icons in IconsFactory.
*
* @param clazz the IconsFactory class
*/
public static void generateHTML(Class> clazz) {
String fullClassName = clazz.getName();
String className = getClassName(fullClassName);
File file = new File(fullClassName + ".html");
try {
FileWriter writer = new FileWriter(file);
try {
writer.write("\n\nIcons in " +
fullClassName + "
");
writer.write("Generated by JIDE Icons
");
writer.write("1. If you cannot view the images in this page, " +
"make sure the file is at the same directory as " + className + ".java
");
writer.write("2. To get a particular icon in your code, call " +
className + ".getImageIcon(FULL_CONSTANT_NAME). Replace FULL_CONSTANT_NAME with the actual " +
"full constant name as in the table below" + "
");
generate(clazz, writer, className);
writer.write("\n\n");
}
catch (IOException e) {
System.err.println(e);
}
finally {
writer.close();
}
System.out.println("File is generated at \"" + file.getAbsolutePath() + "\". Please copy it to the same directory as " + className + ".java");
}
catch (IOException e) {
System.err.println(e);
}
}
private static String getClassName(String fullName) {
int last = fullName.lastIndexOf(".");
if (last != -1) {
fullName = fullName.substring(last + 1);
}
StringTokenizer tokenizer = new StringTokenizer(fullName, "$");
StringBuffer buffer = new StringBuffer();
while (tokenizer.hasMoreTokens()) {
buffer.append(tokenizer.nextToken());
buffer.append(".");
}
return buffer.substring(0, buffer.length() - 1);
}
private static void generate(Class> aClass, FileWriter writer, String prefix) throws IOException {
Class>[] classes = aClass.getDeclaredClasses();
// don't know why but the order is exactly the reverse of the order of definitions.
for (int i = classes.length - 1; i >= 0; i--) {
Class> clazz = classes[i];
generate(clazz, writer, getClassName(clazz.getName()));
}
Field[] fields = aClass.getFields();
writer.write("" + prefix + "
");
writer.write("");
writer.write("\n");
writer.write("Name \n");
writer.write("Image \n");
writer.write("File Name \n");
writer.write("Full Constant Name \n");
writer.write(" \n");
for (Field field : fields) {
try {
Object name = field.getName();
Object value = field.get(aClass);
writer.write("\n");
writer.write("" + name + " \n");
writer.write(" \n");
writer.write("" + value + " \n");
writer.write("" + prefix + "." + name + " \n");
writer.write(" \n");
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
writer.write("
\n");
}
/**
* Gets part of the image from input image icon. It basically takes a snapshot of the input image at {x, y} location
* and the size is width x height.
*
* @param c the component where the returned icon will be used. The component is used as the ImageObserver. It
* could be null.
* @param icon the original icon. This is the larger icon where a sub-image will be created using this method.
* @param x the x location of the sub-image, relative to the original icon.
* @param y the y location of the sub-image, relative to the original icon.
* @param width the width of the sub-image. It should be less than the width of the original icon.
* @param height the height of the sub-image. It should be less than the height of the original icon.
* @return an new image icon that was part of the input image icon.
*/
public static ImageIcon getIcon(Component c, ImageIcon icon, int x, int y, int width, int height) {
return getIcon(c, icon, x, y, width, height, width, height);
}
/**
* Gets part of the image from input image icon. It basically takes a snapshot of the input image at {x, y} location
* and the size is width x height, then resize it to a size of destWidth x destHeight.
*
* @param c the component where the returned icon will be used. The component is used as the ImageObserver.
* It could be null.
* @param icon the original icon. This is the larger icon where a sub-image will be created using this
* method.
* @param x the x location of the sub-image, relative to the original icon.
* @param y the y location of the sub-image, relative to the original icon.
* @param width the width of the sub-image. It should be less than the width of the original icon.
* @param height the height of the sub-image. It should be less than the height of the original icon.
* @param destWidth the width of the returned icon. The sub-image will be resize if the destWidth is not the same
* as the width.
* @param destHeight the height of the returned icon. The sub-image will be resize if the destHeight is not the same
* as the height.
* @return an new image icon that was part of the input image icon.
*/
public static ImageIcon getIcon(Component c, ImageIcon icon, int x, int y, int width, int height, int destWidth, int destHeight) {
return getIcon(c, icon, x, y, width, height, BufferedImage.TYPE_INT_ARGB, destWidth, destHeight);
}
/**
* Gets part of the image from input image icon. It basically takes a snapshot of the input image at {x, y} location
* and the size is width x height.
*
* @param c the component where the returned icon will be used. The component is used as the ImageObserver.
* It could be null.
* @param icon the original icon. This is the larger icon where a small icon will be created using this
* method.
* @param x the x location of the smaller icon, relative to the original icon.
* @param y the y location of the smaller icon, relative to the original icon.
* @param width the width of the smaller icon. It should be less than the width of the original icon.
* @param height the height of the smaller icon. It should be less than the height of the original icon.
* @param imageType image type is defined in {@link BufferedImage}, such as {@link BufferedImage#TYPE_INT_ARGB},
* {@link BufferedImage#TYPE_INT_RGB} etc.
* @return an new image icon that was part of the input image icon.
*/
public static ImageIcon getIcon(Component c, ImageIcon icon, int x, int y, int width, int height, int imageType) {
return getIcon(c, icon, x, y, width, height, imageType, width, height);
}
/**
* Gets part of the image from input image icon. It basically takes a snapshot of the input image at {x, y} location
* and the size is width x height, then resize it to a size of destWidth x destHeight. if the original icon is null
* or the specified location is outside the original icon, EMPTY_ICON will be returned.
*
* @param c the component where the returned icon will be used. The component is used as the ImageObserver.
* It could be null.
* @param icon the original icon. This is the larger icon where a sub-image will be created using this
* method.
* @param x the x location of the sub-image, relative to the original icon.
* @param y the y location of the sub-image, relative to the original icon.
* @param width the width of the sub-image. It should be less than the width of the original icon.
* @param height the height of the sub-image. It should be less than the height of the original icon.
* @param imageType image type is defined in {@link BufferedImage}, such as {@link BufferedImage#TYPE_INT_ARGB},
* {@link BufferedImage#TYPE_INT_RGB} etc.
* @param destWidth the width of the returned icon. The sub-image will be resize if the destWidth is not the same
* as the width.
* @param destHeight the height of the returned icon. The sub-image will be resize if the destHeight is not the same
* as the height.
* @return an new image icon that was part of the input image icon.
*/
public static ImageIcon getIcon(Component c, ImageIcon icon, int x, int y, int width, int height, int imageType, int destWidth, int destHeight) {
if (icon == null || x < 0 || x + width > icon.getIconWidth() || y < 0 || y + height > icon.getIconHeight()) { // outside the original icon.
return EMPTY_ICON;
}
BufferedImage image = new BufferedImage(destWidth, destHeight, imageType);
image.getGraphics().drawImage(icon.getImage(), 0, 0, destWidth, destHeight, x, y, x + width, y + height, c);
return new ImageIcon(image);
}
/**
* Gets a new icon with the overlayIcon paints over the original icon.
*
* @param c the component where the returned icon will be used. The component is used as the
* ImageObserver. It could be null.
* @param icon the original icon
* @param overlayIcon the overlay icon.
* @param location the location as defined in SwingConstants - CENTER, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
* NORTH_WEST, SOUTH_WEST and SOUTH_EAST.
* @return the new icon.
*/
public static ImageIcon getOverlayIcon(Component c, ImageIcon icon, ImageIcon overlayIcon, int location) {
return getOverlayIcon(c, icon, overlayIcon, location, new Insets(0, 0, 0, 0));
}
/**
* Gets a new icon with the overlayIcon paints over the original icon.
*
* @param c the component where the returned icon will be used. The component is used as the
* ImageObserver. It could be null.
* @param icon the original icon
* @param overlayIcon the overlay icon.
* @param location the location as defined in SwingConstants - CENTER, NORTH, SOUTH, WEST, EAST, NORTH_EAST,
* NORTH_WEST, SOUTH_WEST and SOUTH_EAST.
* @param insets the insets to the border. This parameter has no effect if the location is CENTER. For example,
* if the location is WEST, insets.left will be the gap of the left side of the original icon and
* the left side of the overlay icon.
* @return the new icon.
*/
public static ImageIcon getOverlayIcon(Component c, ImageIcon icon, ImageIcon overlayIcon, int location, Insets insets) {
int x = -1, y = -1;
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int sw = overlayIcon.getIconWidth();
int sh = overlayIcon.getIconHeight();
switch (location) {
case SwingConstants.CENTER:
x = (w - sw) / 2;
y = (h - sh) / 2;
break;
case SwingConstants.NORTH:
x = (w - sw) / 2;
y = insets.top;
break;
case SwingConstants.SOUTH:
x = (w - sw) / 2;
y = h - insets.bottom - sh;
break;
case SwingConstants.WEST:
x = insets.left;
y = (h - sh) / 2;
break;
case SwingConstants.EAST:
x = w - insets.right - sw;
y = (h - sh) / 2;
break;
case SwingConstants.NORTH_EAST:
x = w - insets.right - sw;
y = insets.top;
break;
case SwingConstants.NORTH_WEST:
x = insets.left;
y = insets.top;
break;
case SwingConstants.SOUTH_WEST:
x = insets.left;
y = h - insets.bottom - sh;
break;
case SwingConstants.SOUTH_EAST:
x = w - insets.right - sw;
y = h - insets.bottom - sh;
break;
}
return getOverlayIcon(c, icon, overlayIcon, x, y);
}
/**
* Gets a new icon with the overlayIcon paints over the original icon.
*
* @param c the component where the returned icon will be used. The component is used as the
* ImageObserver. It could be null.
* @param icon the original icon
* @param overlayIcon the overlay icon.
* @param x the x location relative to the original icon where the overlayIcon will be pained.
* @param y the y location relative to the original icon where the overlayIcon will be pained.
* @return the overlay icon
*/
public static ImageIcon getOverlayIcon(Component c, ImageIcon icon, ImageIcon overlayIcon, int x, int y) {
int w = icon == null ? overlayIcon.getIconWidth() : icon.getIconWidth();
int h = icon == null ? overlayIcon.getIconHeight() : icon.getIconHeight();
int sw = overlayIcon.getIconWidth();
int sh = overlayIcon.getIconHeight();
if (x != -1 && y != -1) {
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
if (icon != null) {
image.getGraphics().drawImage(icon.getImage(), 0, 0, w, h, c);
}
image.getGraphics().drawImage(overlayIcon.getImage(), x, y, sw, sh, c);
return new ImageIcon(image);
}
else {
return icon;
}
}
/**
* Gets a new icon with the icon2 painting right or down to the icon1.
*
* @param c the component where the returned icon will be used. The component is used as the
* ImageObserver. It could be null
* @param icon1 the left side or up side icon
* @param icon2 the right side or down side icon
* @param orientation the orientation as defined in SwingConstants - HORIZONTAL, VERTICAL
* @param gap the gap between the two icons
* @return the new icon.
*/
public static ImageIcon getCombinedIcon(Component c, ImageIcon icon1, ImageIcon icon2, int orientation, int gap) {
if (icon1 == null) {
return icon2;
}
if (icon2 == null) {
return icon1;
}
int x1, y1, x2, y2, width, height;
int w1 = icon1.getIconWidth();
int h1 = icon1.getIconHeight();
int w2 = icon2.getIconWidth();
int h2 = icon2.getIconHeight();
if (orientation == SwingConstants.HORIZONTAL) {
width = w1 + w2 + gap;
height = Math.max(h1, h2);
x1 = 0;
x2 = w1 + gap;
y1 = h1 > h2 ? 0 : (h2 - h1) / 2;
y2 = h1 < h2 ? 0 : (h1 - h2) / 2;
}
else {
width = Math.max(w1, w2);
height = h1 + h2 + gap;
x1 = w1 > w2 ? 0 : (w2 - w1) / 2;
x2 = w1 < w2 ? 0 : (w1 - w2) / 2;
y1 = 0;
y2 = h1 + gap;
}
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
image.getGraphics().drawImage(icon1.getImage(), x1, y1, w1, h1, c);
image.getGraphics().drawImage(icon2.getImage(), x2, y2, w2, h2, c);
return new ImageIcon(image);
}
/**
* Gets a scaled version of the existing icon.
*
* @param c the component where the returned icon will be used. The component is used as the ImageObserver. It
* could be null.
* @param icon the original icon
* @param w the new width
* @param h the new height
* @return the scaled icon
*/
public static ImageIcon getScaledImage(Component c, ImageIcon icon, int w, int h) {
if (w >= icon.getIconWidth() / 2) {
BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(icon.getImage(), 0, 0, temp.getWidth(), temp.getHeight(), c);
g2.dispose();
return new ImageIcon(temp);
}
else {
BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(icon.getImage(), 0, 0, temp.getWidth(), temp.getHeight(), c);
g2.dispose();
return new ImageIcon(JideSwingUtilities.getFasterScaledInstance(temp, w, h, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true));
}
}
/**
* Writes a GIF image of the supplied component to the given file. In particular, you can use this method to take a
* 'screen shot' of a Chart component as a GIF Image.
*
* @param c the component to save as an image
* @param file the file to save it to
* @throws FileNotFoundException if the file exists but is a directory rather than a regular file, does not exist
* but cannot be created, or cannot be opened for any other reason
*/
public static void writeGifToFile(Component c, File file) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream(file);
writeToStream(c, "gif", fos);
try {
fos.close();
}
catch (IOException e) {
Logger.getAnonymousLogger().severe(e.getMessage());
}
}
/**
* Writes a JPEG image of the supplied component to the given file. In particular, you can use this method to take a
* 'screen shot' of a Chart component as a JPEG Image.
*
* @param c the component to save as an image
* @param file the file to save it to
* @throws FileNotFoundException if the file exists but is a directory rather than a regular file, does not exist
* but cannot be created, or cannot be opened for any other reason
*/
public static void writeJpegToFile(Component c, File file) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream(file);
writeToStream(c, "jpg", fos);
try {
fos.close();
}
catch (IOException e) {
Logger.getAnonymousLogger().severe(e.getMessage());
}
}
/**
* Writes a PNG image of the supplied component to the given file. In particular, you can use this method to take a
* 'screen shot' of a Chart component as a PNG Image.
*
* @param c the component to save as an image
* @param file the file to save it to
* @throws FileNotFoundException if the file exists but is a directory rather than a regular file, does not exist
* but cannot be created, or cannot be opened for any other reason
*/
public static void writePngToFile(Component c, File file) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream(file);
writeToStream(c, "png", fos);
try {
fos.close();
}
catch (IOException e) {
Logger.getAnonymousLogger().severe(e.getMessage());
}
}
/**
* Paints the component as a PNG image to the supplied output stream
*
* @param c the component to capture as a PNG image
* @param stream the stream to write the PNG data to
*/
public static void writeToStream(Component c, OutputStream stream) {
writeToStream(c, "png", stream);
}
/**
* Paints the component to the supplied output stream
*
* @param c the component to capture as an image
* @param format the format of the image output data, currently "png", "jpg" or "gif"
* @param stream the stream to write the image data to
*/
private static void writeToStream(Component c, String format, OutputStream stream) {
BufferedImage img = createImage(c);
try {
ImageIO.write(img, format, stream);
}
catch (IOException e) {
// could happen if the output format is not supported
Logger.getAnonymousLogger().severe(e.getMessage());
}
}
/**
* Creates a buffered image of type TYPE_INT_RGB from the supplied component.
*
* @param component the component to draw
* @return an image of the component
*/
public static BufferedImage createImage(Component component) {
return createImage(component, BufferedImage.TYPE_INT_RGB);
}
/**
* Creates a buffered image (of the specified type) from the supplied component.
*
* @param component the component to draw
* @param bounds the area relative to the component where the image will be created.
* @param imageType the type of buffered image to draw
* @return an image of the component
*/
public static BufferedImage createImage(final Component component, Rectangle bounds, int imageType) {
BufferedImage img = new BufferedImage(bounds.width,
bounds.height,
imageType);
final Graphics2D graphics = img.createGraphics();
graphics.fillRect(0, 0, img.getWidth(), img.getHeight());
// If we are painting a JComponent then switch off double buffering because it
// causes a failure when running headlessly on Linux
if (component instanceof JComponent) {
JComponent c = (JComponent) component;
boolean isDoubleBuffered = c.isDoubleBuffered();
c.setDoubleBuffered(false);
graphics.translate(-bounds.x, -bounds.y);
graphics.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
c.paint(graphics);
c.setDoubleBuffered(isDoubleBuffered);
}
else {
component.paint(graphics);
}
graphics.dispose();
return img;
}
/**
* Creates a buffered image (of the specified type) from the supplied component.
*
* @param component the component to draw
* @param imageType the type of buffered image to draw
* @return an image of the component
*/
public static BufferedImage createImage(final Component component, int imageType) {
Dimension componentSize = component.getSize();
BufferedImage img = new BufferedImage(componentSize.width,
componentSize.height,
imageType);
final Graphics2D graphics = img.createGraphics();
graphics.fillRect(0, 0, img.getWidth(), img.getHeight());
// If we are painting a JComponent then switch off double buffering because it
// causes a failure when running headlessly on Linux
if (component instanceof JComponent) {
JComponent c = (JComponent) component;
boolean isDoubleBuffered = c.isDoubleBuffered();
c.setDoubleBuffered(false);
c.paint(graphics);
c.setDoubleBuffered(isDoubleBuffered);
}
else {
component.paint(graphics);
}
graphics.dispose();
return img;
}
/**
* Creates a thumbnail from the supplied component (such as a chart). If you want to display the thumbnail as a
* component you can pass the created ImageIcon as a parameter to the constructor of a JLabel.
*
* @param component the component from which we would like to generate a thumbnail
* @param width the width of the thumbnail
* @param height the height of the thumbnail
* @return a thumbnail Image of the supplied component
*/
public static Image createThumbnailImage(Component component, int width, int height) {
BufferedImage image = createImage(component);
BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = thumbnailImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
double w = (double) width / image.getWidth();
double h = (double) height / image.getHeight();
assert w <= 1.0 : "The thumbnail should be smaller than the original";
assert h <= 1.0 : "The thumbnail should be smaller than the original";
AffineTransform transform = AffineTransform.getScaleInstance(w, h);
g.drawRenderedImage(image, transform);
return thumbnailImage;
}
/**
* Creates a thumbnail from the supplied component (such as a chart). If you want to display the thumbnail as a
* component you can pass the created ImageIcon as a parameter to the constructor of a JLabel.
*
* @param component the component from which we would like to generate a thumbnail
* @param width the width of the thumbnail
* @param height the height of the thumbnail
* @return an ImageIcon of the supplied component
*/
public static ImageIcon createThumbnail(Component component, int width, int height) {
return new ImageIcon(createThumbnailImage(component, width, height));
}
/**
* Utility method to create a texture paint from a graphics file
*
* @param observer the observer to be informed when the texture image has been drawn
* @param fileName the name of a file on the classpath, e.g., com/mycompany/project/images/widget.gif
* @return a TexturePaint instance
*/
public static TexturePaint createTexture(JComponent observer, String fileName) {
Image image = createImage(fileName);
MediaTracker tracker = new MediaTracker(observer);
tracker.addImage(image, 1);
try {
tracker.waitForAll();
}
catch (Exception e) {
}
int w = image.getWidth(observer);
int h = image.getHeight(observer);
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D big = bi.createGraphics();
big.drawImage(image, 0, 0, observer);
return new TexturePaint(bi, new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
}
/**
* Creates an image from a file on the classpath
*
* @param path the path to the file
* @return an Image object
*/
public static Image createImage(String path) {
ClassLoader loader = IconsFactory.class.getClassLoader();
if (loader != null) {
URL url = loader.getResource(path);
if (url == null) {
url = loader.getResource("/" + path);
}
return Toolkit.getDefaultToolkit().createImage(url);
}
return null;
}
}