blob: cce8ce53d9e0b962d80e8a2de59f229e98710503 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.gef.editpolicies;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.AncestorListener;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.ConnectionLocator;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Polygon;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.ConnectionEndpointHandle;
import org.eclipse.gef.requests.ReconnectRequest;
/**
* A selection handle policy for placing handles at the two ends of a
* ConnectionEditPart. All ConnectionEditParts should have one of these, even if
* the ends of the connection aren't draggable, because this is the primary
* SelectionEditPolicy for showing focus.
* <P>
* A connection can receive focus but not selection by pressing
* <code>Control+/</code> on the keyboard.
*
* @since 2.0
*/
public class ConnectionEndpointEditPolicy extends SelectionHandlesEditPolicy {
private ConnectionAnchor originalAnchor;
private FeedbackHelper feedbackHelper;
private ConnectionFocus focus;
class ConnectionFocus extends Polygon implements PropertyChangeListener {
AncestorListener ancestorListener = new AncestorListener.Stub() {
public void ancestorMoved(IFigure ancestor) {
revalidate();
}
};
ConnectionFocus() {
setFill(false);
setForegroundColor(ColorConstants.white());
setXOR(true);
setOutline(true);
}
public void addNotify() {
super.addNotify();
getConnection().addPropertyChangeListener(
Connection.PROPERTY_POINTS, this);
getConnection().addAncestorListener(ancestorListener);
}
protected void outlineShape(Graphics g) {
g.setLineDash(new int[] { 1, 1 });
super.outlineShape(g);
}
public void propertyChange(PropertyChangeEvent evt) {
revalidate();
}
public void removeNotify() {
getConnection().removePropertyChangeListener(
Connection.PROPERTY_POINTS, this);
getConnection().removeAncestorListener(ancestorListener);
super.removeNotify();
}
public void validate() {
if (isValid())
return;
PointList points = getConnection().getPoints().getCopy();
getConnection().translateToAbsolute(points);
points = StrokePointList.strokeList(points, 5);
translateToRelative(points);
setPoints(points);
}
}
/**
* @see org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy#createSelectionHandles()
*/
protected List createSelectionHandles() {
List list = new ArrayList();
list.add(new ConnectionEndpointHandle((ConnectionEditPart) getHost(),
ConnectionLocator.SOURCE));
list.add(new ConnectionEndpointHandle((ConnectionEditPart) getHost(),
ConnectionLocator.TARGET));
return list;
}
/**
* Erases connection move feedback. This method is called when a
* ReconnectRequest is received.
*
* @param request
* the reconnect request.
*/
protected void eraseConnectionMoveFeedback(ReconnectRequest request) {
if (originalAnchor == null)
return;
if (request.isMovingStartAnchor())
getConnection().setSourceAnchor(originalAnchor);
else
getConnection().setTargetAnchor(originalAnchor);
originalAnchor = null;
feedbackHelper = null;
}
/**
* @see org.eclipse.gef.EditPolicy#eraseSourceFeedback(org.eclipse.gef.Request)
*/
public void eraseSourceFeedback(Request request) {
if (REQ_RECONNECT_TARGET.equals(request.getType())
|| REQ_RECONNECT_SOURCE.equals(request.getType()))
eraseConnectionMoveFeedback((ReconnectRequest) request);
}
/**
* @see org.eclipse.gef.EditPolicy#getCommand(org.eclipse.gef.Request)
*/
public Command getCommand(Request request) {
return null;
}
/**
* Convenience method for obtaining the host's <code>Connection</code>
* figure.
*
* @return the Connection figure
*/
protected Connection getConnection() {
return (Connection) ((GraphicalEditPart) getHost()).getFigure();
}
/**
* Lazily creates and returns the feedback helper for the given request. The
* helper will be configured as either moving the source or target end of
* the connection.
*
* @param request
* the reconnect request
* @return the feedback helper
*/
protected FeedbackHelper getFeedbackHelper(ReconnectRequest request) {
if (feedbackHelper == null) {
feedbackHelper = new FeedbackHelper();
feedbackHelper.setConnection(getConnection());
feedbackHelper.setMovingStartAnchor(request.isMovingStartAnchor());
}
return feedbackHelper;
}
/**
* Hides the focus indicator. The focus indicator is a dotted outline around
* the connection.
*
* @see #showFocus()
* @see org.eclipse.gef.editpolicies.SelectionEditPolicy#hideFocus()
*/
protected void hideFocus() {
if (focus != null) {
removeFeedback(focus);
focus = null;
}
}
/**
* Shows or updates connection move feedback. Called whenever a show
* feedback request is received for reconnection.
*
* @param request
* the reconnect request
*/
protected void showConnectionMoveFeedback(ReconnectRequest request) {
NodeEditPart node = null;
if (request.getTarget() instanceof NodeEditPart)
node = (NodeEditPart) request.getTarget();
if (originalAnchor == null) {
if (request.isMovingStartAnchor())
originalAnchor = getConnection().getSourceAnchor();
else
originalAnchor = getConnection().getTargetAnchor();
}
ConnectionAnchor anchor = null;
if (node != null) {
if (request.isMovingStartAnchor())
anchor = node.getSourceConnectionAnchor(request);
else
anchor = node.getTargetConnectionAnchor(request);
}
FeedbackHelper helper = getFeedbackHelper(request);
helper.update(anchor, request.getLocation());
}
/**
* Shows focus around the connection.
*
* @see org.eclipse.gef.editpolicies.SelectionEditPolicy#showFocus()
*/
protected void showFocus() {
if (focus == null) {
focus = new ConnectionFocus();
addFeedback(focus);
}
}
/**
* @see org.eclipse.gef.EditPolicy#showSourceFeedback(org.eclipse.gef.Request)
*/
public void showSourceFeedback(Request request) {
if (REQ_RECONNECT_SOURCE.equals(request.getType())
|| REQ_RECONNECT_TARGET.equals(request.getType()))
showConnectionMoveFeedback((ReconnectRequest) request);
}
}