| /****************************************************************************** |
| * 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; |
| } |
| } |