| /****************************************************************************** |
| * Copyright (c) 2002, 2009 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.gmf.runtime.diagram.ui.editpolicies; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.draw2d.Connection; |
| import org.eclipse.draw2d.ConnectionAnchor; |
| import org.eclipse.draw2d.ConnectionLayer; |
| import org.eclipse.draw2d.ConnectionRouter; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.PolylineConnection; |
| import org.eclipse.draw2d.geometry.PointList; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.LayerConstants; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.requests.CreateConnectionRequest; |
| import org.eclipse.gef.requests.CreateRequest; |
| import org.eclipse.gef.requests.ReconnectRequest; |
| import org.eclipse.gmf.runtime.common.core.command.CommandResult; |
| import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; |
| import org.eclipse.gmf.runtime.common.core.command.ICommand; |
| import org.eclipse.gmf.runtime.common.core.util.StringStatics; |
| import org.eclipse.gmf.runtime.diagram.core.commands.SetConnectionAnchorsCommand; |
| import org.eclipse.gmf.runtime.diagram.core.commands.SetConnectionEndsCommand; |
| import org.eclipse.gmf.runtime.diagram.core.commands.SetPropertyCommand; |
| import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter; |
| import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.CreateOrSelectElementCommand; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; |
| import org.eclipse.gmf.runtime.diagram.ui.commands.SemanticCreateCommand; |
| import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; |
| import org.eclipse.gmf.runtime.diagram.ui.editparts.INodeEditPart; |
| import org.eclipse.gmf.runtime.diagram.ui.editparts.ITreeBranchEditPart; |
| import org.eclipse.gmf.runtime.diagram.ui.internal.commands.SetConnectionBendpointsCommand; |
| import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties; |
| import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; |
| import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.ChangePropertyValueRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeConnectionRequest; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequestFactory; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper; |
| import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants; |
| import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx; |
| import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; |
| import org.eclipse.gmf.runtime.emf.core.util.PackageUtil; |
| import org.eclipse.gmf.runtime.emf.type.core.IElementType; |
| import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest; |
| import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.ModelingAssistantService; |
| import org.eclipse.gmf.runtime.notation.Diagram; |
| import org.eclipse.gmf.runtime.notation.NotationPackage; |
| import org.eclipse.gmf.runtime.notation.Routing; |
| import org.eclipse.gmf.runtime.notation.RoutingStyle; |
| import org.eclipse.gmf.runtime.notation.View; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.swt.widgets.Display; |
| |
| /* |
| * @canBeSeenBy %partners |
| */ |
| /** |
| * the graphical node edit policy |
| * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy |
| * |
| * @author mmostafa, cmahoney |
| */ |
| public class GraphicalNodeEditPolicy |
| extends |
| org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy { |
| /** describes the view to be created. */ |
| private IAdaptable _viewAdapter; |
| |
| /** |
| * The label used for the command to create a new connection. |
| */ |
| private static final String CREATE_CONNECTION_COMMAND_LABEL = DiagramUIMessages.GraphicalNodeEditPolicy_createRelationshipCommand_label; |
| |
| /** |
| * Gets a command that pops up a menu which allows the user to select which |
| * type of connection to be created and then creates the connection. This |
| * command uses |
| * {@link #getCommandForMenuSelection(Object, CreateConnectionRequest)} on |
| * the connection chosen to get the creation command. |
| * |
| * @author cmahoney |
| */ |
| protected class PromptAndCreateConnectionCommand |
| extends CreateOrSelectElementCommand { |
| |
| /** |
| * Cache the request because it needs to be passed to |
| * {@link #getCommandForMenuSelection(Object, CreateConnectionRequest)}. |
| */ |
| private CreateConnectionRequest request; |
| |
| /** |
| * Creates a new instance. |
| * |
| * @param content |
| * The list of items making up the content of the popup menu. |
| * @param request |
| * The relevant create connection request. |
| */ |
| public PromptAndCreateConnectionCommand(List content, |
| CreateConnectionRequest request) { |
| super(CREATE_CONNECTION_COMMAND_LABEL, Display.getCurrent() |
| .getActiveShell(), content); |
| this.request = request; |
| } |
| |
| /** |
| * The command to create the connection that may need to be |
| * undone/redone. |
| */ |
| private Command createCommand; |
| |
| /** |
| * Pops up the dialog with the content provided, gets the command to be |
| * executed based on the user selection, and then executes the command. |
| */ |
| protected CommandResult doExecuteWithResult( |
| IProgressMonitor progressMonitor, IAdaptable info) |
| throws ExecutionException { |
| |
| CommandResult cmdResult = super.doExecuteWithResult(progressMonitor, info); |
| if (!cmdResult.getStatus().isOK()) { |
| return cmdResult; |
| } |
| |
| Object connectionType = cmdResult.getReturnValue(); |
| |
| Command cmd = getConnectionCompleteCommand(connectionType, getRequest()); |
| Assert.isTrue(cmd != null && cmd.canExecute()); |
| cmd.execute(); |
| createCommand = cmd; |
| |
| if (connectionType instanceof IElementType) { |
| CreateRequest createRequest = ((CreateUnspecifiedTypeConnectionRequest) request) |
| .getRequestForType((IElementType) connectionType); |
| Object newObject = createRequest.getNewObject(); |
| |
| return CommandResult.newOKCommandResult(newObject); |
| } |
| return CommandResult.newOKCommandResult(); |
| } |
| |
| protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { |
| if (createCommand != null) { |
| createCommand.undo(); |
| } |
| return super.doUndoWithResult(progressMonitor, info); |
| } |
| |
| protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { |
| if (createCommand != null) { |
| createCommand.redo(); |
| } |
| return super.doRedoWithResult(progressMonitor, info); |
| } |
| |
| /** |
| * Gets the request. |
| * |
| * @return Returns the request. |
| */ |
| private CreateConnectionRequest getRequest() { |
| return request; |
| } |
| |
| } |
| |
| protected Connection createDummyConnection(Request req) { |
| PolylineConnection c = (PolylineConnection) super.createDummyConnection(req); |
| c.setLineStyle(Graphics.LINE_DASHDOT); |
| c.setForegroundColor(((GraphicalEditPart) getHost()).getFigure() |
| .getForegroundColor()); |
| return c; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getDummyConnectionRouter(org.eclipse.gef.requests.CreateConnectionRequest) |
| */ |
| protected ConnectionRouter getDummyConnectionRouter(CreateConnectionRequest arg0) { |
| EditPart ep = getHost(); |
| if (ep instanceof IGraphicalEditPart) { |
| IGraphicalEditPart gep = ((IGraphicalEditPart)ep); |
| Routing routingVal = Routing.MANUAL_LITERAL; |
| if (gep.getNotationView() != null) { |
| Diagram dgrm = gep.getNotationView().getDiagram(); |
| EditPart epfromReg = (EditPart)gep.getViewer().getEditPartRegistry().get(dgrm); |
| if (epfromReg != null) |
| routingVal = (Routing)epfromReg.getAdapter(Routing.class); |
| } |
| else { |
| IPreferenceStore store = (IPreferenceStore) ((IGraphicalEditPart)ep).getDiagramPreferencesHint().getPreferenceStore(); |
| routingVal = Routing.get(store.getInt(IPreferenceConstants.PREF_LINE_STYLE)); |
| } |
| |
| ConnectionLayer cLayer = (ConnectionLayer) getLayer(LayerConstants.CONNECTION_LAYER); |
| if (cLayer instanceof ConnectionLayerEx) { |
| ConnectionLayerEx cLayerEx = (ConnectionLayerEx)cLayer; |
| if (routingVal == Routing.MANUAL_LITERAL) { |
| return cLayerEx.getObliqueRouter(); |
| } |
| else if (routingVal == Routing.RECTILINEAR_LITERAL) { |
| return cLayerEx.getRectilinearRouter(); |
| } |
| else if (routingVal == Routing.TREE_LITERAL) { |
| return cLayerEx.getTreeRouter(); |
| } |
| } |
| } |
| |
| return super.getDummyConnectionRouter(arg0); |
| } |
| |
| |
| |
| protected ConnectionAnchor getSourceConnectionAnchor( |
| CreateConnectionRequest request) { |
| EditPart source = request.getSourceEditPart(); |
| return source instanceof INodeEditPart ? ((INodeEditPart) source) |
| .getSourceConnectionAnchor(request) : null; |
| } |
| |
| protected ConnectionAnchor getTargetConnectionAnchor( |
| CreateConnectionRequest request) { |
| EditPart target = request.getTargetEditPart(); |
| return target instanceof INodeEditPart ? ((INodeEditPart) target) |
| .getTargetConnectionAnchor(request) : null; |
| } |
| |
| /** |
| * get a connectable edit part |
| * @return INodeEditPart |
| */ |
| protected INodeEditPart getConnectableEditPart() { |
| return (INodeEditPart) getHost(); |
| } |
| /** |
| * getConnectionCompleteEditPart |
| * |
| * This method is used when the connection is verified and made complete to |
| * retrieve the final connecting editpart to be used in the connection |
| * creation. This is by default the "host" edit part which is what is |
| * connected to by the user feedback. Subclassing edit-policies may wish to |
| * redirect the connection to a different edit-part depending on the |
| * gesture. i.e. the tree-view for generalizations will redirect the |
| * connection to the target of the host. |
| * |
| * @param request |
| * Request giving some information about the user gesture. |
| * @return INodeEditPart which will be the target connection. |
| */ |
| protected INodeEditPart getConnectionCompleteEditPart(Request request) { |
| if (getHost() instanceof INodeEditPart) { |
| return (INodeEditPart) getHost(); |
| } |
| return null; |
| } |
| /** |
| * getConnectionTargetAnchor Method used during reconnection to retrieve |
| * the appropriate target anchor based on a request. |
| * |
| * @param request |
| * Request giving some information about the user gesture. |
| * @return ConnectionAnchor the connections target end will connect to. |
| */ |
| protected ConnectionAnchor getConnectionTargetAnchor(Request request) { |
| INodeEditPart node = getConnectableEditPart(); |
| if (node != null) |
| return node.getTargetConnectionAnchor(request); |
| |
| return null; |
| } |
| /** |
| * get this edit policy's edit part <code>View</code> |
| * @return View |
| */ |
| protected View getView() { |
| return (View)getHost().getModel(); |
| } |
| /** |
| * getSemanticHint Retrieves the semanticHint from the request regarding |
| * the type of elemen being manipulated. |
| * |
| * @param request |
| * Request that is sent from the user gesture |
| * @return String that is the semantic type. |
| */ |
| protected String getSemanticHint(Request request) { |
| String hint = null; |
| if (request instanceof CreateConnectionViewAndElementRequest) { |
| CreateConnectionViewAndElementRequest ccvr = (CreateConnectionViewAndElementRequest) request; |
| // get the element descriptor |
| CreateElementRequestAdapter requestAdapter = ccvr |
| .getConnectionViewAndElementDescriptor() |
| .getCreateElementRequestAdapter(); |
| // get the semantic request |
| CreateRelationshipRequest createElementRequest = (CreateRelationshipRequest) requestAdapter |
| .getAdapter(CreateRelationshipRequest.class); |
| hint = PackageUtil.getID(createElementRequest.getElementType().getEClass()); |
| } else if (request instanceof ReconnectRequest) { |
| ReconnectRequest rr = (ReconnectRequest) request; |
| hint = ViewUtil.getSemanticElementClassId((View)rr.getConnectionEditPart().getModel()); |
| } else if (request instanceof CreateConnectionViewRequest) { |
| CreateConnectionViewRequest ccvr = (CreateConnectionViewRequest) request; |
| hint = ccvr.getConnectionViewDescriptor().getSemanticHint(); |
| } |
| return hint; |
| } |
| /** |
| * getRoutingAdjustment method to adjust routing if the reorient has moved |
| * the connection into a different routing environment. Specifically, if |
| * the connection has been reoriented out of a tree structure it will |
| * change routing to the default set in preference. Likewise, if the |
| * connection has connected to a tree structure then the routing will |
| * create a tree. |
| * |
| * @param connection |
| * IAdaptable that is placeholder for not yet created connection. |
| * Also adapts directly to a ConnectionEditPart in the case of a |
| * reorient. |
| * @param connectionHint |
| * String that is the semantic hint of the connection being |
| * manipulated |
| * @param currentRouterType |
| * Integer current representation of the routing style |
| * @param target |
| * EditPart that is being targeted by the request. |
| * @return Command to make any routing adjustments if necessary. |
| */ |
| protected Command getRoutingAdjustment(IAdaptable connection, |
| String connectionHint, Routing currentRouterType, EditPart target) { |
| Command cmd = null; |
| if (connectionHint == null || |
| target == null || target.getModel() == null |
| || ((View)target.getModel()).getElement() == null) |
| return null; |
| // check if router needs to change type due to reorient. |
| String targetHint = ViewUtil.getSemanticElementClassId((View) target.getModel()); |
| Routing newRouterType = null; |
| if (target instanceof ITreeBranchEditPart |
| && connectionHint.equals(targetHint)) { |
| newRouterType = Routing.TREE_LITERAL; |
| ChangePropertyValueRequest cpvr = new ChangePropertyValueRequest( |
| StringStatics.BLANK, Properties.ID_ROUTING, newRouterType); |
| Command cmdRouter = target.getCommand(cpvr); |
| if (cmdRouter != null) |
| cmd = cmd == null ? cmdRouter : cmd.chain(cmdRouter); |
| } else { |
| if (currentRouterType.equals(Routing.TREE_LITERAL)) { |
| IPreferenceStore store = (IPreferenceStore) |
| ((IGraphicalEditPart) getHost()) |
| .getDiagramPreferencesHint().getPreferenceStore(); |
| newRouterType = Routing.get(store.getInt(IPreferenceConstants.PREF_LINE_STYLE)); |
| } |
| } |
| if (newRouterType != null) { |
| // add commands for line routing. Convert the new connection and |
| // also the targeted connection. |
| ICommand spc = new SetPropertyCommand( |
| getEditingDomain(), connection, |
| Properties.ID_ROUTING, StringStatics.BLANK, newRouterType); |
| Command cmdRouter = new ICommandProxy(spc); |
| if (cmdRouter != null) { |
| cmd = cmd == null ? cmdRouter : cmd.chain(cmdRouter); |
| } |
| } |
| return cmd; |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getReconnectTargetCommand(org.eclipse.gef.requests.ReconnectRequest) |
| */ |
| protected Command getReconnectTargetCommand(ReconnectRequest request) { |
| INodeEditPart node = getConnectableEditPart(); |
| if (node == null) |
| return null; |
| |
| TransactionalEditingDomain editingDomain = getEditingDomain(); |
| |
| ConnectionAnchor targetAnchor = getConnectionTargetAnchor(request); |
| INodeEditPart targetEP = getConnectionCompleteEditPart(request); |
| if (targetEP == null) { |
| return null; |
| } |
| SetConnectionEndsCommand sceCommand = new SetConnectionEndsCommand(editingDomain, StringStatics.BLANK); |
| sceCommand.setEdgeAdaptor(new EObjectAdapter((EObject)request |
| .getConnectionEditPart().getModel())); |
| sceCommand.setNewTargetAdaptor(targetEP); |
| SetConnectionAnchorsCommand scaCommand = new SetConnectionAnchorsCommand(editingDomain, StringStatics.BLANK); |
| scaCommand.setEdgeAdaptor(new EObjectAdapter((EObject) request |
| .getConnectionEditPart().getModel())); |
| scaCommand.setNewTargetTerminal(targetEP |
| .mapConnectionAnchorToTerminal(targetAnchor)); |
| CompositeCommand cc = new CompositeCommand( |
| DiagramUIMessages.Commands_SetConnectionEndsCommand_Target); |
| cc.compose(sceCommand); |
| cc.compose(scaCommand); |
| Command cmd = new ICommandProxy(cc); |
| EditPart cep = request.getConnectionEditPart(); |
| RoutingStyle style = (RoutingStyle) ((View)cep.getModel()).getStyle(NotationPackage.eINSTANCE.getRoutingStyle()); |
| Routing currentRouter = Routing.MANUAL_LITERAL; |
| if (style != null) { |
| currentRouter = style.getRouting(); |
| } |
| Command cmdRouter = getRoutingAdjustment(request |
| .getConnectionEditPart(), getSemanticHint(request), |
| currentRouter, request.getTarget()); |
| if (cmdRouter != null) { |
| cmd = cmd == null ? cmdRouter : cmd.chain(cmdRouter); |
| // reset the bendpoints |
| ConnectionAnchor sourceAnchor = node |
| .getSourceConnectionAnchor(request); |
| PointList pointList = new PointList(); |
| pointList.addPoint(sourceAnchor.getLocation(targetAnchor |
| .getReferencePoint())); |
| pointList.addPoint(targetAnchor.getLocation(sourceAnchor |
| .getReferencePoint())); |
| |
| SetConnectionBendpointsCommand sbbCommand = new SetConnectionBendpointsCommand(editingDomain); |
| sbbCommand.setEdgeAdapter(request.getConnectionEditPart()); |
| sbbCommand.setNewPointList(pointList, sourceAnchor |
| .getReferencePoint(), targetAnchor.getReferencePoint()); |
| Command cmdBP = new ICommandProxy(sbbCommand); |
| if (cmdBP != null) { |
| cmd = cmd == null ? cmdBP : cmd.chain(cmdBP); |
| } |
| } |
| return cmd; |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getReconnectSourceCommand(org.eclipse.gef.requests.ReconnectRequest) |
| */ |
| protected Command getReconnectSourceCommand(ReconnectRequest request) { |
| INodeEditPart node = getConnectableEditPart(); |
| if (node == null) |
| return null; |
| |
| TransactionalEditingDomain editingDomain = getEditingDomain(); |
| |
| ConnectionAnchor sourceAnchor = node.getSourceConnectionAnchor(request); |
| SetConnectionEndsCommand sceCommand = new SetConnectionEndsCommand(editingDomain, StringStatics.BLANK); |
| sceCommand.setEdgeAdaptor(new EObjectAdapter((View) request |
| .getConnectionEditPart().getModel())); |
| sceCommand.setNewSourceAdaptor(new EObjectAdapter((View)node |
| .getModel())); |
| SetConnectionAnchorsCommand scaCommand = new SetConnectionAnchorsCommand(editingDomain, StringStatics.BLANK); |
| scaCommand.setEdgeAdaptor(new EObjectAdapter((View) request |
| .getConnectionEditPart().getModel())); |
| scaCommand.setNewSourceTerminal(node.mapConnectionAnchorToTerminal(sourceAnchor)); |
| CompositeCommand cc = new CompositeCommand( |
| DiagramUIMessages.Commands_SetConnectionEndsCommand_Source); |
| cc.compose(sceCommand); |
| cc.compose(scaCommand); |
| return new ICommandProxy(cc); |
| } |
| /** |
| * Returns a command that will create the connection. |
| * |
| * If you must override this method, you should call super. |
| * |
| * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getConnectionCompleteCommand(org.eclipse.gef.requests.CreateConnectionRequest) |
| * |
| */ |
| protected Command getConnectionCompleteCommand( |
| CreateConnectionRequest request) { |
| ICommandProxy proxy = (ICommandProxy) request |
| .getStartCommand(); |
| if (proxy == null) { |
| return null; |
| } |
| |
| // reset the target edit-part for the request |
| INodeEditPart targetEP = getConnectionCompleteEditPart(request); |
| if (targetEP == null) { |
| return null; |
| } |
| |
| CompositeCommand cc = (CompositeCommand) proxy.getICommand(); |
| ConnectionAnchor targetAnchor = targetEP |
| .getTargetConnectionAnchor(request); |
| Iterator commandItr = cc.iterator(); |
| commandItr.next(); //0 |
| SetConnectionEndsCommand sceCommand = (SetConnectionEndsCommand) commandItr.next(); //1 |
| sceCommand.setNewTargetAdaptor(new EObjectAdapter(((IGraphicalEditPart) targetEP).getNotationView())); |
| SetConnectionAnchorsCommand scaCommand = (SetConnectionAnchorsCommand) commandItr.next(); //2 |
| scaCommand.setNewTargetTerminal(targetEP |
| .mapConnectionAnchorToTerminal(targetAnchor)); |
| setViewAdapter(sceCommand.getEdgeAdaptor()); |
| INodeEditPart sourceEditPart = (INodeEditPart) request |
| .getSourceEditPart(); |
| ConnectionAnchor sourceAnchor = sourceEditPart |
| .mapTerminalToConnectionAnchor(scaCommand.getNewSourceTerminal()); |
| PointList pointList = new PointList(); |
| if (request.getLocation() == null) { |
| pointList.addPoint(sourceAnchor.getLocation(targetAnchor.getReferencePoint())); |
| pointList.addPoint(targetAnchor.getLocation(sourceAnchor.getReferencePoint())); |
| } |
| else { |
| pointList.addPoint(sourceAnchor.getLocation(request.getLocation())); |
| pointList.addPoint(targetAnchor.getLocation(request.getLocation())); |
| } |
| SetConnectionBendpointsCommand sbbCommand = (SetConnectionBendpointsCommand) commandItr.next(); //3 |
| sbbCommand.setNewPointList(pointList, sourceAnchor.getReferencePoint(), |
| targetAnchor.getReferencePoint()); |
| return request.getStartCommand(); |
| } |
| |
| /** |
| * Cache the view descriptor describing the connection to be create. |
| * |
| * @param viewAdapter |
| */ |
| protected final void setViewAdapter(IAdaptable viewAdapter) { |
| _viewAdapter = viewAdapter; |
| } |
| |
| /** |
| * Return the view adapter describing the element to be created. |
| * @see #setViewAdapter(IAdaptable) |
| * @return adpater that can adapt <code>View.class</code> |
| */ |
| protected final IAdaptable getViewAdapter() { |
| return _viewAdapter; |
| } |
| protected Command getConnectionCreateCommand(CreateConnectionRequest request) { |
| if (!(request instanceof CreateConnectionViewRequest)) |
| return null; |
| CreateConnectionViewRequest req = (CreateConnectionViewRequest) request; |
| CompositeCommand cc = new CompositeCommand( |
| DiagramUIMessages.Commands_CreateCommand_Connection_Label); |
| Diagram diagramView = ((View)getHost().getModel()) |
| .getDiagram(); |
| TransactionalEditingDomain editingDomain = getEditingDomain(); |
| CreateCommand createCommand = new CreateCommand(editingDomain, req |
| .getConnectionViewDescriptor(), diagramView.getDiagram()); |
| setViewAdapter((IAdaptable) createCommand.getCommandResult() |
| .getReturnValue()); |
| |
| |
| SetConnectionEndsCommand sceCommand = new SetConnectionEndsCommand(editingDomain, StringStatics.BLANK); |
| sceCommand.setEdgeAdaptor(getViewAdapter()); |
| sceCommand.setNewSourceAdaptor(new EObjectAdapter(getView())); |
| ConnectionAnchor sourceAnchor = getConnectableEditPart() |
| .getSourceConnectionAnchor(request); |
| SetConnectionAnchorsCommand scaCommand = new SetConnectionAnchorsCommand(editingDomain, StringStatics.BLANK); |
| scaCommand.setEdgeAdaptor(getViewAdapter()); |
| scaCommand.setNewSourceTerminal(getConnectableEditPart() |
| .mapConnectionAnchorToTerminal(sourceAnchor)); |
| SetConnectionBendpointsCommand sbbCommand = new SetConnectionBendpointsCommand(editingDomain); |
| sbbCommand.setEdgeAdapter(getViewAdapter()); |
| cc.compose(createCommand); |
| cc.compose(sceCommand); |
| cc.compose(scaCommand); |
| cc.compose(sbbCommand); |
| Command c = new ICommandProxy(cc); |
| request.setStartCommand(c); |
| return c; |
| } |
| |
| public Command getCommand(Request request) { |
| if (RequestConstants.REQ_CONNECTION_START.equals(request.getType())) { |
| if (request instanceof CreateConnectionViewAndElementRequest) { |
| return getConnectionAndRelationshipCreateCommand((CreateConnectionViewAndElementRequest) request); |
| } else if (request instanceof CreateUnspecifiedTypeConnectionRequest) { |
| return getUnspecifiedConnectionCreateCommand((CreateUnspecifiedTypeConnectionRequest) request); |
| } |
| } else if (RequestConstants.REQ_CONNECTION_END |
| .equals(request.getType())) { |
| if (request instanceof CreateConnectionViewAndElementRequest) { |
| return getConnectionAndRelationshipCompleteCommand((CreateConnectionViewAndElementRequest) request); |
| } else if (request instanceof CreateUnspecifiedTypeConnectionRequest) { |
| return getUnspecifiedConnectionCompleteCommand((CreateUnspecifiedTypeConnectionRequest) request); |
| } |
| } |
| return super.getCommand(request); |
| } |
| |
| /** |
| * Gets the command to start the creation of a new connection and |
| * relationship. This will update the request appropriately. |
| * |
| * @param request |
| * @return Command |
| */ |
| protected Command getConnectionAndRelationshipCreateCommand( |
| CreateConnectionViewAndElementRequest request) { |
| // get the element descriptor |
| CreateElementRequestAdapter requestAdapter = request |
| .getConnectionViewAndElementDescriptor().getCreateElementRequestAdapter(); |
| // get the semantic request |
| CreateRelationshipRequest createElementRequest = (CreateRelationshipRequest) requestAdapter |
| .getAdapter(CreateRelationshipRequest.class); |
| // complete the semantic request by filling in the source |
| View sourceView = (View)getHost().getModel(); |
| createElementRequest.setSource(ViewUtil.resolveSemanticElement(sourceView)); |
| // get the create element request based on the elementdescriptor's |
| // request |
| Command createElementCommand = getHost().getCommand( |
| new EditCommandRequestWrapper( |
| (CreateRelationshipRequest) requestAdapter |
| .getAdapter(CreateRelationshipRequest.class), request.getExtendedData())); |
| // if element cannot be created, ignore |
| if (createElementCommand == null || !createElementCommand.canExecute()){ |
| // Even if the command is not executable, status information may be set. |
| return createElementCommand; |
| } |
| |
| return getConnectionCreateCommand(request); |
| } |
| |
| /** |
| * Gets the command to start the creation of a new connection and |
| * relationship (if applicable) for a unspecified type request. This will |
| * update all the individual requests appropriately. |
| * |
| * @param request |
| * the unspecified type request |
| * @return the command |
| */ |
| private Command getUnspecifiedConnectionCreateCommand( |
| final CreateUnspecifiedTypeConnectionRequest request) { |
| |
| if (request.isDirectionReversed()) { |
| return new Command() { |
| |
| /** |
| * All we know is the target and the possible relationship |
| * types. At this point, there is no way to validate the |
| * commands for this scenario. |
| */ |
| public boolean canExecute() { |
| return true; |
| } |
| }; |
| } else { |
| |
| // Get the start command for each individual request, this will |
| // update each request as required. |
| final List commands = new ArrayList(); |
| for (Iterator iter = request.getAllRequests().iterator(); iter |
| .hasNext();) { |
| Request individualRequest = (Request) iter.next(); |
| Command cmd = null; |
| if (individualRequest instanceof CreateConnectionViewAndElementRequest) { |
| cmd = getConnectionAndRelationshipCreateCommand((CreateConnectionViewAndElementRequest) individualRequest); |
| } else if (individualRequest instanceof CreateConnectionViewRequest) { |
| cmd = getConnectionCreateCommand((CreateConnectionViewRequest) individualRequest); |
| } |
| if (cmd != null && cmd.canExecute()) { |
| commands.add(cmd); |
| } |
| } |
| |
| if (commands.isEmpty()) { |
| // GEF's AbstractConnectionCreationTool expects a null command |
| // when the gesture should be disabled. |
| return null; |
| } |
| |
| // return an executable command that does nothing |
| return new Command() {/* do nothing*/}; |
| } |
| } |
| |
| /** |
| * Gets the command to complete the creation of a new connection and |
| * relationship. |
| * |
| * @param request |
| * @return Command |
| */ |
| protected Command getConnectionAndRelationshipCompleteCommand( |
| CreateConnectionViewAndElementRequest request) { |
| // get the element descriptor |
| CreateElementRequestAdapter requestAdapter = request |
| .getConnectionViewAndElementDescriptor().getCreateElementRequestAdapter(); |
| // get the semantic request |
| CreateRelationshipRequest createElementRequest = (CreateRelationshipRequest) requestAdapter |
| .getAdapter(CreateRelationshipRequest.class); |
| |
| createElementRequest.setPrompt(!request.isUISupressed()); |
| |
| // complete the semantic request by filling in the source and |
| // destination |
| INodeEditPart targetEP = getConnectionCompleteEditPart(request); |
| View sourceView = (View)request.getSourceEditPart().getModel(); |
| View targetView = (View)targetEP.getModel(); |
| |
| // resolve the source |
| EObject source = ViewUtil.resolveSemanticElement(sourceView); |
| if (source == null) { |
| source = sourceView; |
| } |
| createElementRequest.setSource(source); |
| |
| // resolve the target |
| EObject target = ViewUtil.resolveSemanticElement(targetView); |
| if (target == null) { |
| target = targetView; |
| } |
| createElementRequest.setTarget(target); |
| |
| // get the create element request based on the elementdescriptor's |
| // request |
| Command createElementCommand = targetEP |
| .getCommand(new EditCommandRequestWrapper( |
| (CreateRelationshipRequest) requestAdapter |
| .getAdapter(CreateRelationshipRequest.class), request.getExtendedData())); |
| |
| // create the create semantic element wrapper command |
| if (null == createElementCommand) |
| return null; |
| |
| SemanticCreateCommand semanticCommand = new SemanticCreateCommand( |
| requestAdapter, createElementCommand); |
| // get the view command |
| Command viewCommand = getConnectionCompleteCommand(request); |
| if (null == viewCommand) |
| return null; |
| // form the compound command and return |
| CompositeCommand cc = new CompositeCommand(semanticCommand.getLabel()); |
| cc.compose( semanticCommand ); |
| cc.compose( new CommandProxy(viewCommand) ); |
| return new ICommandProxy(cc); |
| } |
| |
| /** |
| * Gets the command to complete the creation of a new connection and |
| * relationship (if applicable) for an unspecified type request. This command |
| * includes a command to popup a menu to prompt the user for the type of |
| * connection to be created. |
| * |
| * @param request |
| * the unspecified type request |
| * @return the command |
| */ |
| protected Command getUnspecifiedConnectionCompleteCommand( |
| CreateUnspecifiedTypeConnectionRequest request) { |
| |
| if (request.isDirectionReversed()) { |
| return getReversedUnspecifiedConnectionCompleteCommand(request); |
| } |
| |
| List menuContent = getConnectionMenuContent(request); |
| |
| if (menuContent.isEmpty()) { |
| return null; |
| } else if (menuContent.size() == 1) { |
| return getConnectionCompleteCommand(menuContent.get(0), request); |
| } else { |
| return new ICommandProxy(getPromptAndCreateConnectionCommand( |
| menuContent, request)); |
| } |
| } |
| |
| /** |
| * Gets a command that pops up a menu which allows the user to select which |
| * type of connection to be created and then creates the connection. |
| * |
| * @param content |
| * The list of items making up the content of the popup menu. |
| * @param request |
| * The relevant create connection request. |
| * @return the command to popup up the menu and create the connection |
| */ |
| protected ICommand getPromptAndCreateConnectionCommand(List content, |
| CreateConnectionRequest request) { |
| return new PromptAndCreateConnectionCommand(content, request); |
| } |
| |
| /** |
| * Gets the command to create a connection based on the request and the |
| * connection identifier. This method is called after the user has selected |
| * the connection to be created when presented with a popup. |
| * @see #getPromptAndCreateConnectionCommand(List, CreateConnectionRequest) |
| * |
| * @param connectionType |
| * the connection type as specified in |
| * {@link #getConnectionMenuContent(CreateConnectionRequest)} |
| * @param request |
| * the request, identifying the source and target |
| * @return the command to create the connection |
| */ |
| protected Command getConnectionCompleteCommand(Object connectionType, |
| CreateConnectionRequest request) { |
| if (connectionType instanceof IElementType) { |
| if (request instanceof CreateUnspecifiedTypeConnectionRequest) { |
| CreateRequest createRequest = ((CreateUnspecifiedTypeConnectionRequest) request) |
| .getRequestForType((IElementType) connectionType); |
| if (createRequest != null) { |
| return getHost().getCommand(createRequest); |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Gets a list of all the connector items that will represent the connector |
| * choices and will appear in the popup menu. This method will get the |
| * connector content if the given request is a |
| * <code>CreateUnspecifiedTypeConnectionRequest</code> using the types it |
| * holds or the types retrieved from the Modeling Assistant Service. |
| * |
| * <p> |
| * If a subclass wishes to provide additional element types they should |
| * consider providing these in a Modeling Assistant Provider. If a subclass |
| * wishes to provide connector choices that are not elements types they may |
| * provide them here, in this case, the label provider for |
| * {@link PromptAndCreateConnectionCommand} may need to customized. |
| * </p> |
| * |
| * @return the list of connector items to appear in the popup menu |
| */ |
| protected List getConnectionMenuContent(CreateConnectionRequest request) { |
| List validRelTypes = new ArrayList(); |
| if (request instanceof CreateUnspecifiedTypeConnectionRequest) { |
| CreateUnspecifiedTypeConnectionRequest unspecifiedRequest = (CreateUnspecifiedTypeConnectionRequest) request; |
| List allRequests = unspecifiedRequest.getAllRequests(); |
| if (allRequests.isEmpty()) { |
| return null; |
| } |
| IGraphicalEditPart sourceEP = (IGraphicalEditPart) ((CreateConnectionRequest) allRequests |
| .get(0)).getSourceEditPart(); |
| IGraphicalEditPart targetEP = (IGraphicalEditPart) ((CreateConnectionRequest) allRequests |
| .get(0)).getTargetEditPart(); |
| |
| List allRelTypes = unspecifiedRequest.useModelingAssistantService() ? ModelingAssistantService |
| .getInstance().getRelTypesOnSourceAndTarget(sourceEP, targetEP) |
| : unspecifiedRequest.getElementTypes(); |
| |
| for (Iterator iter = allRelTypes.iterator(); iter.hasNext();) { |
| IElementType type = (IElementType) iter.next(); |
| |
| Command individualCmd = null; |
| |
| Request createConnectionRequest = unspecifiedRequest |
| .getRequestForType(type); |
| if (createConnectionRequest != null) { |
| individualCmd = getHost().getCommand( |
| createConnectionRequest); |
| |
| if (individualCmd != null && individualCmd.canExecute()) { |
| validRelTypes.add(type); |
| } |
| } else { |
| // This type may not have been given when the connection |
| // creation occurred. In this case, use the deferred |
| // connection creation mechanism. |
| |
| // First, setup the request to initialize the connection |
| // start command. |
| CreateConnectionViewRequest connectionRequest = CreateViewRequestFactory |
| .getCreateConnectionRequest(type, |
| ((IGraphicalEditPart) getHost()) |
| .getDiagramPreferencesHint()); |
| connectionRequest.setSourceEditPart(null); |
| connectionRequest.setTargetEditPart(sourceEP); |
| connectionRequest |
| .setType(RequestConstants.REQ_CONNECTION_START); |
| sourceEP.getCommand(connectionRequest); |
| |
| // Now, setup the request in preparation to get the |
| // connection end |
| // command. |
| connectionRequest.setSourceEditPart(sourceEP); |
| connectionRequest.setTargetEditPart(targetEP); |
| connectionRequest |
| .setType(RequestConstants.REQ_CONNECTION_END); |
| individualCmd = targetEP.getCommand(connectionRequest); |
| |
| if (individualCmd != null && individualCmd.canExecute()) { |
| validRelTypes.add(type); |
| unspecifiedRequest.addRequest(type, connectionRequest); |
| } |
| } |
| } |
| |
| } |
| return validRelTypes; |
| } |
| |
| /** |
| * Gets the command to complete the creation of a new connection and |
| * relationship (if applicable) for an unspecified type request. This command |
| * includes a command to popup a menu to prompt the user for the type of |
| * relationship to be created. |
| * |
| * @param request |
| * the reversed unspecified type request |
| * @return the command |
| */ |
| protected Command getReversedUnspecifiedConnectionCompleteCommand( |
| CreateUnspecifiedTypeConnectionRequest request) { |
| EditPart realSourceEP = request.getTargetEditPart(); |
| EditPart realTargetEP = request.getSourceEditPart(); |
| for (Iterator iter = request.getAllRequests().iterator(); iter |
| .hasNext();) { |
| CreateConnectionRequest connectionRequest = (CreateConnectionRequest) iter |
| .next(); |
| |
| // First, setup the request to initialize the connection start |
| // command. |
| connectionRequest.setSourceEditPart(null); |
| connectionRequest.setTargetEditPart(realSourceEP); |
| connectionRequest.setType(RequestConstants.REQ_CONNECTION_START); |
| realSourceEP.getCommand(connectionRequest); |
| |
| // Now, setup the request in preparation to get the connection end |
| // command. |
| connectionRequest.setSourceEditPart(realSourceEP); |
| connectionRequest.setTargetEditPart(realTargetEP); |
| connectionRequest.setType(RequestConstants.REQ_CONNECTION_END); |
| } |
| |
| // The requests are now ready to be sent to get the connection end |
| // command from real source to real target. |
| request.setDirectionReversed(false); |
| Command command = realTargetEP.getCommand(request); |
| return command; |
| } |
| |
| private TransactionalEditingDomain getEditingDomain() { |
| return ((IGraphicalEditPart) getHost()).getEditingDomain(); |
| } |
| } |