/* Violet - A program for editing UML diagrams. Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.horstmann.violet; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import com.horstmann.violet.framework.Direction; import com.horstmann.violet.framework.ShapeEdge; /** An S- or C-shaped edge with an arrowhead. */ public class ObjectReferenceEdge extends ShapeEdge { public void draw(Graphics2D g2) { g2.draw(getShape()); Line2D line = getConnectionPoints(); double x1; double x2 = line.getX2(); double y = line.getY2(); if (isSShaped()) x1 = x2 - ENDSIZE; else x1 = x2 + ENDSIZE; ArrowHead.BLACK_TRIANGLE.draw(g2, new Point2D.Double(x1, y), new Point2D.Double(x2, y)); } public Shape getShape() { Line2D line = getConnectionPoints(); double y1 = line.getY1(); double y2 = line.getY2(); double xmid = (line.getX1() + line.getX2()) / 2; double ymid = (line.getY1() + line.getY2()) / 2; GeneralPath p = new GeneralPath(); if (isSShaped()) { double x1 = line.getX1() + ENDSIZE; double x2 = line.getX2() - ENDSIZE; p.moveTo((float)line.getX1(), (float)y1); p.lineTo((float)x1, (float)y1); p.quadTo((float)((x1 + xmid) / 2), (float)y1, (float)xmid, (float)ymid); p.quadTo((float)((x2 + xmid) / 2), (float)y2, (float)x2, (float)y2); p.lineTo((float)line.getX2(), (float)y2); } else // reverse C shaped { double x1 = Math.max(line.getX1(), line.getX2()) + ENDSIZE; double x2 = x1 + ENDSIZE; p.moveTo((float)line.getX1(), (float)y1); p.lineTo((float)x1, (float)y1); p.quadTo((float)x2, (float)y1, (float)x2, (float)ymid); p.quadTo((float)x2, (float)y2, (float)x1, (float)y2); p.lineTo((float)line.getX2(), (float)y2); } return p; } public Line2D getConnectionPoints() { Rectangle2D b = getEnd().getBounds(); Point2D p = getStart().getConnectionPoint(Direction.EAST); if (isSShaped()) return new Line2D.Double(p, getEnd().getConnectionPoint(Direction.WEST)); else return new Line2D.Double(p, getEnd().getConnectionPoint(Direction.EAST)); } /** Tests whether the node should be S- or C-shaped. @return true if the node should be S-shaped */ private boolean isSShaped() { Rectangle2D b = getEnd().getBounds(); Point2D p = getStart().getConnectionPoint(Direction.EAST); return b.getX() >= p.getX() + 2 * ENDSIZE; } private static final int ENDSIZE = 10; }