/*****************************************************************************
* Copyright (c) 2011 Atos.
*
*
* 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 - Initial API and implementation
*
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.statemachine.custom.listeners;
import java.util.Collections;
import java.util.Set;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
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.internal.commands.RefreshEditPartCommand;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.InternalTransitionEditPart;
import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.RegionCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.TransitionEditPart;
import org.eclipse.uml2.uml.Transition;
import org.eclipse.uml2.uml.TransitionKind;
import org.eclipse.uml2.uml.UMLPackage;
/**
* Listener of internal state transition
*/
public class InternalStateListener extends AbstractModifcationTriggerListener {
private static final String DROP_INTERNAL_TRANSITION_COMMAND_LABEL = "Drop internal transition";
@Override
protected boolean isCorrectStructuralfeature(EStructuralFeature eStructuralFeature) {
if(UMLPackage.Literals.TRANSITION__KIND.equals(eStructuralFeature)) {
return true;
}
return false;
}
@Override
protected CompositeCommand getModificationCommand(Notification notif) {
Object newValue = notif.getNewValue();
Object notifier = notif.getNotifier();
if(newValue instanceof TransitionKind && notifier instanceof EObject) {
CompositeCommand cc = new CompositeCommand("Modification command triggered by modedication of the kind of the current selected transition");//$NON-NLS-0$
EObject eNotifier = (EObject)notifier;
//Handle deletion of the old EditPart
boolean becomingInternal = isBecomingInternal(notif);
IGraphicalEditPart availableEditPart = getChildByEObject(eNotifier, getDiagramEditPart(), becomingInternal);
//If there no current represent nothing has to be done
if(availableEditPart == null) {
return null;
}
Command deleteCommant = getDeleteCommand(becomingInternal, availableEditPart);
if(deleteCommant != null && deleteCommant.canExecute()) {
cc.compose(new CommandProxy(deleteCommant));
}
//handle addition of the new EditPart
Command creationCommaned = getCreationCommand(becomingInternal, eNotifier);
if(creationCommaned != null && creationCommaned.canExecute()) {
cc.compose(new CommandProxy(creationCommaned));
}
return cc;
}
return null;
}
/**
* Refresh all needed EditParts {@link AbstractModifcationTriggerListener#needRefresh()} and
* {@link AbstractModifcationTriggerListener#getEditPartsToRefresh()}
*
* @param cc
* @param set
*/
protected void refreshEditParts(CompositeCommand cc, Set<IGraphicalEditPart> set) {
for(IGraphicalEditPart part : set) {
RefreshEditPartCommand refreshEditPart = new RefreshEditPartCommand(part, true);
if(refreshEditPart != null && refreshEditPart.canExecute()) {
cc.compose(refreshEditPart);
}
}
}
/**
* Return true if the the current feature indicate that the new value of the feature is {@link TransitionKind#INTERNAL}
*
* @param notif
* @return
*/
protected boolean isBecomingInternal(Notification notif) {
Object newValue = notif.getNewValue();
if(newValue instanceof TransitionKind) {
TransitionKind newKind = (TransitionKind)newValue;
return TransitionKind.INTERNAL_LITERAL.equals(newKind);
}
return false;
}
/**
* Get the command to delete the old EditPart
*
* @param isBecomingInternal
* Boolean true if transition is going to kind X -> Internal
* @param availableEditPart
* Existing editpart of the transition
* @return
*/
private Command getDeleteCommand(boolean isBecomingInternal, IGraphicalEditPart availableEditPart) {
if(isBecomingInternal) {
//Get the old transition editpart
if(!(availableEditPart instanceof TransitionEditPart)) {
return null;
}
} else {
if(!(availableEditPart instanceof InternalTransitionEditPart)) {
return null;
}
}
Request request = new GroupRequest(RequestConstants.REQ_DELETE);
((GroupRequest)request).setEditParts(availableEditPart);
return availableEditPart.getCommand(request);
}
private Command getCreationCommand(boolean isBecomingInternal, EObject eNotifier) {
// IGraphicalEditPart
if(eNotifier instanceof Transition) {
Transition transition = (Transition)eNotifier;
IGraphicalEditPart dropTarget = null;
dropTarget = getChildByEObject(transition.getSource(), getDiagramEditPart(), isBecomingInternal);
if(isBecomingInternal) {
dropTarget = getChildByEObject(transition.getSource(), getDiagramEditPart(), false);
} else {
//get the region
dropTarget = getChildByEObject(transition.getContainer(), getDiagramEditPart(), false);
//get the compartment
dropTarget = dropTarget.getChildBySemanticHint(String.valueOf(RegionCompartmentEditPart.VISUAL_ID));
}
if(dropTarget != null) {
Request request = new DropObjectsRequest();
((DropObjectsRequest)request).setLocation(new Point(1, 1));
((DropObjectsRequest)request).setObjects(Collections.singletonList(transition));
Command cmd = dropTarget.getCommand(request);
if(cmd != null && cmd.canExecute()) {
CompositeCommand cc = new CompositeCommand(DROP_INTERNAL_TRANSITION_COMMAND_LABEL);
cc.compose(new CommandProxy(cmd));
refreshEditParts(cc, Collections.singleton(dropTarget));
return new ICommandProxy(cc);
}
return cmd;
}
}
return null;
}
}