/*******************************************************************************
* Copyright (c) 2000, 2008 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);
}
/**
* If the children's Figures should be
* @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;
}
/**
* 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 exising 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;
Map modelToEditPart = new HashMap();
List editParts = getSourceConnections();
for (i = 0; i < editParts.size(); i++) {
editPart = (ConnectionEditPart)editParts.get(i);
modelToEditPart.put(editPart.getModel(), editPart);
}
List modelObjects = getModelSourceConnections();
if (modelObjects == null) modelObjects = new ArrayList();
for (i = 0; i < modelObjects.size(); i++) {
model = modelObjects.get(i);
if (i < editParts.size()
&& ((EditPart) editParts.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
List trash = new ArrayList ();
for (; i < editParts.size(); i++)
trash.add(editParts.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 exising 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;
Map mapModelToEditPart = new HashMap();
List connections = getTargetConnections();
for (i = 0; i < connections.size(); i++) {
editPart = (ConnectionEditPart)connections.get(i);
mapModelToEditPart.put(editPart.getModel(), editPart);
}
List modelObjects = getModelTargetConnections();
if (modelObjects == null) modelObjects = new ArrayList();
for (i = 0; i < modelObjects.size(); i++) {
model = modelObjects.get(i);
if (i < connections.size()
&& ((EditPart) connections.get(i)).getModel() == model)
continue;
editPart = (ConnectionEditPart)mapModelToEditPart.get(model);
if (editPart != null)
reorderTargetConnection(editPart, i);
else {
editPart = createOrFindConnection(model);
addTargetConnection(editPart, i);
}
}
//Remove the remaining Connection EditParts
List trash = new ArrayList ();
for (; i < connections.size(); i++)
trash.add(connections.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());
}
}