/*
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.Dimension;
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 javax.swing.JLabel;
import com.horstmann.violet.framework.Direction;
import com.horstmann.violet.framework.ShapeEdge;
/**
A curved edge for a state transition in a state diagram.
*/
public class StateTransitionEdge extends ShapeEdge
{
/**
Sets the label property value.
@param newValue the new value
*/
public void setLabel(String newValue)
{
labelText = newValue;
}
/**
Gets the label property value.
@return the current value
*/
public String getLabel()
{
return labelText;
}
public void draw(Graphics2D g2)
{
g2.draw(getShape());
drawLabel(g2);
ArrowHead.V.draw(g2, getControlPoint(), getConnectionPoints().getP2());
}
/**
Draws the label.
@param g2 the graphics context
*/
private void drawLabel(Graphics2D g2)
{
Rectangle2D labelBounds = getLabelBounds(g2);
double x = labelBounds.getX();
double y = labelBounds.getY();
g2.translate(x, y);
label.paint(g2);
g2.translate(-x, -y);
}
/**
Gets the bounds of the label text
@param g2 the graphics context
@return the bounds of the label text
*/
private Rectangle2D getLabelBounds(Graphics2D g2)
{
Line2D line = getConnectionPoints();
Point2D control = getControlPoint();
double x = control.getX() / 2 + line.getX1() / 4 + line.getX2() / 4;
double y = control.getY() / 2 + line.getY1() / 4 + line.getY2() / 4;
label.setText("<html>" + labelText + "</html>");
label.setFont(g2.getFont());
Dimension d = label.getPreferredSize();
label.setBounds(0, 0, d.width, d.height);
final int GAP = 3;
if (line.getY1() == line.getY2())
x -= d.getWidth() / 2;
else if (line.getY1() <= line.getY2())
x += GAP;
else
x -= d.getWidth() + GAP;
if (line.getX1() == line.getX2())
y += d.getHeight() / 2;
else if (line.getX1() <= line.getX2())
y -= d.getHeight() + GAP;
else
y += GAP;
return new Rectangle2D.Double(x, y, d.width, d.height);
}
/**
Gets the control point for the quadratic spline.
@return the control point
*/
private Point2D getControlPoint()
{
Line2D line = getConnectionPoints();
double t = Math.tan(Math.toRadians(angle));
double dx = (line.getX2() - line.getX1()) / 2;
double dy = (line.getY2() - line.getY1()) / 2;
return new Point2D.Double(
(line.getX1() + line.getX2()) / 2 + t * dy,
(line.getY1() + line.getY2()) / 2 - t * dx);
}
public Shape getShape()
{
Line2D line = getConnectionPoints();
Point2D control = getControlPoint();
GeneralPath p = new GeneralPath();
p.moveTo((float)line.getX1(), (float)line.getY1());
p.quadTo((float)control.getX(), (float)control.getY(), (float)line.getX2(), (float)line.getY2());
return p;
}
public Rectangle2D getBounds(Graphics2D g2)
{
Rectangle2D r = super.getBounds(g2);
r.add(getLabelBounds(g2));
return r;
}
public Line2D getConnectionPoints()
{
Direction d1;
Direction d2;
if (getStart() == getEnd())
{
angle = 60;
d1 = Direction.EAST.turn(-30);
d2 = Direction.EAST.turn(30);
}
else
{
angle = 10;
Rectangle2D start = getStart().getBounds();
Rectangle2D end = getEnd().getBounds();
Point2D startCenter = new Point2D.Double(
start.getCenterX(),
start.getCenterY());
Point2D endCenter = new Point2D.Double(
end.getCenterX(),
end.getCenterY());
d1 = new Direction(startCenter, endCenter).turn(-5);
d2 = new Direction(endCenter, startCenter).turn(5);
}
Point2D p = getStart().getConnectionPoint(d1);
Point2D q = getEnd().getConnectionPoint(d2);
return new Line2D.Double(p, q);
}
private double angle;
private String labelText = "";
private static JLabel label = new JLabel();
}