1: import java.awt.Graphics2D; 2: import java.awt.geom.Point2D; 3: import java.awt.geom.Rectangle2D; 4: import java.awt.geom.RectangularShape; 5: import java.io.IOException; 6: import java.io.ObjectInputStream; 7: import java.io.ObjectOutputStream; 9: /** 10: A node that has a rectangular shape. 11: */ 12: public abstract class RectangularNode implements Node 13: { 14: public Object clone() 15: { 16: try 17: { 18: RectangularNode cloned = (RectangularNode) super.clone(); 19: cloned.bounds = (Rectangle2D) bounds.clone(); 20: return cloned; 21: } 22: catch (CloneNotSupportedException exception) 23: { 24: return null; 25: } 26: } 28: public void translate(double dx, double dy) 29: { 30: bounds.setFrame(bounds.getX() + dx, 31: bounds.getY() + dy, 32: bounds.getWidth(), 33: bounds.getHeight()); 34: } 36: public boolean contains(Point2D p) 37: { 38: return bounds.contains(p); 39: } 41: public Rectangle2D getBounds() 42: { 43: return (Rectangle2D) bounds.clone(); 44: } 46: public void setBounds(Rectangle2D newBounds) 47: { 48: bounds = newBounds; 49: } 51: public Point2D getConnectionPoint(Point2D aPoint) 52: { 53: double slope = bounds.getHeight() / bounds.getWidth(); 54: double x = bounds.getCenterX(); 55: double y = bounds.getCenterY(); 56: double ex = aPoint.getX() - x; 57: double ey = aPoint.getY() - y; 58: 59: if (ex != 0 && -slope <= ey / ex && ey / ex <= slope) 60: { 61: // intersects at left or right boundary 62: if (ex > 0) 63: { 64: x = bounds.getMaxX(); 65: y += (bounds.getWidth() / 2) * ey / ex; 66: } 67: else 68: { 69: x = bounds.getX(); 70: y -= (bounds.getWidth() / 2) * ey / ex; 71: } 72: } 73: else if (ey != 0) 74: { 75: // intersects at top or bottom 76: if (ey > 0) 77: { 78: x += (bounds.getHeight() / 2) * ex / ey; 79: y = bounds.getMaxY(); 80: } 81: else 82: { 83: x -= (bounds.getHeight() / 2) * ex / ey; 84: y = bounds.getY(); 85: } 86: } 87: return new Point2D.Double(x, y); 88: } 90: private void writeObject(ObjectOutputStream out) 91: throws IOException 92: { 93: out.defaultWriteObject(); 94: writeRectangularShape(out, bounds); 95: } 97: /** 98: A helper method to overcome the problem that the 2D shapes 99: aren't serializable. It writes x, y, width and height 100: to the stream. 101: @param out the stream 102: @param s the shape 103: */ 104: private static void writeRectangularShape( 105: ObjectOutputStream out, 106: RectangularShape s) 107: throws IOException 108: { 109: out.writeDouble(s.getX()); 110: out.writeDouble(s.getY()); 111: out.writeDouble(s.getWidth()); 112: out.writeDouble(s.getHeight()); 113: } 115: private void readObject(ObjectInputStream in) 116: throws IOException, ClassNotFoundException 117: { 118: in.defaultReadObject(); 119: bounds = new Rectangle2D.Double(); 120: readRectangularShape(in, bounds); 121: } 122: 123: /** 124: A helper method to overcome the problem that the 2D shapes 125: aren't serializable. It reads x, y, width and height 126: from the stream. 127: @param in the stream 128: @param s the shape whose frame is set from the stream values 129: */ 130: private static void readRectangularShape(ObjectInputStream in, 131: RectangularShape s) 132: throws IOException 133: { 134: double x = in.readDouble(); 135: double y = in.readDouble(); 136: double width = in.readDouble(); 137: double height = in.readDouble(); 138: s.setFrame(x, y, width, height); 139: } 141: private transient Rectangle2D bounds; 142: }