/*****************************************************************************
* Copyright (c) 2010 CEA
*
*
* 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.sequence.edit.policies;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.FeedbackHelper;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.diagram.core.commands.SetConnectionAnchorsCommand;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
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.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeConnectionRequest;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.sequence.command.PromptCreateElementAndNodeCommand;
import org.eclipse.papyrus.uml.diagram.sequence.providers.UMLElementTypes;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceRequestConstant;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceUtil;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.Lifeline;
/**
* Edit Policy to create an element on a lifeline associated with the creation of a message.
* For example it can be used to create a Destruction Event with a Message Delete
* or the target Execution Specification with a Message Sync.
*
* @author Mathieu Velten
*
*/
public class ElementCreationWithMessageEditPolicy extends LifelineChildGraphicalNodeEditPolicy {
/**
* apex updated
*/
@Override
protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {
// CompoundCommand compound = new CompoundCommand();
Command command = super.getConnectionCompleteCommand(request);
if(command != null && command.canExecute()) {
// compound.add(command);
if(request instanceof CreateConnectionViewAndElementRequest) {
CreateConnectionViewAndElementRequest viewRequest = (CreateConnectionViewAndElementRequest)request;
EditPart targetEP = getTargetEditPart(viewRequest);
EObject target = ViewUtil.resolveSemanticElement((View)targetEP.getModel());
EditPart sourceEP = viewRequest.getSourceEditPart();
EObject source = ViewUtil.resolveSemanticElement((View)sourceEP.getModel());
/* apex improved start */
if (apexGetMessageHints().contains(viewRequest.getConnectionViewDescriptor().getSemanticHint())) {
/* apex improved end */
/* apex replaced
if(getSyncMessageHint().equals(viewRequest.getConnectionViewDescriptor().getSemanticHint()) || getReplyMessageHint().equals(viewRequest.getConnectionViewDescriptor().getSemanticHint())) {
*/
if(target instanceof Lifeline ||
// handle reflexive synch message by creating a new ES
(target instanceof ExecutionSpecification && target.equals(source))) {
InteractionFragment ift = SequenceUtil.findInteractionFragmentContainerAt(viewRequest.getLocation(), getHost());
// retrieve the good execution specification type using the source of the message
if(target instanceof ExecutionSpecification) {
// retrieve its associated lifeline
targetEP = targetEP.getParent();
target = ViewUtil.resolveSemanticElement((View)targetEP.getModel());
}
/* apex improved start */
return new ICommandProxy(new PromptCreateElementAndNodeCommand(
command, getEditingDomain(),viewRequest.getConnectionViewDescriptor(),
(ShapeNodeEditPart) targetEP, target, sourceEP, request, ift));
/* apex improved end */
/* apex replaced
EditPart sourceEditPart = request.getSourceEditPart();
if (sourceEditPart instanceof ActionExecutionSpecificationEditPart || sourceEditPart instanceof BehaviorExecutionSpecificationEditPart) {
return new ICommandProxy(new PromptCreateElementAndNodeCommand(command, getEditingDomain(),viewRequest.getConnectionViewDescriptor(),(ShapeNodeEditPart) targetEP, target,sourceEP,request, ift));
}
*/
// IHintedType elementType = null;
// if(sourceEditPart instanceof ActionExecutionSpecificationEditPart) {
// elementType = (IHintedType)UMLElementTypes.ActionExecutionSpecification_3006;
// } else if(request.getSourceEditPart() instanceof BehaviorExecutionSpecificationEditPart) {
// elementType = (IHintedType)UMLElementTypes.BehaviorExecutionSpecification_3003;
// }
//
//
// if(elementType != null) {
// CreateElementAndNodeCommand createExecutionSpecificationCommand = new CreateElementAndNodeCommand(getEditingDomain(), (ShapeNodeEditPart)targetEP, target, elementType, request.getLocation());
// createExecutionSpecificationCommand.putCreateElementRequestParameter(SequenceRequestConstant.INTERACTIONFRAGMENT_CONTAINER, ift);
// compound.add(createExecutionSpecificationCommand);
//
// // put the anchor at the top of the figure
// ChangeEdgeTargetCommand changeTargetCommand = new ChangeEdgeTargetCommand(getEditingDomain(), createExecutionSpecificationCommand, viewRequest.getConnectionViewDescriptor(), "(0.5, 0.0)");
// compound.add(new ICommandProxy(changeTargetCommand));
// }
}
}
}
}
return command;
}
private static String getSyncMessageHint() {
IHintedType message = (IHintedType)UMLElementTypes.Message_4003;
return message.getSemanticHint();
}
private static String getReplyMessageHint() {
IHintedType message = (IHintedType)UMLElementTypes.Message_4005;
return message.getSemanticHint();
}
private TransactionalEditingDomain getEditingDomain() {
return ((IGraphicalEditPart)getHost()).getEditingDomain();
}
/**
* 모든 Message들의 SemanticHint List 반환
* @return
*/
private static List<String> apexGetMessageHints() {
List<String> hints = new ArrayList<String>();
hints.add(((IHintedType)UMLElementTypes.Message_4003).getSemanticHint());
hints.add(((IHintedType)UMLElementTypes.Message_4004).getSemanticHint());
hints.add(((IHintedType)UMLElementTypes.Message_4005).getSemanticHint());
// hints.add(((IHintedType)UMLElementTypes.Message_4006).getSemanticHint()); // Create Message
hints.add(((IHintedType)UMLElementTypes.Message_4007).getSemanticHint());
hints.add(((IHintedType)UMLElementTypes.Message_4008).getSemanticHint());
hints.add(((IHintedType)UMLElementTypes.Message_4009).getSemanticHint());
return hints;
}
/**
* apex updated
*/
@Override
protected void showCreationFeedback(CreateConnectionRequest request) {
/* apex improved start */
FeedbackHelper helper = getFeedbackHelper(request);
Point p = new Point(request.getLocation());
ConnectionAnchor anchor = getTargetConnectionAnchor(request);
Point sourceLocation = null;
if (request instanceof CreateUnspecifiedTypeConnectionRequest) {
CreateUnspecifiedTypeConnectionRequest unspecifiedRequest = (CreateUnspecifiedTypeConnectionRequest)request;
for (Object type : unspecifiedRequest.getElementTypes()) {
if (type instanceof IElementType) {
CreateRequest createRequest = unspecifiedRequest.getRequestForType((IElementType)type);
Object srcLocation = createRequest.getExtendedData().get(SequenceRequestConstant.SOURCE_LOCATION_DATA);
if (srcLocation instanceof Point) {
sourceLocation = (Point)srcLocation;
break;
}
}
}
}
if (anchor == null && sourceLocation != null) {
p.y = sourceLocation.y;
}
helper.update(anchor, p);
/* apex improved end */
/* apex replaced
super.showCreationFeedback(request);
*/
/* apex added start */
if (request instanceof CreateUnspecifiedTypeConnectionRequest) {
CreateUnspecifiedTypeConnectionRequest unspecifiedRequest = (CreateUnspecifiedTypeConnectionRequest)request;
for (Object type : unspecifiedRequest.getElementTypes()) {
if (type instanceof IElementType) {
CreateRequest createRequest = unspecifiedRequest.getRequestForType((IElementType)type);
if (createRequest instanceof CreateConnectionRequest) {
apexResetSourceAnchor((CreateConnectionRequest)createRequest);
}
}
}
}
/* apex added end */
}
/**
* 화면 이동에 따른 Feedback의 source anchor 변경
* SetConnectionAnchorsCommand의 source terminal 변경
* @param request
*/
private void apexResetSourceAnchor(CreateConnectionRequest request) {
EditPart sourceEditPart = request.getSourceEditPart();
if (sourceEditPart instanceof INodeEditPart && !sourceEditPart.equals(request.getTargetEditPart())) {
INodeEditPart sourceNodeEditPart = (INodeEditPart)sourceEditPart;
Point p = (Point)request.getExtendedData().get(SequenceRequestConstant.SOURCE_LOCATION_DATA);
ICommandProxy proxy = (ICommandProxy) request.getStartCommand();
if (p != null && proxy != null) {
CreateConnectionRequest createRequest = new CreateConnectionRequest();
createRequest.setLocation(p);
ConnectionAnchor anchor = sourceNodeEditPart.getSourceConnectionAnchor(createRequest);
FeedbackHelper helper = getFeedbackHelper(createRequest);
helper.setMovingStartAnchor(true);
helper.update(anchor, p);
helper.setMovingStartAnchor(false);
CompositeCommand cc = (CompositeCommand)proxy.getICommand();
SetConnectionAnchorsCommand scaCommand = null;
Iterator iter = cc.iterator();
while (iter.hasNext()) {
Object next = iter.next();
if (next instanceof SetConnectionAnchorsCommand) {
scaCommand = (SetConnectionAnchorsCommand)next;
break;
}
}
if (scaCommand != null) {
scaCommand.setNewSourceTerminal(sourceNodeEditPart.mapConnectionAnchorToTerminal(anchor));
}
}
}
}
}