/***************************************************************************** * Copyright (c) 2010 Atos Origin. * * * 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: * Atos Origin - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.activity.edit.policies; import java.util.Iterator; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.draw2d.ConnectionAnchor; 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.EditPolicy; import org.eclipse.gef.commands.Command; import org.eclipse.gef.requests.CreateConnectionRequest; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; 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.ui.commands.CreateCommand; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; 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.editpolicies.CanonicalEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.GraphicalNodeEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.internal.commands.SetConnectionBendpointsCommand; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.type.core.IHintedType; import org.eclipse.gmf.runtime.notation.Connector; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.gmf.runtime.notation.impl.ShapeImpl; import org.eclipse.papyrus.uml.diagram.activity.providers.UMLElementTypes; import org.eclipse.uml2.uml.ActivityNode; import org.eclipse.uml2.uml.ObjectFlow; public class ObjectFlowWithPinsCreationEditPolicy extends GraphicalNodeEditPolicy { /** * Returns a command that will initialize connection creation. * * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.GraphicalNodeEditPolicy#getConnectionCreateCommand(org.eclipse.gef.requests.CreateConnectionRequest) * @param request * the request for creating the connection * @return the command */ @Override 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()); if(getObjectFlowHint().equals(req.getConnectionViewDescriptor().getSemanticHint())) { // handle redirection of Object flow on created child pin sceCommand.setNewSourceAdaptor(getObjectFlowSourceViewAdapter(request)); } else { 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; } /** * Get the semantic hint for an object flow edge * * @return semantic hint */ private static String getObjectFlowHint() { IHintedType objectFlowType = (IHintedType)UMLElementTypes.ObjectFlow_4003; return objectFlowType.getSemanticHint(); } /** * Returns a command that will create the connection. * * @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getConnectionCompleteCommand(org.eclipse.gef.requests.CreateConnectionRequest) * @param request * the request for creating the connection * @return the command */ 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 if(request instanceof CreateConnectionViewRequest && getObjectFlowHint().equals(((CreateConnectionViewRequest)request).getConnectionViewDescriptor().getSemanticHint())) { // handle redirection of Object flow on created child pin sceCommand.setNewTargetAdaptor(getObjectFlowTargetViewAdapter(request)); } else { 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(); } /** * Get the adapter to recover the object flow source view * * @param request * connection creation request * @return adapter */ private IAdaptable getObjectFlowSourceViewAdapter(final CreateConnectionRequest request) { return new IAdaptable() { public Object getAdapter(Class adapter) { if(adapter != null && adapter.isAssignableFrom(ShapeImpl.class)) { return getObjectFlowExtremityView(true); } return null; } }; } /** * Get the adapter to recover the object flow target view * * @param request * connection creation request * @return adapter */ private IAdaptable getObjectFlowTargetViewAdapter(final CreateConnectionRequest request) { return new IAdaptable() { public Object getAdapter(Class adapter) { if(adapter != null && adapter.isAssignableFrom(ShapeImpl.class)) { return getObjectFlowExtremityView(false); } return null; } }; } /** * Try and get an extremity view of the object flow contained in this host. * * @param isStartEnd * true if view is the object flow start end, false for the * target end * @return the view or null */ protected View getObjectFlowExtremityView(boolean isStartEnd) { Object objectFlowView = getViewAdapter().getAdapter(Connector.class); if(objectFlowView instanceof Connector) { EObject objectFlow = ((Connector)objectFlowView).getElement(); if(objectFlow instanceof ObjectFlow) { ActivityNode actNode = null; if(isStartEnd) { actNode = ((ObjectFlow)objectFlow).getSource(); } else { actNode = ((ObjectFlow)objectFlow).getTarget(); } if(actNode != null) { if(getHost().getModel() instanceof View) { View view = (View)getHost().getModel(); if(actNode.equals(view.getElement())) { return view; } } // refresh view children which have not been created yet. EditPolicy policy = getHost().getEditPolicy(EditPolicyRoles.CANONICAL_ROLE); if(policy instanceof CanonicalEditPolicy) { CanonicalEditPolicy canonical = (CanonicalEditPolicy)policy; if(!canonical.isEnabled()) { canonical.setEnable(true); canonical.refresh(); canonical.setEnable(false); } else { canonical.refresh(); } } // recover the appropriate child view for(Object childPart : getHost().getChildren()) { if(childPart instanceof EditPart) { Object containedView = ((EditPart)childPart).getModel(); if(containedView instanceof View) { if(actNode.equals(((View)containedView).getElement())) { return (View)containedView; } } } } } } } return null; } /** * Get the editing domain * * @return editing domain */ private TransactionalEditingDomain getEditingDomain() { return ((IGraphicalEditPart)getHost()).getEditingDomain(); } }