package prefuse.action.assignment;
import java.awt.BasicStroke;
import java.awt.Stroke;
import java.util.logging.Logger;
import prefuse.action.EncoderAction;
import prefuse.data.expression.Predicate;
import prefuse.data.expression.parser.ExpressionParser;
import prefuse.util.StrokeLib;
import prefuse.visual.VisualItem;
/**
* <p>Assignment Action that assigns <code>Stroke</code> values to VisualItems.
* The Stroke instance determines how lines and shape outlines are drawn,
* including the base size of the line, the line endings and line join types,
* and whether the line is solid or dashed. By default, a StrokeAction simply
* sets each VisualItem to use a default 1-pixel wide solid line. Clients can
* change this default value to achieve uniform Stroke assignment, or can add
* any number of additional rules for Stroke assignment.
* Rules are specified by a Predicate instance which, if returning true, will
* trigger that rule, causing either the provided Stroke value or the result of
* a delegate StrokeAction to be applied. Rules are evaluated in the order in
* which they are added to the StrokeAction, so earlier rules will have
* precedence over rules added later.
* </p>
*
* <p>In addition, subclasses can simply override
* {@link #getStroke(VisualItem)} to achieve custom Stroke assignment. In some
* cases, this may be the simplest or most flexible approach.</p>
*
* @author <a href="http://jheer.org">jeffrey heer</a>
*/
public class StrokeAction extends EncoderAction {
protected BasicStroke defaultStroke = StrokeLib.getStroke(1.0f);
/**
* Create a new StrokeAction that processes all data groups.
*/
public StrokeAction() {
super();
}
/**
* Create a new StrokeAction that processes the specified group.
* @param group the data group to process
*/
public StrokeAction(String group) {
super(group);
}
/**
* Create a new StrokeAction that processes the specified group.
* @param group the data group to process
* @param defaultStroke the default Stroke to assign
*/
public StrokeAction(String group, BasicStroke defaultStroke) {
super(group);
this.defaultStroke = defaultStroke;
}
// ------------------------------------------------------------------------
/**
* Set the default BasicStroke to be assigned to items. Items will be
* assigned the default Stroke if they do not match any registered rules.
* @param f the default BasicStroke to use
*/
public void setDefaultStroke(BasicStroke f) {
defaultStroke = f;
}
/**
* Get the default BasicStroke assigned to items.
* @return the default BasicStroke
*/
public BasicStroke getDefaultStroke() {
return defaultStroke;
}
/**
* Add a mapping rule to this StrokeAction. VisualItems that match
* the provided predicate will be assigned the given BasicStroke value
* (assuming they do not match an earlier rule).
* @param p the rule Predicate
* @param stroke the BasicStroke
*/
public void add(Predicate p, BasicStroke stroke) {
super.add(p, stroke);
}
/**
* Add a mapping rule to this StrokeAction. VisualItems that match
* the provided expression will be assigned the given BasicStroke 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 stroke the BasicStroke
* @throws RuntimeException if the expression does not parse correctly or
* does not result in a Predicate instance.
*/
public void add(String expr, BasicStroke stroke) {
Predicate p = (Predicate)ExpressionParser.parse(expr);
add(p, stroke);
}
/**
* Add a mapping rule to this StrokeAction. VisualItems that match
* the provided predicate will be assigned the BasicStroke value returned
* by the given StrokeAction's getStroke() method.
* @param p the rule Predicate
* @param f the delegate StrokeAction to use
*/
public void add(Predicate p, StrokeAction f) {
super.add(p, f);
}
/**
* Add a mapping rule to this StrokeAction. VisualItems that match
* the provided expression will be assigned the given BasicStroke 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 StrokeAction to use
* @throws RuntimeException if the expression does not parse correctly or
* does not result in a Predicate instance.
*/
public void add(String expr, StrokeAction 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) {
item.setStroke(getStroke(item));
}
/**
* Returns the stroke to use for a given VisualItem. Subclasses should
* override this method to perform customized Stroke assignment.
* @param item the VisualItem for which to get the Stroke
* @return the BasicStroke for the given item
*/
public BasicStroke getStroke(VisualItem item) {
Object o = lookup(item);
if ( o != null ) {
if ( o instanceof StrokeAction ) {
return ((StrokeAction)o).getStroke(item);
} else if ( o instanceof Stroke ) {
return (BasicStroke)o;
} else {
Logger.getLogger(this.getClass().getName())
.warning("Unrecognized Object from predicate chain.");
}
}
return defaultStroke;
}
} // end of class StrokeAction