package org.freehep.swing; import java.awt.Color; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; import javax.swing.JColorChooser; /** A utility class for converting strings to color's. * @author Tony Johnson * @author M.Donszelmann * @version $Id: ColorConverter.java 8981 2006-09-15 02:46:28Z serbo $ */ public class ColorConverter { private static ColorConverter defaultInstance = new ColorConverter(true); private Map colorToString; private Map stringToColor; /** Creates an instance of ColorConverter with the default color conversions */ public ColorConverter() { this(false); } private ColorConverter(boolean init) { if (init) { colorToString = new HashMap(); stringToColor = new HashMap(); init(); } else { colorToString = new HashMap(defaultInstance.colorToString); stringToColor = new HashMap(defaultInstance.stringToColor); } } private void init() { //first we look for the special named Java colors addEntry(Color.black, "Black"); addEntry(Color.blue, "Blue"); addEntry(Color.cyan, "Cyan"); addEntry(Color.darkGray, "Dark Gray"); addEntry(Color.gray, "Gray"); addEntry(Color.green, "Green"); addEntry(Color.lightGray, "Light Gray"); addEntry(Color.magenta, "Magenta"); addEntry(Color.orange, "Orange"); addEntry(Color.pink, "Pink"); addEntry(Color.red, "Red"); addEntry(Color.white, "White"); addEntry(Color.yellow, "Yellow"); //now we look for the HTML3.2 colors (we look for all of them since //we don't want to depend on the RGB values of Java and HTML3.2 colors //being the same) addEntry(new Color(0, 0, 0), "Black"); addEntry(new Color(192, 192, 192), "Silver"); addEntry(new Color(128, 128, 128), "Gray"); addEntry(new Color(255, 255, 255), "White"); addEntry(new Color(128, 0, 0), "Maroon"); addEntry(new Color(255, 0, 0), "Red"); addEntry(new Color(128, 0, 128), "Purple"); addEntry(new Color(255, 0, 255), "Fuchsia"); addEntry(new Color(0, 128, 0), "Green"); addEntry(new Color(0, 255, 0), "Lime"); addEntry(new Color(128, 128, 0), "Olive"); addEntry(new Color(255, 255, 0), "Yellow"); addEntry(new Color(0, 0, 128), "Navy"); addEntry(new Color(0, 0, 255), "Blue"); addEntry(new Color(0, 128, 128), "Teal"); addEntry(new Color(0, 255, 255), "Aqua"); //now we look for the "all hail Crayola" colors :) //(we don't look for those which are also Java named colors) addEntry(new Color(0.1f, 0.1f, 0.1f), "Gray 10%"); addEntry(new Color(0.2f, 0.2f, 0.2f), "Gray 20%"); addEntry(new Color(0.3f, 0.3f, 0.3f), "Gray 30%"); addEntry(new Color(0.4f, 0.4f, 0.4f), "Gray 40%"); addEntry(new Color(0.5f, 0.5f, 0.5f), "Gray 50%"); addEntry(new Color(0.6f, 0.6f, 0.6f), "Gray 60%"); addEntry(new Color(0.7f, 0.7f, 0.7f), "Gray 70%"); addEntry(new Color(0.8f, 0.8f, 0.8f), "Gray 80%"); addEntry(new Color(0.9f, 0.9f, 0.9f), "Gray 90%"); addEntry(new Color(255, 136, 28), "Orange"); addEntry(new Color(120, 62, 27), "Brown"); addEntry(new Color(0, 125, 32), "Forest Green"); addEntry(new Color(11, 157, 150), "Turquoise"); addEntry(new Color(109, 0, 168), "Purple"); addEntry(new Color(168, 0, 126), "Magenta"); addEntry(new Color(164, 207, 255), "Sky Blue"); addEntry(new Color(225, 170, 255), "Violet"); addEntry(new Color(255, 170, 210), "Light Magenta"); } /** * Creates new JColorChooser with extra panel that allows to choose * Color by name */ public static JColorChooser getColorChooser() { JColorChooser chooser = new JColorChooser(); chooser.addChooserPanel(new ColorNameChooserPanel()); return chooser; } /** Convert a color to a string, using the default ColorConverter * @param color The color to convert * @return The resulting String */ public static String get(Color color) { return defaultInstance.colorToString(color); } /** Converts a string to a color, using the default ColorConverter * @param name The string to convert * @return The resulting color * @throws ColorConversionException Thrown if the given string cannot be converted to a color */ public static Color get(String name) throws ColorConversionException { return defaultInstance.stringToColor(name); } /** Returns array of all Color names that are added, each name is unique * @return Array of names for all colors, each name is unique */ public static String[] getNames() { return defaultInstance.colorNames(); } /** Returns array of all Color names that are added, each name is unique * @return Array of names for all colors, each name is unique */ public String[] colorNames() { ArrayList list = new ArrayList(colorToString.size()); Iterator it = colorToString.values().iterator(); while(it.hasNext()) { String name = (String) it.next(); if (!list.contains(name)) list.add(name); } Collections.sort(list); String[] names = new String[list.size()]; names = (String[]) list.toArray(names); return names; } /** Add an entry to the color converter map * @param c The color to add * @param name The name corresponding to the color */ public void addEntry(Color c, String name) { stringToColor.put(name.toLowerCase(), c); colorToString.put(c, name); } /** Clear all the mappings from the color converter */ public void clear() { stringToColor.clear(); colorToString.clear(); } /** Convert the given color to a string. * @param color The color to be converted * @return Teh resulting string */ public String colorToString(Color color) { String name = (String) colorToString.get(color); return (name != null) ? name : getRGBName(color); } /** this method returns a Color. Colors are supposedly immutable * and are returned from the same table. * The supported formats are: * <pre> * by name: "yellow" , where alpha is always 1.0 * by int r,g,b,a: "128, 255, 64, 255" , where alpha (a) is optional * by float r,g,b,a: "0.5, 1.0, 0.25, 1.0" , where alpha (a) is optional * by single number: "64637" or "0x0FFF08" , where alpha is always 1.0 * </pre> * @param name name/number of the color * @return requested Color or defaulting to white in case of a invalid name (message is printed). * @throws ColorConversionException Thrown if the given string cannot be converted to a color */ public Color stringToColor(String name) throws ColorConversionException { name = name.toLowerCase(); // first look up if its name exists in the table Color c = (Color) stringToColor.get(name); if (c == null) { try { // check if the format is r,g,b,a if (name.indexOf(',') > 0) { StringTokenizer st = new StringTokenizer(name, ","); int[] i = new int[4]; float[] f = new float[4]; String red = st.nextToken().trim(); String green = st.nextToken().trim(); String blue = st.nextToken().trim(); String alpha = st.hasMoreTokens() ? st.nextToken().trim() : null; try { i[0] = Integer.parseInt(red); i[1] = Integer.parseInt(green); i[2] = Integer.parseInt(blue); i[3] = (alpha != null) ? Integer.parseInt(alpha) : 255; c = createColor(i[0], i[1], i[2], i[3]); } catch (NumberFormatException nfe1) { f[0] = Float.parseFloat(red); f[1] = Float.parseFloat(green); f[2] = Float.parseFloat(blue); f[3] = (alpha != null) ? Float.parseFloat(alpha) : 1.0f; c = createColor(f[0], f[1], f[2], f[3]); } } else { // the format should be rgb in a single number c = Color.decode(name); } } catch (Throwable t) { throw new ColorConversionException(name, t); } } return c; } /** * Return a color for the given values. * Subclasses may override this to tweak colors. */ protected Color createColor(int red, int green, int blue, int alpha) { return new Color(red, green, blue, alpha); } /** * Return a color for the given values. * Subclasses may override this to tweak colors. */ protected Color createColor(float red, float green, float blue, float alpha) { return new Color(red, green, blue, alpha); } private static String getRGBName(Color color) { return color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ", " + color.getAlpha(); } /** An exception thrown if a given string cannot be converted to a Color */ public static class ColorConversionException extends Exception { ColorConversionException(String value, Throwable cause) { super("Cannot convert " + value + " to Color"); initCause(cause); } } }