/** * 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