package att.grappa; import java.awt.*; import java.util.*; /** * This class provides the basis for actually drawing edge elements on a pane. * Extensions of this class and its subclasses allow for the specific drawing * requirements of a particular edge element. For each DrawEdge * instance and target DrawPane instance, there is one * DrawEdgePeer instance. * The size and position of the object are possibly scaled and translated from * the values originally supplied through the element attributes as * a consequence of the characteristics of the DrawPane. * Certainly the y-axis is flipped to account for the origin at the upper-left * as used by the AWT versus the origin to the lower-left as used by the graph. * * @version 1.1, 18 May 1998; Copyright 1996, 1997, 1998 by AT&T Corp. * @author John Mocenigo, Research @ AT&T Labs */ public class DrawEdgePeer extends DrawObjectPeer { protected Polygon polyline = null; protected Polygon startArrow = null; protected Polygon endArrow = null; protected Rectangle bbox = new Rectangle(); protected int lineSize = 0; /** * Creates a DrawEdgePeer related to the supplied DrawEdge * and DrawPane. * * @param drawEdge the source object for this peer object * @param pane the pane to use when drawing this peer */ public DrawEdgePeer(DrawEdge drawEdge, DrawPane pane) { super((DrawObject)drawEdge,pane); } /** * Checks if the supplied co-ordinates are in the specific shape of * this peer. * * @param x the x co-ordinate to check * @param y the y co-ordinate to check * @return true if the co-ordinates lie inside the peer or on its boundary, * false otherwise. */ public boolean inPeer(int x, int y) { if(polyline == null) { setupPeer(true); //throw new IllegalStateException("cannot ask for bounds before Peer is built"); } int[] fuzz = { 0, 1, -1 }; int xp = 0; int yp = 0; for(int i = 0; i < fuzz.length; i++) { for(int j = 0; j < fuzz.length; j++) { xp = x + fuzz[i]; yp = y + fuzz[j]; if(DrawObjectPeer.polygonContainsPoint(polyline,xp,yp)) { return true; } if(startArrow != null && DrawObjectPeer.polygonContainsPoint(startArrow,xp,yp)) { return true; } if(endArrow != null && DrawObjectPeer.polygonContainsPoint(endArrow,xp,yp)) { return true; } if(getTextLabelPeer() != null) { return getTextLabelPeer().inPeer(xp,yp); } } } return false; } /** * Gets the bounds of this peer in terms of the DrawPane coordinates. * * @return the bounding box of this object */ public Rectangle getBounds() { if(polyline == null) { setupPeer(true); //throw new IllegalStateException("cannot ask for bounds before Peer is built"); } return bbox; } /** * Setup this peer. * The setup does the actual co-ordinate mappings from what is available * in the DrawEdge object to the DrawPane co-ordinates. * * @param setupTextToo indicates if text peer should be setup as well */ public void setupPeer(boolean setupTextToo) { if(setupTextToo && getTextLabelPeer() != null) { getTextLabelPeer().setupPeer(); } polyline = getDrawPane().scalePoly(getDrawEdge().getEdgePolygon()); lineSize = (int)Math.round(polyline.npoints/2); bbox.setBounds(polyline.getBounds()); startArrow = null; endArrow = null; if(getDrawEdge().getStartArrow() != null) { startArrow = getDrawPane().scalePoly(getDrawEdge().getStartArrow()); bbox.add(startArrow.getBounds()); } if(getDrawEdge().getEndArrow() != null) { endArrow = getDrawPane().scalePoly(getDrawEdge().getEndArrow()); bbox.add(endArrow.getBounds()); } if(getTextLabelPeer() != null && getTextLabelPeer().getBounds() != null) { bbox.add(getTextLabelPeer().getBounds()); } } /** * Get the DrawEdge object associated with this peer * * @return the associated DrawEdge object */ public DrawEdge getDrawEdge() { return (DrawEdge)getDrawObject(); } /** * Draws the edge using the specified graphics information. * * @param gr the AWT graphic context to use for drawing * @param context the Grappa context to use for drawing */ public void draw(Graphics gr, GraphicContext context) { if(context == null) { context = getDrawObject().getGC(); } if(gr == null) gr = getDrawPane().getCanvasGraphics(); if(getDrawObject().getColorGC().getXORMode()) { gr.setXORMode(getDrawObject().getColorGC().getXORColor()); } else { gr.setPaintMode(); } gr.setColor(getDrawObject().getColorGC().getForeground()); if(getDrawEdge().getLineWidth() == 1) { if(getDrawEdge().getLineStyle() == Grappa.LINE_SOLID) { gr.drawPolyline(polyline.xpoints,polyline.ypoints,lineSize); } else if(getDrawEdge().getLineStyle() == Grappa.LINE_DOTTED) { for(int i = 0; i < lineSize; i++) { gr.drawLine(polyline.xpoints[i],polyline.ypoints[i],polyline.xpoints[i],polyline.ypoints[i]); } } else if(getDrawEdge().getLineStyle() == Grappa.LINE_DASHED) { for(int i = 0; i < (lineSize-1); i+=2) { gr.drawLine(polyline.xpoints[i],polyline.ypoints[i],polyline.xpoints[i+1],polyline.ypoints[i+1]); } } else { // solid gr.drawPolyline(polyline.xpoints,polyline.ypoints,lineSize); } } else { if(getDrawEdge().getLineStyle() == Grappa.LINE_SOLID) { gr.fillPolygon(polyline); } else if(getDrawEdge().getLineStyle() == Grappa.LINE_DOTTED) { int lineWidth = getDrawEdge().getLineWidth(); for(int i = 0; i < lineSize; i++) { gr.fillOval(polyline.xpoints[i],polyline.ypoints[i],lineWidth+1,lineWidth+1); } } else if(getDrawEdge().getLineStyle() == Grappa.LINE_DASHED) { int[] xpts = new int[4]; int[] ypts = new int[4]; for(int i = 0; i < (lineSize-1); i+=2) { xpts[0] = polyline.xpoints[i]; ypts[0] = polyline.ypoints[i]; xpts[1] = polyline.xpoints[i+1]; ypts[1] = polyline.ypoints[i+1]; xpts[2] = polyline.xpoints[polyline.npoints-2-i]; ypts[2] = polyline.ypoints[polyline.npoints-2-i]; xpts[3] = polyline.xpoints[polyline.npoints-1-i]; ypts[3] = polyline.ypoints[polyline.npoints-1-i]; gr.fillPolygon(xpts,ypts,4); } } else { // solid gr.fillPolygon(polyline); } } if(startArrow != null) { gr.fillPolygon(startArrow); } if(endArrow != null) { gr.fillPolygon(endArrow); } if(getTextLabelPeer() != null) { getTextLabelPeer().draw(gr,context); } } }