blob: 74be227bcb3e10e911e98aa31a9fd1caba06cb54 [file] [log] [blame]
/******************************************************************************
* 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 org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.AbstractEditPolicy;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand;
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.ConnectionEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ITreeBranchEditPart;
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.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyReferenceRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientReferenceRelationshipRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Display;
/**
* An editpolicy to handle creation and updating of semantic model elements
*
* @author melaasar
*/
public class SemanticEditPolicy
extends AbstractEditPolicy {
private static final String DELETE_FROM_MODEL_DLG_TITLE = DiagramUIMessages.PromptingDeleteFromModelAction_DeleteFromModelDialog_Title;
private static final String DELETE_FROM_MODEL_DLG_MESSAGE = DiagramUIMessages.PromptingDeleteFromModelAction_DeleteFromModelDialog_Message;
private static final String DELETE_FROM_MODEL_DLG_TOGGLE_LABEL = DiagramUIMessages.MessageDialogWithToggle_DoNotPromptAgainToggle_label;
/**
* @see org.eclipse.gef.EditPolicy#getCommand(Request)
*/
public Command getCommand(Request request) {
if (RequestConstants.REQ_SEMANTIC_WRAPPER.equals(request.getType())) {
return getSemanticCommand(((EditCommandRequestWrapper) request)
.getEditCommandRequest());
} else if (REQ_RECONNECT_SOURCE.equals(request.getType())
&& relationshipSourceHasChanged((ReconnectRequest) request)) {
EditPart connectionEP = ((ReconnectRequest) request)
.getConnectionEditPart();
if (ViewUtil.resolveSemanticElement((View) connectionEP.getModel()) == null) {
return getReorientRefRelationshipSourceCommand((ReconnectRequest) request);
} else {
return getReorientRelationshipSourceCommand((ReconnectRequest) request);
}
} else if (REQ_RECONNECT_TARGET.equals(request.getType())
&& relationshipTargetHasChanged((ReconnectRequest) request)) {
EditPart connectionEP = ((ReconnectRequest) request)
.getConnectionEditPart();
if (ViewUtil.resolveSemanticElement((View) connectionEP.getModel()) == null) {
return getReorientRefRelationshipTargetCommand((ReconnectRequest) request);
} else {
return getReorientRelationshipTargetCommand((ReconnectRequest) request);
}
}
return super.getCommand(request);
}
/**
* Has the relationship target changed? If not, then it is not necessary to
* return a command that will change the relationship's target.
*
* @param request
* the request to reconnect the target of a relationship
* @return true if the target has changed; false otherwise
*/
private boolean relationshipTargetHasChanged(ReconnectRequest request) {
return !request.getConnectionEditPart().getTarget().equals(
request.getTarget());
}
/**
* Has the relationship source changed? If not, then it is not necessary to
* return a command that will change the relationship's source.
*
* @param request
* the request to reconnect the source of a relationship
* @return true if the source has changed; false otherwise
*/
private boolean relationshipSourceHasChanged(ReconnectRequest request) {
return !request.getConnectionEditPart().getSource().equals(
request.getTarget());
}
/**
* Method getSemanticCommand.
*
* @param request
* @return Command
*/
protected Command getSemanticCommand(IEditCommandRequest request) {
if ((request instanceof DestroyRequest) && (getHost() instanceof ConnectionEditPart)
&& !((ConnectionEditPart) getHost()).isSemanticConnection()) {
// no semantic meaning to the connection being destroyed
return null;
}
IEditCommandRequest completedRequest = completeRequest(request);
boolean shouldPromptOnDestroy = false;
if (completedRequest instanceof DestroyRequest && !isParentCanonical(getHost())) {
shouldPromptOnDestroy = ((DestroyRequest) completedRequest).isConfirmationRequired();
((DestroyRequest) completedRequest).setConfirm(false);
}
ICommand semanticCommand = null;
Object editHelperContext = completedRequest.getEditHelperContext();
IElementType elementType = ElementTypeRegistry.getInstance()
.getElementType(editHelperContext);
if(elementType == null && editHelperContext instanceof ICommand){
semanticCommand = (ICommand)editHelperContext ;
} else {
semanticCommand = (elementType != null)
? elementType.getEditCommand(completedRequest)
: null;
}
if(semanticCommand == null){
return null;
}
if (completedRequest instanceof DestroyRequest) {
((DestroyRequest) completedRequest).setConfirm(shouldPromptOnDestroy);
}
boolean shouldProceed = true;
if (completedRequest instanceof DestroyRequest) {
shouldProceed = shouldProceed((DestroyRequest) completedRequest);
}
if (shouldProceed) {
Command c = new ICommandProxy(semanticCommand);
if (completedRequest instanceof DestroyRequest) {
TransactionalEditingDomain domain = ((IGraphicalEditPart) getHost()).getEditingDomain();
ICommand ic = new DeleteCommand(domain, (View)getHost().getModel());
CompositeTransactionalCommand cc = new CompositeTransactionalCommand(domain, semanticCommand
.getLabel());
cc.setTransactionNestingEnabled(true);
cc.compose(semanticCommand);
cc.compose(ic);
c = new ICommandProxy(cc);
}
return c;
}
return null;
}
/**
* @see org.eclipse.gef.EditPolicy#understandsRequest(Request)
*/
public boolean understandsRequest(Request request) {
if (request instanceof EditCommandRequestWrapper)
return true;
if (REQ_RECONNECT_SOURCE.equals(request.getType())
|| REQ_RECONNECT_TARGET.equals(request.getType())) {
EObject parentElement = null;
if (getHost().getParent() instanceof IGraphicalEditPart) {
parentElement = ViewUtil
.resolveSemanticElement((View) getHost().getParent()
.getModel());
}
if (getHostElement() != parentElement)
return true;
}
return false;
}
private EObject getHostElement() {
return ViewUtil.resolveSemanticElement((View) getHost()
.getModel());
}
/**
* Returns a new completed version of the <code>request</code>, mainly
* based on targetting the host of this edit policy.
*
* @param request
* the request to be completed
* @return the completed version of the request. This may or may not be a
* new instance.
*/
protected IEditCommandRequest completeRequest(IEditCommandRequest request) {
IEditCommandRequest result = request;
if (result instanceof DestroyRequest) {
DestroyRequest destroyRequest = (DestroyRequest) result;
if (getHostElement() != null) {
// Destroy element request
if (destroyRequest instanceof DestroyElementRequest) {
((DestroyElementRequest) destroyRequest)
.setElementToDestroy(getHostElement());
((DestroyElementRequest) destroyRequest).getParameters().clear();
} else {
result = new DestroyElementRequest(request
.getEditingDomain(), getHostElement(), destroyRequest
.isConfirmationRequired());
result.addParameters(request.getParameters());
}
} else if (getHost() instanceof ConnectionEditPart) {
// Destroy reference request
EObject container = ViewUtil
.resolveSemanticElement(((Edge) getHost().getModel())
.getSource());
EObject referenceObject = ViewUtil
.resolveSemanticElement(((Edge) getHost().getModel())
.getTarget());
if (destroyRequest instanceof DestroyReferenceRequest) {
DestroyReferenceRequest destroyReferenceRequest = (DestroyReferenceRequest) result;
destroyReferenceRequest.setContainer(container);
destroyReferenceRequest
.setReferencedObject(referenceObject);
} else {
result = new DestroyReferenceRequest(((IGraphicalEditPart)getHost())
.getEditingDomain(), container, null, referenceObject,
destroyRequest.isConfirmationRequired());
result.addParameters(request.getParameters());
}
}
}
return result;
}
/**
* Method getReorientRelationshipSourceCommand.
*
* @param request
* @return Command
*/
protected Command getReorientRelationshipSourceCommand(
ReconnectRequest request) {
EObject connectionSemElement = ViewUtil.resolveSemanticElement(((View) request.getConnectionEditPart()
.getModel()));
EObject targetSemElement = ViewUtil.resolveSemanticElement(((View) request.getTarget().getModel()));
EObject oldSemElement = ViewUtil.resolveSemanticElement(((View) request.getConnectionEditPart()
.getSource().getModel()));
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
.getEditingDomain();
ReorientRelationshipRequest semRequest = new ReorientRelationshipRequest(
editingDomain, connectionSemElement, targetSemElement,
oldSemElement, ReorientRelationshipRequest.REORIENT_SOURCE);
semRequest.addParameters(request.getExtendedData());
return getSemanticCommand(semRequest);
}
/**
* Method getReorientRelationshipTargetCommand.
*
* @param request
* @return Command
*/
protected Command getReorientRelationshipTargetCommand(
ReconnectRequest request) {
EObject connectionSemElement = ViewUtil.resolveSemanticElement((View) request.getConnectionEditPart().getModel());
EObject targetSemElement = ViewUtil.resolveSemanticElement((View) request.getTarget().getModel());
EObject oldSemElement = ViewUtil.resolveSemanticElement((View) request.getConnectionEditPart()
.getTarget().getModel());
// check if we need to redirect the semantic request because of a tree
// gesture.
String connectionHint = ViewUtil
.getSemanticElementClassId((View) request.getConnectionEditPart()
.getModel());
if (((View) request.getTarget().getModel()).getElement() != null) {
String targetHint = ViewUtil
.getSemanticElementClassId((View) request.getTarget()
.getModel());
if (request.getConnectionEditPart() instanceof ITreeBranchEditPart
&& request.getTarget() instanceof ITreeBranchEditPart
&& connectionHint.equals(targetHint)) {
ITreeBranchEditPart targetBranch = (ITreeBranchEditPart) request
.getTarget();
targetSemElement = ViewUtil.resolveSemanticElement((View) targetBranch.getTarget().getModel());
}
}
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
.getEditingDomain();
ReorientRelationshipRequest semRequest = new ReorientRelationshipRequest(
editingDomain, connectionSemElement, targetSemElement,
oldSemElement, ReorientRelationshipRequest.REORIENT_TARGET);
semRequest.addParameters(request.getExtendedData());
return getSemanticCommand(semRequest);
}
/*
* Returns the getHost() if the policy understands the request.
*
* @see org.eclipse.gef.EditPolicy#getTargetEditPart(org.eclipse.gef.Request)
*/
public EditPart getTargetEditPart(Request request) {
if (understandsRequest(request)) {
return getHost();
} else {
return super.getTargetEditPart(request);
}
}
/**
* Method getReorientRelationshipSourceCommand.
*
* @param request
* @return Command
*/
protected Command getReorientRefRelationshipSourceCommand(
ReconnectRequest request) {
org.eclipse.gef.ConnectionEditPart connectionEP = (request).getConnectionEditPart();
if (connectionEP instanceof ConnectionEditPart) {
if (!((ConnectionEditPart) connectionEP).isSemanticConnection()) {
return null;
}
}
EditPart sourceEditPart = connectionEP.getSource();
EditPart targetEditPart = connectionEP.getTarget();
EObject referenceOwner = ViewUtil
.resolveSemanticElement((View) sourceEditPart.getModel());
EObject oldTarget = ViewUtil
.resolveSemanticElement((View) targetEditPart.getModel());
EObject newTarget = ViewUtil
.resolveSemanticElement((View) request.getTarget().getModel());
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
.getEditingDomain();
ReorientReferenceRelationshipRequest semRequest = new ReorientReferenceRelationshipRequest(
editingDomain, referenceOwner, newTarget, oldTarget,
ReorientReferenceRelationshipRequest.REORIENT_SOURCE);
semRequest.addParameters(request.getExtendedData());
return getSemanticCommand(semRequest);
}
/**
* Method getReorientRefRelationshipTargetCommand. Removes the reference the
* ConnectionEditPart current has an add the new TargetEditPart
*
* @param request
* @return Command
*/
protected Command getReorientRefRelationshipTargetCommand(
ReconnectRequest request) {
org.eclipse.gef.ConnectionEditPart connectionEP = (request).getConnectionEditPart();
if (connectionEP instanceof ConnectionEditPart) {
if (!((ConnectionEditPart) connectionEP).isSemanticConnection()) {
return null;
}
}
EditPart sourceEditPart = connectionEP.getSource();
EditPart targetEditPart = connectionEP.getTarget();
EObject referenceOwner = ViewUtil
.resolveSemanticElement((View) sourceEditPart.getModel());
EObject oldTarget = ViewUtil
.resolveSemanticElement((View) targetEditPart.getModel());
EObject newTarget = ViewUtil
.resolveSemanticElement((View) request.getTarget().getModel());
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart) getHost())
.getEditingDomain();
ReorientReferenceRelationshipRequest semRequest = new ReorientReferenceRelationshipRequest(
editingDomain, referenceOwner, newTarget, oldTarget,
ReorientReferenceRelationshipRequest.REORIENT_TARGET);
semRequest.addParameters(request.getExtendedData());
return getSemanticCommand(semRequest);
}
/**
* should proceed
* @param destroyRequest the destroy request
* @return true or false
*/
protected boolean shouldProceed(DestroyRequest destroyRequest) {
if (isParentCanonical(getHost())) {
return true;
}
if (!(destroyRequest.isConfirmationRequired())){
return true;
}else{
destroyRequest.setConfirm(false);
return showMessageDialog();
}
}
/**
* Checks if the parent container is canonical
*
* @param editpart the editpart in question
* @return true if the parent shape is canonical
*/
private static boolean isParentCanonical(EditPart editpart) {
EditPart parent = null;
if ((editpart instanceof ConnectionEditPart)
&& (((ConnectionEditPart) editpart).getSource() != null)) {
parent = ((ConnectionEditPart) editpart).getSource().getParent();
} else {
parent = editpart.getParent();
}
while (parent instanceof GroupEditPart) {
parent = parent.getParent();
}
return ((parent instanceof GraphicalEditPart) && ((GraphicalEditPart) parent)
.isCanonical());
}
/**
* launches the prompting dialogBox on deletion of elements from the model
* for the end user.
*
* @return boolean true if user pressed YES; false otherwise
*/
private boolean showMessageDialog() {
MessageDialogWithToggle dialog = MessageDialogWithToggle
.openYesNoQuestion(Display.getCurrent().getActiveShell(),
DELETE_FROM_MODEL_DLG_TITLE, DELETE_FROM_MODEL_DLG_MESSAGE,
DELETE_FROM_MODEL_DLG_TOGGLE_LABEL, false,
(IPreferenceStore) ((IGraphicalEditPart) getHost())
.getDiagramPreferencesHint().getPreferenceStore(),
IPreferenceConstants.PREF_PROMPT_ON_DEL_FROM_MODEL);
if (dialog.getReturnCode() == IDialogConstants.YES_ID)
return true;
else
return false;
}
}