// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/util/ColorFactory.java,v $
// $RCSfile: ColorFactory.java,v $
// $Revision: 1.7 $
// $Date: 2005/08/11 20:39:15 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.util;
import java.awt.Color;
import java.awt.Paint;
import java.lang.reflect.Field;
import java.util.Properties;
/**
* ColorFactory creates instances of colors. This class has methods which create
* <code>java.awt.Color</code> or
* <code>com.bbn.openmap.omGraphics.OMColor</code> objects. This class handles
* creation of Color objects in a Java version-neutral way by using reflection
* to create the java.awt.Color object. This way we support the extended Java 2
* platform without sacrificing support for JDK 1.1.X.
* <p>
* NOTE: For general RGB-colored graphics, you should directly use the
* java.awt.Color 1.1.X constructors. If you are interested in using
* alpha-valued colors, or using colors in a (JDK) version-neutral way, then
* read on...
* <p>
* You may want to use this class because:
* <ul>
* <li>You want to use alpha-valued colors in your images under both JDK 1.1 and
* JDK 1.2. (JDK1.1 has limited support for alpha-valued images). You can use
* the appropriate <code>createColor()</code> methods in this class with the
* <code>forceAlpha</code> set to <code>true</code> and you are guaranteed
* (almost!) to get back an alpha-valued color.
* <p>
* <li>You want to use alpha-valued colors for generic graphics, but only in a
* version-neutral way and if the support is available (e.g., you're running
* under the Java 2 platform). In this case you can call the appropriate
* <code>createColor()</code> methods without the <code>forceAlpha</code>
* argument, or with <code>forceAlpha</code> set to false.
* </ul>
*
* @see com.bbn.openmap.omGraphics.OMColor
*/
public class ColorFactory {
/**
* Take a string from a properties file, representing the 24bit RGB or 32bit
* ARGB hex values for a color, and convert it to a java.awt.Color.
*
* @param p
* properties
* @param propName
* the name of the property
* @param dfault
* color to use if the property value doesn't work
* @return java.awt.Color
* @exception NumberFormatException
* if the specified string cannot be interpreted as a
* hexidecimal integer
* @see #parseColor(String, boolean)
*/
public static Color parseColorFromProperties(Properties p, String propName, String dfault)
throws NumberFormatException {
String colorString = p.getProperty(propName, dfault);
return parseColor(colorString, true);
}
/**
* Take a string from a properties file, representing the 24bit RGB or 32bit
* ARGB hex values for a color, and convert it to a java.awt.Color.
*
* @param p
* properties
* @param propName
* the name of the property
* @param dfault
* color to use if the property value doesn't work
* @param forceAlpha
* force using alpha value
* @return java.awt.Color
* @exception NumberFormatException
* if the specified string cannot be interpreted as a
* hexidecimal integer
* @see #parseColor(String, boolean)
*/
public static Color parseColorFromProperties(Properties p, String propName, String dfault, boolean forceAlpha)
throws NumberFormatException {
String colorString = p.getProperty(propName, dfault);
return parseColor(colorString, forceAlpha);
}
/**
* Take a string from a properties file, representing the 24bit RGB or 32bit
* ARGB hex values for a color, and convert it to a java.awt.Color.
*
* @param p
* properties
* @param propName
* the name of the property
* @param dfault
* color to use if the property value doesn't work
* @return java.awt.Color
* @see #parseColor(String, boolean)
*/
public static Paint parseColorFromProperties(Properties p, String propName, Paint dfault) {
try {
String colorString = p.getProperty(propName);
if (colorString != null) {
return parseColor(colorString, true);
}
} catch (NumberFormatException nfe) {
}
return dfault;
}
/**
* Convert a string representing a 24/32bit hex color value into a Color
* value.
*
* @param colorString
* the 24/32bit hex string value (ARGB)
* @return java.awt.Color 24bit RGB, 24/32bit ARGB
* @exception NumberFormatException
* if the specified string cannot be interpreted as a
* hexidecimal integer
* @see #parseColor(String, boolean)
*/
public static Color parseColor(String colorString) throws NumberFormatException {
return parseColor(colorString, true);
}
/**
* Convert a string representing a 24/32bit hex color value into a Color
* value. NOTE:
* <ul>
* <li>Only 24bit (RGB) java.awt.Color is supported on the JDK 1.1 platform.
* <li>Both 24/32bit (ARGB) java.awt.Color is supported on the Java 2
* platform.
* </ul>
*
* @param colorString
* the 24/32bit hex string value (ARGB)
* @param forceAlpha
* force using alpha value
* @return java.awt.Color (24bit RGB on JDK 1.1, 24/32bit ARGB on JDK1.2)
* @exception NumberFormatException
* if the specified string cannot be interpreted as a
* hexidecimal integer
* @see #createColor(int, boolean)
*/
public static Color parseColor(String colorString, boolean forceAlpha) throws NumberFormatException {
int value;
// If we come across people who do one letter per color.
if (colorString.length() == 3) {
colorString = new StringBuilder().append(colorString.charAt(0)).append(colorString.charAt(0))
.append(colorString.charAt(1)).append(colorString.charAt(1)).append(colorString.charAt(2))
.append(colorString.charAt(2)).toString();
}
try {
value = (int) Long.parseLong(colorString, 16);
} catch (NumberFormatException nfe) {
value = Long.decode(colorString).intValue();
// If decode can't catch it, throw an Exception...
}
// We want to test for this - if the length of the colorString
// is less than 7, then the caller probably doesn't care about
// transparency and wants the color to be opaque. However,
// "0" is a common number for clear, and should be
// transparent.
if (colorString.length() < 7 && !colorString.equals("0")) {
// Just a RGB value, use regular JDK1.1 constructor
return new Color(value);
}
return createColor(value, forceAlpha);
}
/**
* Create a Color.
*
* @param red
* red component (0.0-1.0)
* @param green
* green component (0.0-1.0)
* @param blue
* blue component (0.0-1.0)
* @param alpha
* alpha component (0.0-1.0)
* @return Color or OMColor that has an ARGB value
* @see #createColor(int, boolean)
*/
public static Color createColor(float red, float green, float blue, float alpha) {
return createColor(red, green, blue, alpha, true);
}
/**
* Create a Color.
*
* @param red
* red component (0.0-1.0)
* @param green
* green component (0.0-1.0)
* @param blue
* blue component (0.0-1.0)
* @param alpha
* alpha component (0.0-1.0)
* @param forceAlpha
* force using alpha value
* @return Color or OMColor that has an ARGB value
* @see #createColor(int, boolean)
*/
public static Color createColor(float red, float green, float blue, float alpha, boolean forceAlpha) {
int value = (((int) (alpha * 255) & 0xff) << 24) | (((int) (red * 255) & 0xff) << 16)
| (((int) (green * 255) & 0xff) << 8) | (int) (blue * 255) & 0xff;
return createColor(value, forceAlpha);
}
/**
* Create a Color.
*
* @param red
* red component (0-255)
* @param green
* green component (0-255)
* @param blue
* blue component (0-255)
* @param alpha
* alpha component (0-255)
* @return Color or OMColor that has an ARGB value
* @see #createColor(int, boolean)
*/
public static Color createColor(int red, int green, int blue, int alpha) {
return createColor(red, green, blue, alpha, true);
}
/**
* Create a Color.
*
* @param red
* red component (0-255)
* @param green
* green component (0-255)
* @param blue
* blue component (0-255)
* @param alpha
* alpha component (0-255)
* @param forceAlpha
* force using alpha value
* @return Color or OMColor that has an ARGB value
* @see #createColor(int, boolean)
*/
public static Color createColor(int red, int green, int blue, int alpha, boolean forceAlpha) {
int value = ((alpha & 0xff) << 24) | ((red & 0xff) << 16) | ((green & 0xff) << 8) | blue & 0xff;
return createColor(value, forceAlpha);
}
/**
* Create a Color.
*
* @param value
* 32bit ARGB color value
* @return Color or OMColor that has an ARGB value
* @see #createColor(int, boolean)
*/
public static Color createColor(int value) {
return createColor(value, true);
}
/**
* Create a Color.
*
* @param value
* 32bit ARGB color value
* @param forceAlpha
* force using alpha value the underlying java.awt.Color supports
* it
* @return Color or OMColor that has an ARGB value
*/
public static Color createColor(int value, boolean forceAlpha) {
return new Color(value, forceAlpha);
}
public static String getHexColorString(Color color) {
return Integer.toHexString((color.getRGB() & 0x00FFFFFF) | (color.getAlpha() << 24));
}
/**
* Method that returns a java.awt.Color object given the name of the color.
* Depends on the static instances of color provided by the java.awt.Color
* class.
*
* @param name
* @param defaultColor
* @return Color that reflects the name, or the default color.
*/
public static Color getNamedColor(String name, Color defaultColor) {
if (name != null) {
Field[] colorFields = Color.class.getDeclaredFields();
for (int i = 0; i < colorFields.length; i++) {
Field f = colorFields[i];
try {
if (name.equalsIgnoreCase(f.getName())) {
return (Color) f.get((Object) null);
}
} catch (IllegalAccessException iae) {
// Whoa, shouldn't happen, but hey
} catch (ClassCastException cce) {
// Shouldn't ask for anything other than colors,
// either.
}
}
}
return defaultColor;
}
}