/* * @(#)ConnectionTool.java 5.1 * */ package CH.ifa.draw.standard; import java.awt.*; import java.awt.event.MouseEvent; import java.util.*; import CH.ifa.draw.framework.*; import CH.ifa.draw.util.Geom; /** * A tool that can be used to connect figures, to split * connections, and to join two segments of a connection. * ConnectionTools turns the visibility of the Connectors * on when it enters a figure. * The connection object to be created is specified by a prototype. *
* Design Patterns

*  o * Prototype
* ConnectionTools creates the connection by cloning a prototype. *


* * @see ConnectionFigure * @see Object#clone */ public class ConnectionTool extends AbstractTool { /** * the anchor point of the interaction */ private Connector fStartConnector; private Connector fEndConnector; private Connector fConnectorTarget = null; private Figure fTarget = null; /** * the currently created figure */ private ConnectionFigure fConnection; /** * the currently manipulated connection point */ private int fSplitPoint; /** * the currently edited connection */ private ConnectionFigure fEditedConnection = null; /** * the prototypical figure that is used to create new * connections. */ private ConnectionFigure fPrototype; public ConnectionTool(DrawingView view, ConnectionFigure prototype) { super(view); fPrototype = prototype; } /** * Handles mouse move events in the drawing view. */ public void mouseMove(MouseEvent e, int x, int y) { trackConnectors(e, x, y); } /** * Manipulates connections in a context dependent way. If the * mouse down hits a figure start a new connection. If the mousedown * hits a connection split a segment or join two segments. */ public void mouseDown(MouseEvent e, int x, int y) { int ex = e.getX(); int ey = e.getY(); fTarget = findConnectionStart(ex, ey, drawing()); if (fTarget != null) { fStartConnector = findConnector(ex, ey, fTarget); if (fStartConnector != null) { Point p = new Point(ex, ey); fConnection = createConnection(); fConnection.startPoint(p.x, p.y); fConnection.endPoint(p.x, p.y); view().add(fConnection); } } else { ConnectionFigure connection = findConnection(ex, ey, drawing()); if (connection != null) { if (!connection.joinSegments(ex, ey)) { fSplitPoint = connection.splitSegment(ex, ey); fEditedConnection = connection; } else { fEditedConnection = null; } } } } /** * Adjust the created connection or split segment. */ public void mouseDrag(MouseEvent e, int x, int y) { Point p = new Point(e.getX(), e.getY()); if (fConnection != null) { trackConnectors(e, x, y); if (fConnectorTarget != null) p = Geom.center(fConnectorTarget.displayBox()); fConnection.endPoint(p.x, p.y); } else if (fEditedConnection != null) { Point pp = new Point(x, y); fEditedConnection.setPointAt(pp, fSplitPoint); } } /** * Connects the figures if the mouse is released over another * figure. */ public void mouseUp(MouseEvent e, int x, int y) { Figure c = null; if (fStartConnector != null) c = findTarget(e.getX(), e.getY(), drawing()); if (c != null) { fEndConnector = findConnector(e.getX(), e.getY(), c); if (fEndConnector != null) { fConnection.connectStart(fStartConnector); fConnection.connectEnd(fEndConnector); fConnection.updateConnection(); } } else if (fConnection != null) view().remove(fConnection); fConnection = null; fStartConnector = fEndConnector = null; editor().toolDone(); } public void deactivate() { super.deactivate(); if (fTarget != null) fTarget.connectorVisibility(false); } /** * Creates the ConnectionFigure. By default the figure prototype is * cloned. */ protected ConnectionFigure createConnection() { return (ConnectionFigure)fPrototype.clone(); } /** * Finds a connectable figure target. */ protected Figure findSource(int x, int y, Drawing drawing) { return findConnectableFigure(x, y, drawing); } /** * Finds a connectable figure target. */ protected Figure findTarget(int x, int y, Drawing drawing) { Figure target = findConnectableFigure(x, y, drawing); Figure start = fStartConnector.owner(); if (target != null && fConnection != null && target.canConnect() && !target.includes(start) && fConnection.canConnect(start, target)) return target; return null; } /** * Finds an existing connection figure. */ protected ConnectionFigure findConnection(int x, int y, Drawing drawing) { Enumeration k = drawing.figuresReverse(); while (k.hasMoreElements()) { Figure figure = (Figure) k.nextElement(); figure = figure.findFigureInside(x, y); if (figure != null && (figure instanceof ConnectionFigure)) return (ConnectionFigure)figure; } return null; } /** * Gets the currently created figure */ protected ConnectionFigure createdFigure() { return fConnection; } protected void trackConnectors(MouseEvent e, int x, int y) { Figure c = null; if (fStartConnector == null) c = findSource(x, y, drawing()); else c = findTarget(x, y, drawing()); // track the figure containing the mouse if (c != fTarget) { if (fTarget != null) fTarget.connectorVisibility(false); fTarget = c; if (fTarget != null) fTarget.connectorVisibility(true); } Connector cc = null; if (c != null) cc = findConnector(e.getX(), e.getY(), c); if (cc != fConnectorTarget) fConnectorTarget = cc; view().checkDamage(); } private Connector findConnector(int x, int y, Figure f) { return f.connectorAt(x, y); } /** * Finds a connection start figure. */ protected Figure findConnectionStart(int x, int y, Drawing drawing) { Figure target = findConnectableFigure(x, y, drawing); if ((target != null) && target.canConnect()) return 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(fConnection) && figure.canConnect()) { if (figure.containsPoint(x, y)) return figure; } } return null; } protected Connector getStartConnector() { return fStartConnector; } protected Connector getEndConnector() { return fEndConnector; } protected Connector getTarget() { return fConnectorTarget; } }