/**
*
*/
package vroom.common.modeling.visualization;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.UIManager;
import org.apache.commons.collections15.Transformer;
import vroom.common.modeling.dataModel.IArc;
import vroom.common.modeling.dataModel.INodeVisit;
import vroom.common.modeling.dataModel.IVRPInstance;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
/**
* <code>DefaultInstanceViewer</code> is a specialization of. {@link VisualizationViewer} that defines default colors
* and shapes to represent an {@link IVRPInstance}.
* <p>
* Creation date: Sep 27, 2010 - 5:30:20 PM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public class DefaultInstanceViewer extends VisualizationViewer<INodeVisit, IArc> implements
ComponentListener {
private static final long serialVersionUID = 1L;
/** The vertex size **/
private int mVertexSize;
private final NodeVisitTransformer mTransformer;
/**
* Getter for the node transformer
*
* @return the node transformer
*/
public NodeVisitTransformer getTransformer() {
return mTransformer;
}
/** The underlying graph **/
private final Graph<INodeVisit, IArc> mGraph;
/**
* Getter for the underlying graph
*
* @return the value of name
*/
public Graph<INodeVisit, IArc> getGraph() {
return this.mGraph;
}
/**
* Getter for the vertex size
*
* @return the value of vertexSize
*/
public int getVertexSize() {
return mVertexSize;
}
/**
* Setter for The vertex size
*
* @param vertexSize
* the value to be set for The vertex size
*/
public void setVertexSize(int vertexSize) {
mVertexSize = vertexSize;
mTransformer.setVertexSize(mVertexSize);
update();
}
/**
* Instantiates a new default instance viewer.
*
* @param graph
* the graph
* @param preferredSize
* the preferred size
* @param bounds
* bounds for the nodes coordinates
*/
public DefaultInstanceViewer(Graph<INodeVisit, IArc> graph, Dimension preferredSize,
double[] bounds) {
super(new StaticLayout<INodeVisit, IArc>(graph), preferredSize);
mGraph = graph;
mTransformer = new NodeVisitTransformer(Math.ceil(Math.max(bounds[1] - bounds[0], bounds[3]
- bounds[2])), 14, -bounds[0], -bounds[2]);
getGraphLayout().setInitializer(mTransformer);
addComponentListener(mTransformer);
mVertexSize = UIManager.getFont("Label.font").getSize() + 4;
setDefaultVertexShapeTransformer();
setDefaultVertexFillPaintTransformer();
setDefaultVertexLabelTransformer();
getRenderContext().setVertexFontTransformer(new Transformer<INodeVisit, Font>() {
@Override
public Font transform(INodeVisit arg0) {
return UIManager.getFont("Label.font");
}
});
addComponentListener(this);
}
/**
* Instantiates a new default instance viewer of size 100x100
*
* @param graph
* the graph
*/
public DefaultInstanceViewer(Graph<INodeVisit, IArc> graph) {
this(graph, new Dimension(100, 100), calculateBounds(graph));
}
/**
* Calculate the min and max coordiates of the given graph.
*
* @param graph
* @return an array containing <code>[minX,maxX,minY,naxY]</code>
*/
public static double[] calculateBounds(Graph<INodeVisit, IArc> graph) {
double x, y, minX = Double.POSITIVE_INFINITY, minY = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY, maxY = Double.NEGATIVE_INFINITY;
for (INodeVisit v : graph.getVertices()) {
x = v.getNode().getLocation().getX();
y = v.getNode().getLocation().getX();
if (x > maxX) {
maxX = x;
}
if (x < minX) {
minX = x;
}
if (y > maxY) {
maxY = y;
}
if (x < minY) {
minY = y;
}
}
return new double[] { Math.floor(minX * 1.05), Math.ceil(maxX * 1.05),
Math.floor(minY * 1.05), Math.ceil(maxY * 1.05) };
}
/**
* Sets the default vertex shape transformer.
*/
protected void setDefaultVertexShapeTransformer() {
getRenderContext().setVertexShapeTransformer(new Transformer<INodeVisit, Shape>() {
@Override
public Shape transform(INodeVisit node) {
if (node.isDepot()) {
return new Rectangle2D.Float(-mVertexSize / 2, -mVertexSize / 2, mVertexSize,
mVertexSize);
} else {
return new Ellipse2D.Float(-mVertexSize / 2, -mVertexSize / 2, mVertexSize,
mVertexSize);
}
}
});
}
/**
* Sets the default vertex fill paint transformer.
*/
protected void setDefaultVertexFillPaintTransformer() {
getRenderContext().setVertexFillPaintTransformer(new Transformer<INodeVisit, Paint>() {
@Override
public Paint transform(INodeVisit node) {
if (node.isDepot()) {
return Color.BLACK;
} else {
return Color.DARK_GRAY;
}
}
});
}
/**
* Sets the default vertex label transformer.
*/
protected void setDefaultVertexLabelTransformer() {
getRenderContext().setVertexLabelTransformer(new Transformer<INodeVisit, String>() {
@Override
public String transform(INodeVisit node) {
return "" + node.getID();
}
});
}
/**
* Calls paint. Doesn't clear the background but see ComponentUI.update, which is called by paintComponent.
*/
public void update() {
update(getGraphics());
}
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
}