/* * This file is part of the OSMembrane project. * More informations under www.osmembrane.de * * The project is licensed under the GNU GENERAL PUBLIC LICENSE 3.0. * for more details about the license see http://www.osmembrane.de/license/ * * Source: $HeadURL$ ($Revision$) * Last changed: $Date$ */ package de.osmembrane.view.panels; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.ImageIcon; import javax.swing.JPanel; /** * A {@link JPanel} component with the ability to create colored {@link Image}s * with icons from an {@link ImageIcon} display template. * * To create a displayable {@link Image}, just call * {@link DisplayTemplatePanel#derivateDisplay} with the desired {@link Color} * and icon. * * Howsoever it is capable of pre-rendering all objects necessary into a map and * get them out once they're needed without any extra overhead. * * <b>It is recommended you use the static ability of prerendering since that * will save a lot of memory and processing power.</b> * * @author tobias_kuhn * */ public abstract class DisplayTemplatePanel extends JPanel { protected static final long serialVersionUID = -2046897951374601603L; /** * Map used for the prerendered objects. */ private static Map<Object, List<Image>> prerender; /** * Internal {@link DisplayTemplatePanel} for prerendering. * (derivateDisplay() calls are only possible on instances) */ private static DisplayTemplatePanel prerenderPanel; /** * Renders the correct pre-rendered display image based on template in the * given color and with the given icon. * * @param template * the ImageIcon to colorize and iconify * @param color * The Color this image shall display in * @param icon * The icon this image shall display * @return the pre-rendered Image in the color and with the icon */ protected Image derivateDisplay(ImageIcon template, Color color, Image icon) { // copy displayTemplate to a BufferedImage BufferedImage result = new BufferedImage(template.getIconWidth(), template.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g = result.createGraphics(); g.drawImage(template.getImage(), 0, 0, this); WritableRaster r = result.getRaster(); // Scan the lines with a float multiplication float[] colorRGB = color.getColorComponents(null); float[] pixelRow = new float[4 * result.getWidth()]; for (int y = 0; y < result.getHeight(); y++) { r.getPixels(0, y, result.getWidth() - 1, 1, pixelRow); for (int x = 0; x < result.getWidth(); x++) { pixelRow[4 * x + 0] *= colorRGB[0]; pixelRow[4 * x + 1] *= colorRGB[1]; pixelRow[4 * x + 2] *= colorRGB[2]; } r.setPixels(0, y, result.getWidth() - 1, 1, pixelRow); } // place the icon if (icon != null) { g.drawImage(icon, getWidth() - (icon.getWidth(this) / 2), getHeight() - (icon.getHeight(this) / 2), this); } return result; } /** * Calls * {@link DisplayTemplatePanel#derivateDisplay(ImageIcon, Color, Image)} for * the object forObject and stores it in the list for forObject for quick * further access. * * If there is already an image stored for forObject, it is overwritten. You * can easily test this by checking * {@link DisplayTemplatePanel#givePrerender(Object)} == null. * * @param forObject * object to identify the prerendering * @see #derivateDisplay(ImageIcon, Color, Image) * @return the immediately created Image */ protected static Image prerenderDisplay(Object forObject, ImageIcon template, Color color, Image icon) { if (prerender == null) { prerender = new HashMap<Object, List<Image>>(); } if (prerenderPanel == null) { prerenderPanel = new DisplayTemplatePanel() { private static final long serialVersionUID = -8556169733942717510L; }; } if (prerender.get(forObject) == null) { prerender.put(forObject, new ArrayList<Image>()); } Image created = prerenderPanel.derivateDisplay(template, color, icon); prerender.get(forObject).add(created); return created; } /** * Returns the prerendered {@link Image} created for forObject * * @param forObject * object to identify the prerendering * @return the prerendered images for forObject, or null if none exists */ protected static List<Image> givePrerender(Object forObject) { return (prerender != null) ? prerender.get(forObject) : null; } }