ConnectionHandle.java
/*
* @(#)ConnectionHandle.java
*
* Project: JHotdraw - a GUI framework for technical drawings
* http://www.jhotdraw.org
* http://jhotdraw.sourceforge.net
* Copyright: © by the original author(s) and all contributors
* License: Lesser GNU Public License (LGPL)
* http://www.opensource.org/licenses/lgpl-license.html
*/
package CH.ifa.draw.standard;
import java.awt.*;
import CH.ifa.draw.framework.*;
import CH.ifa.draw.util.Geom;
/**
* A handle to connect figures.
* The connection object to be created is specified by a prototype.
* <hr>
* <b>Design Patterns</b><P>
* <img src="images/red-ball-small.gif" width=6 height=6 alt=" o ">
* <b><a href=../pattlets/sld029.htm>Prototype</a></b><br>
* ConnectionHandle creates the connection by cloning a prototype.
* <hr>
*
* @see ConnectionFigure
* @see Object#clone
*
* @version <$CURRENT_VERSION$>
*/
public class ConnectionHandle extends LocatorHandle {
/**
* the currently created connection
*/
private ConnectionFigure myConnection;
/**
* the prototype of the connection to be created
*/
private ConnectionFigure fPrototype;
/**
* the current target
*/
private Figure fTarget = null;
/**
* Constructs a handle with the given owner, locator, and connection prototype
*/
public ConnectionHandle(Figure owner, Locator l, ConnectionFigure prototype) {
super(owner, l);
fPrototype = prototype;
}
/**
* Creates the connection
*/
public void invokeStart(int x, int y, DrawingView view) {
setConnection(createConnection());
Point p = locate();
getConnection().startPoint(p.x, p.y);
getConnection().endPoint(p.x, p.y);
view.drawing().add(getConnection());
}
/**
* Tracks the connection.
*/
public void invokeStep (int x, int y, int anchorX, int anchorY, DrawingView view) {
Point p = new Point(x,y);
Figure f = findConnectableFigure(x, y, view.drawing());
// track the figure containing the mouse
if (f != fTarget) {
if (fTarget != null) {
fTarget.connectorVisibility(false);
}
fTarget = f;
if (fTarget != null) {
fTarget.connectorVisibility(true);
}
}
Connector target = findConnectionTarget(p.x, p.y, view.drawing());
if (target != null) {
p = Geom.center(target.displayBox());
}
getConnection().endPoint(p.x, p.y);
}
/**
* Connects the figures if the mouse is released over another
* figure.
*/
public void invokeEnd(int x, int y, int anchorX, int anchorY, DrawingView view) {
Connector target = findConnectionTarget(x, y, view.drawing());
if (target != null) {
getConnection().connectStart(startConnector());
getConnection().connectEnd(target);
getConnection().updateConnection();
}
else {
view.drawing().remove(getConnection());
}
setConnection(null);
if (fTarget != null) {
fTarget.connectorVisibility(false);
fTarget = null;
}
}
private Connector startConnector() {
Point p = locate();
return owner().connectorAt(p.x, p.y);
}
/**
* Creates the ConnectionFigure. By default the figure prototype is
* cloned.
*/
protected ConnectionFigure createConnection() {
return (ConnectionFigure)fPrototype.clone();
}
/**
* Finds a connection end figure.
*/
protected Connector findConnectionTarget(int x, int y, Drawing drawing) {
Figure target = findConnectableFigure(x, y, drawing);
if ((target != null) && target.canConnect()
&& !target.includes(owner())
&& getConnection().canConnect(owner(), target)) {
return findConnector(x, y, target);
}
return null;
}
private Figure findConnectableFigure(int x, int y, Drawing drawing) {
FigureEnumeration k = drawing.figuresReverse();
while (k.hasMoreElements()) {
Figure figure = k.nextFigure();
if (!figure.includes(getConnection()) && figure.canConnect()
&& figure.containsPoint(x, y)) {
return figure;
}
}
return null;
}
protected Connector findConnector(int x, int y, Figure f) {
return f.connectorAt(x, y);
}
/**
* Draws the connection handle, by default the outline of a
* blue circle.
*/
public void draw(Graphics g) {
Rectangle r = displayBox();
g.setColor(Color.blue);
g.drawOval(r.x, r.y, r.width, r.height);
}
protected void setConnection(ConnectionFigure newConnection) {
myConnection = newConnection;
}
protected ConnectionFigure getConnection() {
return myConnection;
}
}