001 package nl.cwi.sen1.gui.plugin; 002 003 import java.awt.Shape; 004 import java.awt.geom.AffineTransform; 005 import java.awt.geom.GeneralPath; 006 import java.awt.geom.Point2D; 007 import java.awt.geom.Rectangle2D; 008 009 import prefuse.Constants; 010 import prefuse.render.EdgeRenderer; 011 import prefuse.util.GraphicsLib; 012 import prefuse.visual.EdgeItem; 013 import prefuse.visual.VisualItem; 014 015 public class GraphEdgeRenderer extends EdgeRenderer { 016 private static Point2D start = new Point2D.Float(); 017 018 private static Point2D end = new Point2D.Float(); 019 020 public GraphEdgeRenderer(int edgeType, int arrowType) { 021 super(edgeType, arrowType); 022 } 023 024 private boolean onDotLocation(VisualItem item) { 025 return item.getX() == item.getInt(GraphDotLayout.DOT_X) 026 && item.getY() == item.getInt(GraphDotLayout.DOT_Y); 027 } 028 029 private Shape makeCurvedEdge(Point2D start, Point2D end, Point2D[] points) { 030 Point2D from = start; 031 Point2D to = from; 032 033 GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO); 034 gp.moveTo((float) from.getX(), (float) from.getY()); 035 036 int i; 037 for (i = 1; i + 2 < points.length; i += 3) { 038 Point2D cp1 = points[i]; 039 Point2D cp2 = points[i + 1]; 040 Point2D cur = points[i + 2]; 041 042 from = cp1; 043 to = cur; 044 045 gp.curveTo((float) cp1.getX(), (float) cp1.getY(), (float) cp2 046 .getX(), (float) cp2.getY(), (float) cur.getX(), 047 (float) cur.getY()); 048 } 049 050 if (i < points.length) { 051 from = to; 052 to = points[points.length - 1]; 053 gp.lineTo((float) to.getX(), (float) to.getY()); 054 } 055 056 gp.lineTo((float) end.getX(), (float) end.getY()); 057 058 // TODO: remove this hack that is used to retrieve the last direction of 059 // the edge 060 start.setLocation(from); 061 return gp; 062 } 063 064 protected Shape getArrowShape(Point2D start, Point2D end, VisualItem item) { 065 Rectangle2D r = item.getBounds(); 066 int i = GraphicsLib.intersectLineRectangle(start, end, r, m_isctPoints); 067 if (i > 0) { 068 end = m_isctPoints[0]; 069 } 070 AffineTransform at = getArrowTrans(start, end, 1); 071 return at.createTransformedShape(m_arrowHead); 072 } 073 074 protected Shape getRawShape(VisualItem item) { 075 EdgeItem edge = (EdgeItem) item; 076 VisualItem item1 = edge.getSourceItem(); 077 VisualItem item2 = edge.getTargetItem(); 078 079 // If the nodes are not on their original dot positions, the curved 080 // edge degenerates to a straight edge. 081 if (!onDotLocation(item1) || !onDotLocation(item2)) { 082 return super.getRawShape(item); 083 } 084 085 // Find the middle of the start and end nodes 086 getAlignedPoint(start, item1.getBounds(), Constants.CENTER, Constants.CENTER); 087 getAlignedPoint(end, item2.getBounds(), Constants.CENTER, Constants.CENTER); 088 089 // Retrieve the dot curve points data 090 Point2D[] points = (Point2D[]) item.get(GraphDotLayout.CURVE_POINTS); 091 if (points == null) { 092 return super.getRawShape(item); 093 } 094 095 096 // now construct the curved edge 097 Shape shape = makeCurvedEdge(start, end, points); 098 AffineTransform at = getTransform(item); 099 shape = (at == null) ? shape : at.createTransformedShape(shape); 100 101 // create the arrow head, if needed 102 Shape arrow = getArrowShape(start, end, item2); 103 setRenderType(RENDER_TYPE_DRAW_AND_FILL); 104 m_curArrow = arrow; 105 106 setRenderType(RENDER_TYPE_DRAW); 107 return shape; 108 } 109 }