package implementation.source.java.nodes; import implementation.source.java.file.GraphFrame; import java.awt.Color; import java.awt.Point; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import edu.umd.cs.piccolo.nodes.PPath; import edu.umd.cs.piccolox.handles.PHandle; import edu.umd.cs.piccolox.util.PLocator; /** * @author Timothy Ober */ public class DFEdge extends PPath { /** * @author Timothy Ober * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class Arrowhead extends PPath { /** * */ public Arrowhead() { super(); } /** * @param arg0 */ public Arrowhead(Shape arg0) { super(arg0); } /** * @param arg0 * @param arg1 */ public Arrowhead(Shape arg0, Stroke arg1) { super(arg0, arg1); } } final int ARROW_LENGTH = 15; final double ARROW_WIDTH = Math.PI / 6; final int ERR = 2; DFEndpoint endFrom; DFEndpoint endTo; GraphFrame graphFrame; DFLabel label; ArrayList controlPoints; Arrowhead arrowHead; public DFEdge(DFEndpoint from, DFEndpoint to, GraphFrame gf) { super(); endFrom = from; endTo = to; graphFrame = gf; controlPoints = new ArrayList(); arrowHead = new Arrowhead(); addChild(arrowHead); addStartingHandles(); label = new DFLabel("New Edge"); centerLabel(); addChild(label); } public void showLabel(boolean show) { if (show) { if (!getChildrenReference().contains(label)) { addChild(label); } } else { if (getChildrenReference().contains(label)) { removeChild(label); } } } private void centerLabel() { label.setX(getX() - (label.getWidth() / 2) + (getWidth() / 2)); label.setY(getY() - (label.getHeight() / 2) + (getHeight() / 2)); } private void addStartingHandles() { SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeEndpointHandle(l, this, endFrom); addChild(h); controlPoints.add(h); h.setVisible(false); h.setPickable(false); l = new SetXYLocator(); h = new DFEdgeEndpointHandle(l, this, endTo); addChild(h); controlPoints.add(h); h.setVisible(false); h.setPickable(false); drawEdge(); } public void addControlPoint(double x, double y) { if (controlPoints.size() > 1) { Rectangle2D addPoint = new Rectangle2D.Double(x - ERR, y - ERR, ERR * 2, ERR * 2); PLocator tp0 = ((PHandle)controlPoints.get(0)).getLocator(); PLocator tp1 = ((PHandle)controlPoints.get(1)).getLocator(); Point midPoint2 = new Point((int) ((tp0.locateX() + tp1.locateX()) / 2), (int) ((tp1.locateY() + tp0.locateY()) / 2)); Point midPoint1 = null; moveTo((float)tp0.locateX(), (float)tp0.locateY()); lineTo((float)midPoint2.getX(), (float)midPoint2.getY()); if (intersects(addPoint)) { SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeHandle(l, this); l.setX(x); l.setY(y); addChild(h); controlPoints.add(1, h); drawEdge(); return; } for (int index = 1; index < controlPoints.size() - 1; index++) { tp0 = tp1; tp1 = ((PHandle)controlPoints.get(index + 1)).getLocator(); midPoint1 = midPoint2; midPoint2 = new Point((int) ((tp0.locateX() + tp1.locateX()) / 2), (int) ((tp1.locateY() + tp0.locateY()) / 2)); curveTo((float)midPoint1.getX(), (float)midPoint1.getY(), (float)tp0.locateX(), (float)tp0.locateY(), (float)midPoint2.getX(), (float)midPoint2.getY()); if (intersects(addPoint)) { SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeHandle(l, this); addChild(h); controlPoints.add(index + 1, h); h.setVisible(false); h.setPickable(false); drawEdge(); return; } } lineTo((float)tp1.locateX(), (float)tp1.locateY()); if (intersects(addPoint)) { SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeHandle(l, this); addChild(h); controlPoints.add(controlPoints.size() - 1, h); h.setVisible(false); h.setPickable(false); drawEdge(); return; } } } public void deleteControlPoint(DFEdgeHandle h) { controlPoints.remove(h); h.setVisible(false); h.setPickable(false); drawEdge(); } public void enableControlPoints() { for (int ndx = 0; ndx < controlPoints.size(); ndx++) { ((PHandle)controlPoints.get(ndx)).setPickable(true); } for (int ndx = 0; ndx < controlPoints.size(); ndx++) { ((PHandle)controlPoints.get(ndx)).setVisible(true); } repaint(); } public void disableControlPoints() { for (int ndx = 0; ndx < controlPoints.size(); ndx++) { ((PHandle)controlPoints.get(ndx)).setPickable(false); } for (int ndx = 0; ndx < controlPoints.size(); ndx++) { ((PHandle)controlPoints.get(ndx)).setVisible(false); } repaint(); } public void drawEdge() { PLocator tmp; if (controlPoints.size() > 1) { PLocator tp0 = ((PHandle)controlPoints.get(0)).getLocator(); PLocator tp1 = ((PHandle)controlPoints.get(1)).getLocator(); Point midPoint2 = new Point((int) ((tp0.locateX() + tp1.locateX()) / 2), (int) ((tp1.locateY() + tp0.locateY()) / 2)); Point midPoint1 = null; moveTo((float)tp0.locateX(), (float)tp0.locateY()); lineTo((float)midPoint2.getX(), (float)midPoint2.getY()); for (int index = 1; index < controlPoints.size() - 1; index++) { tp0 = tp1; tp1 = ((PHandle)controlPoints.get(index + 1)).getLocator(); midPoint1 = midPoint2; midPoint2 = new Point((int) ((tp0.locateX() + tp1.locateX()) / 2), (int) ((tp1.locateY() + tp0.locateY()) / 2)); curveTo((float)midPoint1.getX(), (float)midPoint1.getY(), (float)tp0.locateX(), (float)tp0.locateY(), (float)midPoint2.getX(), (float)midPoint2.getY()); } lineTo((float)tp1.locateX(), (float)tp1.locateY()); if (endTo.getClass().equals(DFNode.class)) { drawArrow((float)midPoint2.getX(), (float)midPoint2.getY(), (float)tp1.locateX(), (float)tp1.locateY()); } } repaint(); } private void drawArrow(float x0, float y0, float x1, float y1) { float o = y1 - y0; float a = x1 - x0; float theta = (float)Math.atan(o / a); arrowHead.reset(); arrowHead.moveTo(x1, y1); if (x1 > x0) { arrowHead.lineTo((float)(x1 - (ARROW_LENGTH * Math.cos(theta + ARROW_WIDTH / 2))), (float)(y1 - (ARROW_LENGTH * Math.sin(theta + ARROW_WIDTH / 2)))); arrowHead.lineTo((float)(x1 - (ARROW_LENGTH * Math.cos(theta - ARROW_WIDTH / 2))), (float)(y1 - (ARROW_LENGTH * Math.sin(theta - ARROW_WIDTH / 2)))); } else { arrowHead.lineTo((float)(x1 + (ARROW_LENGTH * Math.cos(theta + ARROW_WIDTH / 2))), (float)(y1 + (ARROW_LENGTH * Math.sin(theta + ARROW_WIDTH / 2)))); arrowHead.lineTo((float)(x1 + (ARROW_LENGTH * Math.cos(theta - ARROW_WIDTH / 2))), (float)(y1 + (ARROW_LENGTH * Math.sin(theta - ARROW_WIDTH / 2)))); } arrowHead.closePath(); arrowHead.setPaint(Color.BLACK); } public DFEndpoint getEndFrom() {return endFrom;} public DFEndpoint getEndTo() {return endTo;} public void setEndFrom(DFEndpoint e) { endFrom = e; removeChild((PHandle)controlPoints.get(0)); controlPoints.remove(controlPoints.get(0)); SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeEndpointHandle(l, this, endFrom); addChild(h); controlPoints.add(0, h); h.setVisible(false); h.setPickable(false); if (e.getClass().equals(DFNode.class)) { ((DFNode)e).getEdgesOut().add(this); } else if (e.getClass().getSuperclass().equals(DFPort.class)) { ((DFPort)e).setEdge(this); } drawEdge(); } public void setEndTo(DFEndpoint e) { endTo = e; removeChild((PHandle)controlPoints.get(controlPoints.size() - 1)); controlPoints.remove(controlPoints.get(controlPoints.size() - 1)); SetXYLocator l = new SetXYLocator(); PHandle h = new DFEdgeEndpointHandle(l, this, endTo); addChild(h); controlPoints.add(h); h.setVisible(false); h.setPickable(false); if (e.getClass().equals(DFNode.class)) { ((DFNode)e).getEdgesIn().add(this); } else if (e.getClass().getSuperclass().equals(DFPort.class)) { ((DFPort)e).setEdge(this); } drawEdge(); } public GraphFrame getGraphFrame() {return graphFrame;} public void updateNodeFromHandle() { ((DFEdgeEndpointHandle)controlPoints.get(0)).updateHandleLocation(); repaint(); } public void updateNodeToHandle() { ((DFEdgeEndpointHandle)controlPoints.get(controlPoints.size() - 1)).updateHandleLocation(); repaint(); } }