| /******************************************************************************* |
| * 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.editparts; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.draw2d.ChopboxAnchor; |
| import org.eclipse.draw2d.Connection; |
| import org.eclipse.draw2d.ConnectionAnchor; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.PolylineConnection; |
| import org.eclipse.draw2d.XYAnchor; |
| import org.eclipse.draw2d.geometry.Point; |
| |
| import org.eclipse.gef.AccessibleAnchorProvider; |
| import org.eclipse.gef.ConnectionEditPart; |
| import org.eclipse.gef.DragTracker; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.LayerConstants; |
| import org.eclipse.gef.NodeEditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.tools.SelectEditPartTracker; |
| |
| /** |
| * The base implementation for {@link org.eclipse.gef.ConnectionEditPart}. |
| */ |
| public abstract class AbstractConnectionEditPart extends |
| AbstractGraphicalEditPart implements ConnectionEditPart, LayerConstants { |
| |
| private static final ConnectionAnchor DEFAULT_SOURCE_ANCHOR = new XYAnchor( |
| new Point(10, 10)); |
| private static final ConnectionAnchor DEFAULT_TARGET_ANCHOR = new XYAnchor( |
| new Point(100, 100)); |
| |
| /** |
| * Provides accessibility support for when connections are also themselves |
| * nodes. If a connection is the source or target of another connection, |
| * then its midpoint is used as the accessible anchor location. |
| * |
| * @author hudsonr |
| * @since 2.0 |
| */ |
| protected final class DefaultAccessibleAnchorProvider implements |
| AccessibleAnchorProvider { |
| /** |
| * This class is internal, but is made protected so that JavaDoc will |
| * see it. |
| */ |
| DefaultAccessibleAnchorProvider() { |
| } |
| |
| /** |
| * @see AccessibleAnchorProvider#getSourceAnchorLocations() |
| */ |
| public List getSourceAnchorLocations() { |
| List list = new ArrayList(); |
| if (getFigure() instanceof Connection) { |
| Point p = ((Connection) getFigure()).getPoints().getMidpoint(); |
| getFigure().translateToAbsolute(p); |
| list.add(p); |
| } |
| return list; |
| } |
| |
| /** |
| * @see AccessibleAnchorProvider#getTargetAnchorLocations() |
| */ |
| public List getTargetAnchorLocations() { |
| return getSourceAnchorLocations(); |
| } |
| } |
| |
| private EditPart sourceEditPart, targetEditPart; |
| |
| /** |
| * Activates the Figure representing this, by setting up the start and end |
| * connections, and adding the figure to the Connection Layer. |
| * |
| * @see #deactivate() |
| */ |
| protected void activateFigure() { |
| getLayer(CONNECTION_LAYER).add(getFigure()); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#addNotify() |
| */ |
| public void addNotify() { |
| activateFigure(); |
| super.addNotify(); |
| } |
| |
| /** |
| * Returns a newly created Figure to represent these type of EditParts. |
| * |
| * @return The created Figure. |
| */ |
| protected IFigure createFigure() { |
| return new PolylineConnection(); |
| } |
| |
| /** |
| * Deactivates the Figure representing this, by removing it from the |
| * connection layer, and resetting the source and target connections to |
| * <code>null</code>. |
| */ |
| protected void deactivateFigure() { |
| getLayer(CONNECTION_LAYER).remove(getFigure()); |
| getConnectionFigure().setSourceAnchor(null); |
| getConnectionFigure().setTargetAnchor(null); |
| } |
| |
| /** |
| * <code>AbstractConnectionEditPart</code> extends getAdapter() to overrides |
| * the {@link AccessibleAnchorProvider} adapter returned by the superclass. |
| * When treating a connection as a node for other connections, it makes |
| * sense to target its midpoint, and not the edge of its bounds. |
| * |
| * @see AbstractConnectionEditPart.DefaultAccessibleAnchorProvider |
| * @see AbstractGraphicalEditPart#getAdapter(Class) |
| * @param adapter |
| * the adapter Class |
| * @return the adapter |
| */ |
| public Object getAdapter(Class adapter) { |
| if (adapter == AccessibleAnchorProvider.class) |
| return new DefaultAccessibleAnchorProvider(); |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * Convenience method for casting this GraphicalEditPart's Figure to a |
| * {@link Connection} |
| * |
| * @return the Figure as a Connection |
| */ |
| public Connection getConnectionFigure() { |
| return (Connection) getFigure(); |
| } |
| |
| /** |
| * @see org.eclipse.gef.EditPart#getDragTracker(Request) |
| */ |
| public DragTracker getDragTracker(Request req) { |
| return new SelectEditPartTracker(this); |
| } |
| |
| /** |
| * @see org.eclipse.gef.ConnectionEditPart#getSource() |
| */ |
| public EditPart getSource() { |
| return sourceEditPart; |
| } |
| |
| /** |
| * @see org.eclipse.gef.ConnectionEditPart#getTarget() |
| */ |
| public EditPart getTarget() { |
| return targetEditPart; |
| } |
| |
| /** |
| * Returns the <code>ConnectionAnchor</code> for the <i>source</i> end of |
| * the connection. If the source is an instance of {@link NodeEditPart}, |
| * that interface will be used to determine the proper ConnectionAnchor. If |
| * the source is not an instance of <code>NodeEditPart</code>, this method |
| * should be overridden to return the correct ConnectionAnchor. Failure to |
| * do this will cause a default anchor to be used so that the connection |
| * figure will be made visible to the developer. |
| * |
| * @return ConnectionAnchor for the source end of the Connection |
| */ |
| protected ConnectionAnchor getSourceConnectionAnchor() { |
| if (getSource() != null) { |
| if (getSource() instanceof NodeEditPart) { |
| NodeEditPart editPart = (NodeEditPart) getSource(); |
| return editPart.getSourceConnectionAnchor(this); |
| } |
| IFigure f = ((GraphicalEditPart) getSource()).getFigure(); |
| return new ChopboxAnchor(f); |
| } |
| return DEFAULT_SOURCE_ANCHOR; |
| } |
| |
| /** |
| * Returns the <code>ConnectionAnchor</code> for the <i>target</i> end of |
| * the connection. If the target is an instance of {@link NodeEditPart}, |
| * that interface will be used to determine the proper ConnectionAnchor. If |
| * the target is not an instance of <code>NodeEditPart</code>, this method |
| * should be overridden to return the correct ConnectionAnchor. Failure to |
| * do this will cause a default anchor to be used so that the connection |
| * figure will be made visible to the developer. |
| * |
| * @return ConnectionAnchor for the target end of the Connection |
| */ |
| protected ConnectionAnchor getTargetConnectionAnchor() { |
| if (getTarget() != null) { |
| if (getTarget() instanceof NodeEditPart) { |
| NodeEditPart editPart = (NodeEditPart) getTarget(); |
| return editPart.getTargetConnectionAnchor(this); |
| } |
| IFigure f = ((GraphicalEditPart) getTarget()).getFigure(); |
| return new ChopboxAnchor(f); |
| } |
| return DEFAULT_TARGET_ANCHOR; |
| } |
| |
| /** |
| * Extended here to also refresh the ConnectionAnchors. |
| * |
| * @see org.eclipse.gef.EditPart#refresh() |
| */ |
| public void refresh() { |
| refreshSourceAnchor(); |
| refreshTargetAnchor(); |
| super.refresh(); |
| } |
| |
| /** |
| * Updates the source ConnectionAnchor. Subclasses should override |
| * {@link #getSourceConnectionAnchor()} if necessary, and not this method. |
| */ |
| protected void refreshSourceAnchor() { |
| getConnectionFigure().setSourceAnchor(getSourceConnectionAnchor()); |
| } |
| |
| /** |
| * Updates the target ConnectionAnchor. Subclasses should override |
| * {@link #getTargetConnectionAnchor()} if necessary, and not this method. |
| */ |
| protected void refreshTargetAnchor() { |
| getConnectionFigure().setTargetAnchor(getTargetConnectionAnchor()); |
| } |
| |
| /** |
| * Extended here to remove the ConnectionEditPart's connection figure from |
| * the connection layer. |
| * |
| * @see org.eclipse.gef.EditPart#removeNotify() |
| */ |
| public void removeNotify() { |
| deactivateFigure(); |
| super.removeNotify(); |
| } |
| |
| /** |
| * Extended to implement automatic addNotify and removeNotify handling. |
| * |
| * @see org.eclipse.gef.EditPart#setParent(EditPart) |
| */ |
| public void setParent(EditPart parent) { |
| boolean wasNull = getParent() == null; |
| boolean becomingNull = parent == null; |
| if (becomingNull && !wasNull) |
| removeNotify(); |
| super.setParent(parent); |
| if (wasNull && !becomingNull) |
| addNotify(); |
| } |
| |
| /** |
| * Sets the source EditPart of this connection. |
| * |
| * @param editPart |
| * EditPart which is the source. |
| */ |
| public void setSource(EditPart editPart) { |
| if (sourceEditPart == editPart) |
| return; |
| sourceEditPart = editPart; |
| if (sourceEditPart != null) |
| setParent(sourceEditPart.getRoot()); |
| else if (getTarget() == null) |
| setParent(null); |
| if (sourceEditPart != null && targetEditPart != null) |
| refresh(); |
| } |
| |
| /** |
| * Sets the target EditPart of this connection. |
| * |
| * @param editPart |
| * EditPart which is the target. |
| */ |
| public void setTarget(EditPart editPart) { |
| if (targetEditPart == editPart) |
| return; |
| targetEditPart = editPart; |
| if (editPart != null) |
| setParent(editPart.getRoot()); |
| else if (getSource() == null) |
| setParent(null); |
| if (sourceEditPart != null && targetEditPart != null) |
| refresh(); |
| } |
| |
| } |