/**
* Copyright (c) 2004-2006 Regents of the University of California.
* See "license-prefuse.txt" for licensing terms.
*/
package prefuse.action.assignment;
import java.util.logging.Logger;
import prefuse.action.EncoderAction;
import prefuse.data.expression.Predicate;
import prefuse.data.expression.parser.ExpressionParser;
import prefuse.util.ColorLib;
import prefuse.util.PrefuseLib;
import prefuse.visual.VisualItem;
/**
* <p>Assignment Action that assigns color values to VisualItems for a
* given color field (e.g., the stroke, text, or fill color).</p>
*
* <p>By default, a ColorAction simply assigns a single default color value
* to all items (the initial default color is black). Clients can change this
* default value to achieve uniform color assignment, or can add any number
* of additional rules for color assignment. Rules are specified by a Predicate
* instance which, if returning true, will trigger that rule, causing either the
* provided color value or the result of a delegate ColorAction to be
* applied. Rules are evaluated in the order in which they are added to the
* ColorAction, so earlier rules will have precedence over rules added later.
* </p>
*
* <p>In addition, subclasses can simply override {@link #getColor(VisualItem)}
* to achieve custom color assignment. In some cases, this may be the simplest
* or most flexible approach.</p>
*
* <p>To automatically assign color values based on varying values of a
* particular data field, consider using the DataColorAction.</p>
*
* <p>Color values are represented using integers, into which 8-bit values for
* the red, green, blue, and alpha channels are stored. For more information
* and utilities for creating and manipulating color values, see the
* {@link prefuse.util.ColorLib} class.</p>
*
* @author <a href="http://jheer.org">jeffrey heer</a>
* @see prefuse.util.ColorLib
* @see DataColorAction
*/
public class ColorAction extends EncoderAction {
protected String m_colorField;
protected String m_startField;
protected String m_endField;
protected int m_cidx, m_sidx, m_eidx;
protected int m_defaultColor = ColorLib.gray(0); // initial default = black
/**
* Constructor, sets the data group and color field for color assignment.
* Uses an initial default color value of black [RGB value (0,0,0)].
* @param group the data group processed by this Action
* @param field the color field assigned by this Action
*/
public ColorAction(String group, String field) {
super(group);
setField(field);
}
/**
* Constructor, sets the data group, color field, and default color value
* for color assignment.
* @param group the data group processed by this Action
* @param field the color field assigned by this Action
* @param color the default color value assigned by this ColorAction
*/
public ColorAction(String group, String field, int color) {
this(group, field);
m_defaultColor = color;
}
/**
* Constructor, sets the data group, filter predicate and color field
* for color assignment.
* Uses an initial default color value of black [RGB value (0,0,0)].
* @param group the data group processed by this Action
* @param filter the filter predicate
* {@link prefuse.data.expression.Predicate}
* @param field the color field assigned by this Action
*/
public ColorAction(String group, Predicate filter, String field) {
super(group, filter);
setField(field);
}
/**
* Constructor, sets the data group, filter predicate,
* color field, and default color value for color assignment.
* @param group the data group processed by this Action
* @param filter the filter predicate
* {@link prefuse.data.expression.Predicate}
* @param field the color field assigned by this Action
* @param color the default color value assigned by this ColorAction
*/
public ColorAction(String group, Predicate filter, String field, int color)
{
this(group, filter, field);
setDefaultColor(color);
}
/**
* Set the color field name that this ColorAction should set. The
* ColorAction will automatically try to update the start and end
* values for this field if it is an interpolated field.
* @param field
*/
public void setField(String field) {
m_colorField = field;
m_startField = PrefuseLib.getStartField(field);
m_endField = PrefuseLib.getEndField(field);
}
/**
* Returns the default color for this ColorAction
* @return the default color value
*/
public int getDefaultColor() {
return m_defaultColor;
}
/**
* Sets the default color for this ColorAction. Items will be assigned
* the default color if they do not match any registered rules.
* @param color the new default color
*/
public void setDefaultColor(int color) {
m_defaultColor = color;
}
/**
* Add a color mapping rule to this ColorAction. VisualItems that match
* the provided predicate will be assigned the given color value (assuming
* they do not match an earlier rule).
* @param p the rule Predicate
* @param color the color value
*/
public void add(Predicate p, int color) {
super.add(p, new Integer(color));
}
/**
* Add a color mapping rule to this ColorAction. VisualItems that match
* the provided expression will be assigned the given color value (assuming
* they do not match an earlier rule). The provided expression String will
* be parsed to generate the needed rule Predicate.
* @param expr the expression String, should parse to a Predicate.
* @param color the color value
* @throws RuntimeException if the expression does not parse correctly or
* does not result in a Predicate instance.
*/
public void add(String expr, int color) {
Predicate p = (Predicate)ExpressionParser.parse(expr);
add(p, color);
}
/**
* Add a color mapping rule to this ColorAction. VisualItems that match
* the provided predicate will be assigned the color value returned by
* the given ColorAction's getColor() method.
* @param p the rule Predicate
* @param f the delegate ColorAction to use
*/
public void add(Predicate p, ColorAction f) {
super.add(p, f);
}
/**
* Add a color mapping rule to this ColorAction. VisualItems that match
* the provided expression will be assigned the given color value (assuming
* they do not match an earlier rule). The provided expression String will
* be parsed to generate the needed rule Predicate.
* @param expr the expression String, should parse to a Predicate.
* @param f the delegate ColorAction to use
* @throws RuntimeException if the expression does not parse correctly or
* does not result in a Predicate instance.
*/
public void add(String expr, ColorAction f) {
Predicate p = (Predicate)ExpressionParser.parse(expr);
super.add(p, f);
}
// ------------------------------------------------------------------------
/**
* @see prefuse.action.ItemAction#process(prefuse.visual.VisualItem, double)
*/
public void process(VisualItem item, double frac) {
int c = getColor(item);
int o = item.getInt(m_colorField);
item.setInt(m_startField, o);
item.setInt(m_endField, c);
item.setInt(m_colorField, c);
}
/**
* Returns a color value for the given item. Colors are represented as
* integers, interpreted as holding values for the red, green, blue, and
* alpha channels. This is the same color representation returned by
* the Color.getRGB() method.
* @param item the item for which to get the color value
* @return the color value for the item
*/
public int getColor(VisualItem item) {
Object o = lookup(item);
if ( o != null ) {
if ( o instanceof ColorAction ) {
return ((ColorAction)o).getColor(item);
} else if ( o instanceof Integer ) {
return ((Integer)o).intValue();
} else {
Logger.getLogger(this.getClass().getName())
.warning("Unrecognized Object from predicate chain.");
}
}
return m_defaultColor;
}
} // end of class ColorAction