blob: b701ba11be36ddde6d6bc2de2086bb6d09fb5f63 [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.editparts;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.AccessibleAnchorProvider;
import org.eclipse.gef.AccessibleEditPart;
import org.eclipse.gef.AccessibleHandleProvider;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeListener;
import org.eclipse.gef.Request;
/**
* Default implementation for {@link org.eclipse.gef.GraphicalEditPart}.
* <P>
* This is an implementation class, and the documentation here is targeted at
* subclassing this class. Callers of public API should refer to the interface's
* documentation.
*/
public abstract class AbstractGraphicalEditPart extends AbstractEditPart
implements GraphicalEditPart {
/**
* The Figure
*/
protected IFigure figure;
/**
* List of <i>source</i> ConnectionEditParts
*/
protected List sourceConnections;
/**
* List of <i>source</i> ConnectionEditParts
*/
protected List targetConnections;
/**
* A default implementation of {@link AccessibleEditPart}. Subclasses can
* extend this implementation to get base accessibility for free.
*
* @since 2.0
*/
protected abstract class AccessibleGraphicalEditPart extends
AccessibleEditPart {
/**
* @see AccessibleEditPart#getChildCount(AccessibleControlEvent)
*/
public void getChildCount(AccessibleControlEvent e) {
e.detail = AbstractGraphicalEditPart.this.getChildren().size();
}
/**
* @see AccessibleEditPart#getChildren(AccessibleControlEvent)
*/
public void getChildren(AccessibleControlEvent e) {
List list = AbstractGraphicalEditPart.this.getChildren();
Object children[] = new Object[list.size()];
for (int i = 0; i < list.size(); i++) {
EditPart part = (EditPart) list.get(i);
AccessibleEditPart access = (AccessibleEditPart) part
.getAdapter(AccessibleEditPart.class);
if (access == null)
return; // fail if any children aren't accessible.
children[i] = new Integer(access.getAccessibleID());
}
e.children = children;
}
/**
* @see AccessibleEditPart#getLocation(AccessibleControlEvent)
*/
public void getLocation(AccessibleControlEvent e) {
Rectangle bounds = getFigure().getBounds().getCopy();
getFigure().translateToAbsolute(bounds);
org.eclipse.swt.graphics.Point p = new org.eclipse.swt.graphics.Point(
0, 0);
p = getViewer().getControl().toDisplay(p);
e.x = bounds.x + p.x;
e.y = bounds.y + p.y;
e.width = bounds.width;
e.height = bounds.height;
}
/**
* @see AccessibleEditPart#getState(AccessibleControlEvent)
*/
public void getState(AccessibleControlEvent e) {
e.detail = ACC.STATE_SELECTABLE | ACC.STATE_FOCUSABLE;
if (getSelected() != EditPart.SELECTED_NONE)
e.detail |= ACC.STATE_SELECTED;
if (getViewer().getFocusEditPart() == AbstractGraphicalEditPart.this)
e.detail |= ACC.STATE_FOCUSED;
}
/**
* @see AccessibleEditPart#getRole(AccessibleControlEvent)
*/
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_LABEL;
}
}
/**
* The default implementation of {@link AccessibleAnchorProvider} returned
* in {@link #getAdapter(Class)}. This implementation creates an accessible
* location located along the right edge of the EditPart's Figure.
*
* @since 2.0
*/
protected class DefaultAccessibleAnchorProvider implements
AccessibleAnchorProvider {
private List getDefaultLocations() {
List list = new ArrayList();
Rectangle r = getFigure().getBounds();
Point p = r.getTopRight().translate(-1, r.height / 3);
getFigure().translateToAbsolute(p);
list.add(p);
return list;
}
/**
* @see AccessibleAnchorProvider#getSourceAnchorLocations()
*/
public List getSourceAnchorLocations() {
return getDefaultLocations();
}
/**
* @see AccessibleAnchorProvider#getTargetAnchorLocations()
*/
public List getTargetAnchorLocations() {
return getDefaultLocations();
}
}
static class MergedAccessibleHandles implements AccessibleHandleProvider {
List locations = new ArrayList();
MergedAccessibleHandles(EditPolicyIterator iter) {
while (iter.hasNext()) {
EditPolicy policy = iter.next();
if (!(policy instanceof IAdaptable))
continue;
IAdaptable adaptable = (IAdaptable) policy;
AccessibleHandleProvider adapter = (AccessibleHandleProvider) adaptable
.getAdapter(AccessibleHandleProvider.class);
if (adapter != null)
locations.addAll(adapter.getAccessibleHandleLocations());
}
}
public List getAccessibleHandleLocations() {
return locations;
}
}
/**
* Extends {@link AbstractEditPart#activate()} to also activate all
* <i>source</i> ConnectionEditParts.
*
* @see org.eclipse.gef.EditPart#activate()
*/
public void activate() {
super.activate();
List l = getSourceConnections();
for (int i = 0; i < l.size(); i++)
((EditPart) l.get(i)).activate();
}
/**
* Adds the child's Figure to the {@link #getContentPane() contentPane}.
*
* @see org.eclipse.gef.editparts.AbstractEditPart#addChildVisual(EditPart,
* int)
*/
protected void addChildVisual(EditPart childEditPart, int index) {
IFigure child = ((GraphicalEditPart) childEditPart).getFigure();
getContentPane().add(child, index);
}
/**
* @see org.eclipse.gef.GraphicalEditPart#addNodeListener(org.eclipse.gef.NodeListener)
*/
public void addNodeListener(NodeListener listener) {
eventListeners.addListener(NodeListener.class, listener);
}
/**
* @see org.eclipse.gef.EditPart#addNotify()
*/
public void addNotify() {
super.addNotify();
List conns;
conns = getSourceConnections();
for (int i = 0; i < conns.size(); i++)
((ConnectionEditPart) conns.get(i)).setSource(this);
conns = getTargetConnections();
for (int i = 0; i < conns.size(); i++)
((ConnectionEditPart) conns.get(i)).setTarget(this);
}
/**
* Adds a <i>source</i> ConnectionEditPart at the specified index. This
* method is called from {@link #refreshSourceConnections()}. There should
* be no reason to call or override this method. Source connection are
* created as a result of overriding {@link #getModelSourceConnections()}.
* <P>
* {@link #primAddSourceConnection(ConnectionEditPart, int)} is called to
* perform the actual update of the {@link #sourceConnections}
* <code>List</code>. The connection will have its source set to
* <code>this</code>.
* <P>
* If active, this EditPart will activate the ConnectionEditPart.
* <P>
* Finally, all {@link NodeListener}s are notified of the new connection.
*
* @param connection
* Connection being added
* @param index
* Index where it is being added
*/
protected void addSourceConnection(ConnectionEditPart connection, int index) {
primAddSourceConnection(connection, index);
GraphicalEditPart source = (GraphicalEditPart) connection.getSource();
if (source != null)
source.getSourceConnections().remove(connection);
connection.setSource(this);
if (isActive())
connection.activate();
fireSourceConnectionAdded(connection, index);
}
/**
* Adds a <i>target</i> ConnectionEditPart at the specified index. This
* method is called from {@link #refreshTargetConnections()}. There should
* be no reason to call or override this method. Target connection are
* created as a result of overriding {@link #getModelTargetConnections()}.
* <P>
* {@link #primAddTargetConnection(ConnectionEditPart, int)} is called to
* perform the actual update of the {@link #targetConnections}
* <code>List</code>. The connection will have its target set to
* <code>this</code>.
* <P>
* Finally, all {@link NodeListener}s are notified of the new connection.
*
* @param connection
* Connection being added
* @param index
* Index where it is being added
*/
protected void addTargetConnection(ConnectionEditPart connection, int index) {
primAddTargetConnection(connection, index);
GraphicalEditPart target = (GraphicalEditPart) connection.getTarget();
if (target != null)
target.getTargetConnections().remove(connection);
connection.setTarget(this);
fireTargetConnectionAdded(connection, index);
}
/**
* Creates a {@link ConnectionEditPart} for the given model. Similar to
* {@link AbstractEditPart#createChild(Object)}. This method is called
* indirectly during {@link #refreshSourceConnections()}, and
* {@link #refreshTargetConnections()}.
* <P>
* The default implementation goes to the EditPartViewer's
* {@link EditPartFactory} to create the connection. This method should not
* be overridden unless factories are not being used.
*
* @param model
* the connection model object
* @return the new ConnectionEditPart
*/
protected ConnectionEditPart createConnection(Object model) {
return (ConnectionEditPart) getViewer().getEditPartFactory()
.createEditPart(this, model);
}
/**
* Creates the <code>Figure</code> to be used as this part's <i>visuals</i>.
* This is called from {@link #getFigure()} if the figure has not been
* created.
*
* @return a Figure
*/
protected abstract IFigure createFigure();
/**
* Searches for an existing <code>ConnectionEditPart</code> in the Viewer's
* {@link EditPartViewer#getEditPartRegistry() EditPart registry} and
* returns it if one is found. Otherwise, {@link #createConnection(Object)}
* is called to create a new ConnectionEditPart. Override this method only
* if you need to find an existing connection some other way.
*
* @param model
* the Connection's model
* @return the ConnectionEditPart
*/
protected ConnectionEditPart createOrFindConnection(Object model) {
ConnectionEditPart conx = (ConnectionEditPart) getViewer()
.getEditPartRegistry().get(model);
if (conx != null)
return conx;
return createConnection(model);
}
/**
* Extends {@link AbstractEditPart#deactivate()} to also deactivate the
* source ConnectionEditParts. Subclasses should <em>extend</em> this method
* to remove any listeners added in {@link #activate}.
*
* @see org.eclipse.gef.EditPart#deactivate()
*/
public void deactivate() {
List l = getSourceConnections();
for (int i = 0; i < l.size(); i++)
((EditPart) l.get(i)).deactivate();
super.deactivate();
}
/**
* Notifies listeners that a source connection has been removed. Called from
* {@link #removeSourceConnection(ConnectionEditPart)}. There is no reason
* for subclasses to call or override this method.
*
* @param connection
* <code>ConnectionEditPart</code> being added as child.
* @param index
* Position child is being added into.
*/
protected void fireRemovingSourceConnection(ConnectionEditPart connection,
int index) {
if (eventListeners == null)
return;
Iterator listeners = eventListeners.getListeners(NodeListener.class);
NodeListener listener = null;
while (listeners.hasNext()) {
listener = (NodeListener) listeners.next();
listener.removingSourceConnection(connection, index);
}
}
/**
* Notifies listeners that a target connection has been removed. Called from
* {@link #removeTargetConnection(ConnectionEditPart)}. There is no reason
* for subclasses to call or override this method.
*
* @param connection
* <code>ConnectionEditPart</code> being added as child.
* @param index
* Position child is being added into.
*/
protected void fireRemovingTargetConnection(ConnectionEditPart connection,
int index) {
if (eventListeners == null)
return;
Iterator listeners = eventListeners.getListeners(NodeListener.class);
NodeListener listener = null;
while (listeners.hasNext()) {
listener = (NodeListener) listeners.next();
listener.removingTargetConnection(connection, index);
}
}
/**
* Notifies listeners that a source connection has been added. Called from
* {@link #addSourceConnection(ConnectionEditPart, int)}. There is no reason
* for subclasses to call or override this method.
*
* @param connection
* <code>ConnectionEditPart</code> being added as child.
* @param index
* Position child is being added into.
*/
protected void fireSourceConnectionAdded(ConnectionEditPart connection,
int index) {
if (eventListeners == null)
return;
Iterator listeners = eventListeners.getListeners(NodeListener.class);
NodeListener listener = null;
while (listeners.hasNext()) {
listener = (NodeListener) listeners.next();
listener.sourceConnectionAdded(connection, index);
}
}
/**
* Notifies listeners that a target connection has been added. Called from
* {@link #addTargetConnection(ConnectionEditPart, int)}. There is no reason
* for subclasses to call or override this method.
*
* @param connection
* <code>ConnectionEditPart</code> being added as child.
* @param index
* Position child is being added into.
*/
protected void fireTargetConnectionAdded(ConnectionEditPart connection,
int index) {
if (eventListeners == null)
return;
Iterator listeners = eventListeners.getListeners(NodeListener.class);
NodeListener listener = null;
while (listeners.hasNext()) {
listener = (NodeListener) listeners.next();
listener.targetConnectionAdded(connection, index);
}
}
/**
* Extends {@link AbstractEditPart#getAdapter(Class)} to handle additional
* adapter types. Currently, these types include
* {@link AccessibleHandleProvider} and {@link AccessibleAnchorProvider}.
* Subclasses should <em>extend</em> this method to support additional
* adapter types, or to replace the default provided adapaters.
*
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
*/
public Object getAdapter(Class key) {
if (key == AccessibleHandleProvider.class)
return new MergedAccessibleHandles(getEditPolicyIterator());
if (key == AccessibleAnchorProvider.class)
return new DefaultAccessibleAnchorProvider();
return super.getAdapter(key);
}
/**
* Implemented to delegate to {@link #getFigure()} by default. Subclasses
* may overwrite in case the {@link IFigure} returned by
* {@link #getFigure()} is a composite figure and child figures should be
* added to one of its children instead of the figure itself.
*
* @see GraphicalEditPart#getContentPane()
*/
public IFigure getContentPane() {
return getFigure();
}
/**
* Overridden to return a default <code>DragTracker</code> for
* GraphicalEditParts.
*
* @see org.eclipse.gef.EditPart#getDragTracker(Request)
*/
public DragTracker getDragTracker(Request request) {
return new org.eclipse.gef.tools.DragEditPartsTracker(this);
}
/**
* The default implementation calls {@link #createFigure()} if the figure is
* currently <code>null</code>.
*
* @see org.eclipse.gef.GraphicalEditPart#getFigure()
*/
public IFigure getFigure() {
if (figure == null)
setFigure(createFigure());
return figure;
}
/**
* A convenience method for obtaining the specified layer from the
* <code>LayerManager</code>.
*
* @param layer
* ID of the Layer
* @return The requested layer or <code>null</code> if it doesn't exist
*/
protected IFigure getLayer(Object layer) {
LayerManager manager = (LayerManager) getViewer().getEditPartRegistry()
.get(LayerManager.ID);
return manager.getLayer(layer);
}
/**
* Returns the <code>List</code> of the connection model objects for which
* this EditPart's model is the <b>source</b>.
* {@link #refreshSourceConnections()} calls this method. For each
* connection model object, {@link #createConnection(Object)} will be called
* automatically to obtain a corresponding {@link ConnectionEditPart}.
* <P>
* Callers must not modify the returned List.
*
* @return the List of model source connections
*/
protected List getModelSourceConnections() {
return Collections.EMPTY_LIST;
}
/**
* Returns the <code>List</code> of the connection model objects for which
* this EditPart's model is the <b>target</b>.
* {@link #refreshTargetConnections()} calls this method. For each
* connection model object, {@link #createConnection(Object)} will be called
* automatically to obtain a corresponding {@link ConnectionEditPart}.
* <P>
* Callers must not modify the returned List.
*
* @return the List of model target connections
*/
protected List getModelTargetConnections() {
return Collections.EMPTY_LIST;
}
/**
* @see org.eclipse.gef.GraphicalEditPart#getSourceConnections()
*/
public List getSourceConnections() {
if (sourceConnections == null)
return Collections.EMPTY_LIST;
return sourceConnections;
}
/**
* @see org.eclipse.gef.GraphicalEditPart#getTargetConnections()
*/
public List getTargetConnections() {
if (targetConnections == null)
return Collections.EMPTY_LIST;
return targetConnections;
}
/**
* A GraphicalEditPart is considered selectable, if it is active and its
* figure is showing.
*
* @see org.eclipse.gef.editparts.AbstractEditPart#isSelectable()
*/
public boolean isSelectable() {
return super.isSelectable() && getFigure() != null
&& getFigure().isShowing();
}
/**
* Adds the specified source <code>ConnectionEditPart</code> at an index.
* This method is used to update the {@link #sourceConnections} List. This
* method is called from
* {@link #addSourceConnection(ConnectionEditPart, int)}. Subclasses should
* not call or override this method.
*
* @param connection
* the ConnectionEditPart
* @param index
* the index of the add
*/
protected void primAddSourceConnection(ConnectionEditPart connection,
int index) {
if (sourceConnections == null)
sourceConnections = new ArrayList();
sourceConnections.add(index, connection);
}
/**
* Adds the specified target <code>ConnectionEditPart</code> at an index.
* This method is used to update the {@link #targetConnections} List. This
* method is called from
* {@link #addTargetConnection(ConnectionEditPart, int)}. Subclasses should
* not call or override this method.
*
* @param connection
* the ConnectionEditPart
* @param index
* the index of the add
*/
protected void primAddTargetConnection(ConnectionEditPart connection,
int index) {
if (targetConnections == null)
targetConnections = new ArrayList();
targetConnections.add(index, connection);
}
/**
* Removes the specified source <code>ConnectionEditPart</code> from the
* {@link #sourceConnections} List. This method is called from
* {@link #removeSourceConnection(ConnectionEditPart)}. Subclasses should
* not call or override this method.
*
* @param connection
* Connection to remove.
*/
protected void primRemoveSourceConnection(ConnectionEditPart connection) {
sourceConnections.remove(connection);
}
/**
* Removes the specified target <code>ConnectionEditPart</code> from the
* {@link #targetConnections} List. This method is called from
* {@link #removeTargetConnection(ConnectionEditPart)}. Subclasses should
* not call or override this method.
*
* @param connection
* Connection to remove.
*/
protected void primRemoveTargetConnection(ConnectionEditPart connection) {
targetConnections.remove(connection);
}
/**
* Extends {@link AbstractEditPart#refresh()} to refresh two additional
* structural features: <i>source</i> and <i>target</i> connections.
* Subclasses should probably override
* {@link AbstractEditPart#refreshVisuals()} instead of this method.
*
* @see org.eclipse.gef.EditPart#refresh()
*/
public void refresh() {
super.refresh();
refreshSourceConnections();
refreshTargetConnections();
}
/**
* Updates the set of <i>source</i> ConnectionEditParts so that it is in
* sync with the model source connections. This method is called from
* {@link #refresh()}, and may also be called in response to notification
* from the model.
* <P>
* The update is performed by comparing the existing source
* ConnectionEditParts with the set of model source connections returned
* from {@link #getModelSourceConnections()}. EditParts whose model no
* longer exists are {@link #removeSourceConnection(ConnectionEditPart)
* removed}. New models have their ConnectionEditParts
* {@link #createConnection(Object) created}. Subclasses should override
* <code>getModelSourceChildren()</code>.
* <P>
* This method should <em>not</em> be overridden.
*/
protected void refreshSourceConnections() {
int i;
ConnectionEditPart editPart;
Object model;
List sourceConnections = getSourceConnections();
int size = sourceConnections.size();
Map modelToEditPart = Collections.EMPTY_MAP;
if (size > 0) {
modelToEditPart = new HashMap(size);
for (i = 0; i < size; i++) {
editPart = (ConnectionEditPart) sourceConnections.get(i);
modelToEditPart.put(editPart.getModel(), editPart);
}
}
List modelObjects = getModelSourceConnections();
if (modelObjects == null) {
modelObjects = Collections.EMPTY_LIST;
}
for (i = 0; i < modelObjects.size(); i++) {
model = modelObjects.get(i);
if (i < sourceConnections.size()
&& ((EditPart) sourceConnections.get(i)).getModel() == model)
continue;
editPart = (ConnectionEditPart) modelToEditPart.get(model);
if (editPart != null)
reorderSourceConnection(editPart, i);
else {
editPart = createOrFindConnection(model);
addSourceConnection(editPart, i);
}
}
// Remove the remaining EditParts
size = sourceConnections.size();
if (i < size) {
List trash = new ArrayList(size - i);
for (; i < size; i++)
trash.add(sourceConnections.get(i));
for (i = 0; i < trash.size(); i++)
removeSourceConnection((ConnectionEditPart) trash.get(i));
}
}
/**
* Updates the set of <i>target</i> ConnectionEditParts so that it is in
* sync with the model target connections. This method is called from
* {@link #refresh()}, and may also be called in response to notification
* from the model.
* <P>
* The update is performed by comparing the existing source
* ConnectionEditParts with the set of model source connections returned
* from {@link #getModelTargetConnections()}. EditParts whose model no
* longer exists are {@link #removeTargetConnection(ConnectionEditPart)
* removed}. New models have their ConnectionEditParts
* {@link #createConnection(Object) created}. Subclasses should override
* <code>getModelTargetChildren()</code>.
* <P>
* This method should <em>not</em> be overridden.
*/
protected void refreshTargetConnections() {
int i;
ConnectionEditPart editPart;
Object model;
List targetConnections = getTargetConnections();
int size = targetConnections.size();
Map modelToEditPart = Collections.EMPTY_MAP;
if (size > 0) {
modelToEditPart = new HashMap(size);
for (i = 0; i < size; i++) {
editPart = (ConnectionEditPart) targetConnections.get(i);
modelToEditPart.put(editPart.getModel(), editPart);
}
}
List modelObjects = getModelTargetConnections();
if (modelObjects == null) {
modelObjects = Collections.EMPTY_LIST;
}
for (i = 0; i < modelObjects.size(); i++) {
model = modelObjects.get(i);
if (i < targetConnections.size()
&& ((EditPart) targetConnections.get(i)).getModel() == model)
continue;
editPart = (ConnectionEditPart) modelToEditPart.get(model);
if (editPart != null)
reorderTargetConnection(editPart, i);
else {
editPart = createOrFindConnection(model);
addTargetConnection(editPart, i);
}
}
// Remove the remaining EditParts
size = targetConnections.size();
if (i < size) {
List trash = new ArrayList(size - i);
for (; i < size; i++)
trash.add(targetConnections.get(i));
for (i = 0; i < trash.size(); i++)
removeTargetConnection((ConnectionEditPart) trash.get(i));
}
}
/**
* Registers the EditPart's Figure in the Viewer. This is what makes it
* possible for the Viewer to map a mouse location to an EditPart.
*
* @see org.eclipse.gef.editparts.AbstractEditPart#registerVisuals()
*/
protected void registerVisuals() {
getViewer().getVisualPartMap().put(getFigure(), this);
}
/**
* Remove the child's Figure from the {@link #getContentPane() contentPane}.
*
* @see AbstractEditPart#removeChildVisual(EditPart)
*/
protected void removeChildVisual(EditPart childEditPart) {
IFigure child = ((GraphicalEditPart) childEditPart).getFigure();
getContentPane().remove(child);
}
/**
* @see org.eclipse.gef.GraphicalEditPart#removeNodeListener(org.eclipse.gef.NodeListener)
*/
public void removeNodeListener(NodeListener listener) {
eventListeners.removeListener(NodeListener.class, listener);
}
/**
* Extends {@link AbstractEditPart#removeNotify()} to cleanup
* <code>ConnectionEditParts</code>.
*
* @see EditPart#removeNotify()
*/
public void removeNotify() {
List conns;
ConnectionEditPart cep;
conns = getSourceConnections();
for (int i = 0; i < conns.size(); i++) {
cep = (ConnectionEditPart) conns.get(i);
if (cep.getSource() == this)
cep.setSource(null);
}
conns = getTargetConnections();
for (int i = 0; i < conns.size(); i++) {
cep = (ConnectionEditPart) conns.get(i);
if (cep.getTarget() == this)
cep.setTarget(null);
}
super.removeNotify();
}
/**
* Removes the given connection for which this EditPart is the
* <B>source</b>. <BR>
* Fires notification. <BR>
* Inverse of {@link #addSourceConnection(ConnectionEditPart, int)}
*
* @param connection
* Connection being removed
*/
protected void removeSourceConnection(ConnectionEditPart connection) {
fireRemovingSourceConnection(connection, getSourceConnections()
.indexOf(connection));
if (connection.getSource() == this) {
connection.deactivate();
connection.setSource(null);
}
primRemoveSourceConnection(connection);
}
/**
* Removes the given connection for which this EditPart is the
* <B>target</b>. <BR>
* Fires notification. <BR>
* Inverse of {@link #addTargetConnection(ConnectionEditPart, int)}
*
* @param connection
* Connection being removed
*/
protected void removeTargetConnection(ConnectionEditPart connection) {
fireRemovingTargetConnection(connection, getTargetConnections()
.indexOf(connection));
if (connection.getTarget() == this)
connection.setTarget(null);
primRemoveTargetConnection(connection);
}
/**
* This method is extended to preserve a LayoutManager constraint if one
* exists.
*
* @see org.eclipse.gef.editparts.AbstractEditPart#reorderChild(EditPart,
* int)
*/
protected void reorderChild(EditPart child, int index) {
// Save the constraint of the child so that it does not
// get lost during the remove and re-add.
IFigure childFigure = ((GraphicalEditPart) child).getFigure();
LayoutManager layout = getContentPane().getLayoutManager();
Object constraint = null;
if (layout != null)
constraint = layout.getConstraint(childFigure);
super.reorderChild(child, index);
setLayoutConstraint(child, childFigure, constraint);
}
/**
* Moves a source <code>ConnectionEditPart</code> into a lower index than it
* currently occupies. This method is called from
* {@link #refreshSourceConnections()}.
*
* @param connection
* the ConnectionEditPart
* @param index
* the new index
*/
protected void reorderSourceConnection(ConnectionEditPart connection,
int index) {
primRemoveSourceConnection(connection);
primAddSourceConnection(connection, index);
}
/**
* Moves a target <code>ConnectionEditPart</code> into a lower index than it
* currently occupies. This method is called from
* {@link #refreshTargetConnections()}.
*
* @param connection
* the ConnectionEditPart
* @param index
* the new index
*/
protected void reorderTargetConnection(ConnectionEditPart connection,
int index) {
primRemoveTargetConnection(connection);
primAddTargetConnection(connection, index);
}
/**
* Sets the Figure
*
* @param figure
* the Figure
*/
protected void setFigure(IFigure figure) {
this.figure = figure;
}
/**
* @see GraphicalEditPart#setLayoutConstraint(EditPart, IFigure, Object)
*/
public void setLayoutConstraint(EditPart child, IFigure childFigure,
Object constraint) {
childFigure.getParent().setConstraint(childFigure, constraint);
}
/**
* Implemented to remove the Figure from the Viewer's registry.
*
* @see AbstractEditPart#unregisterVisuals()
*/
protected void unregisterVisuals() {
getViewer().getVisualPartMap().remove(getFigure());
}
}