/*****************************************************************************
* 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
* Arthur daussy (Atos) arthur.daussy@atos.net - Bug : 365405: [State Machine Diagram] Behaviours (Entry,exit,do) on states should have their own mechanisms
*
*****************************************************************************/
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.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.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.StateEditPart;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.UMLPackage;
/**
* This listener will handle the creation of visual for element for behavior (/do /entry /exit).
*
* @author Arthur Daussy
*
*/
public class StateBehaviorsListener extends AbstractModifcationTriggerListener {
/**
* Return one of the following {@link EStructuralFeature} (UMLPackage.Literals.STATE__DO_ACTIVITY.equals(eStructuralFeature) ||
* UMLPackage.Literals.STATE__EXIT.equals(eStructuralFeature) || UMLPackage.Literals.STATE__ENTRY.equals(eStructuralFeature))or null if the
* {@link EStructuralFeature} in argument do concern behaviors
*
* @param eStructuralFeature
* @return
*/
@Override
protected boolean isCorrectStructuralfeature(EStructuralFeature eStructuralFeature) {
if(UMLPackage.Literals.STATE__DO_ACTIVITY.equals(eStructuralFeature) || UMLPackage.Literals.STATE__EXIT.equals(eStructuralFeature) || UMLPackage.Literals.STATE__ENTRY.equals(eStructuralFeature)) {
return true;
}
return false;
}
/**
* Handle modification on behavior attribute of state (entry , exit , do activity)
*
* @param notif
*/
@Override
protected CompositeCommand getModificationCommand(Notification notif) {
Request createRequest = null;
Request deleteRequest = null;
if(notif.getEventType() == Notification.SET) {
Object object = notif.getNewValue();
Object oldObject = notif.getOldValue();
StateEditPart stateEditPart = getContainingEditPart(notif.getNotifier());
if(object instanceof Behavior) {
//Get the request to create the editPart
createRequest = getCreateRequest(object, stateEditPart);
}
//Get the request to delete the editPart
deleteRequest = getDeleteRequest(oldObject, stateEditPart);
//handle both request if needed
CompositeCommand cc = new CompositeCommand("Modification command triggered by modedication of one of the behaviros of selected state");//$NON-NLS-0$
org.eclipse.gef.commands.Command cmd1 = getCommandFromRequest(createRequest, stateEditPart);
if(cmd1 != null && cmd1.canExecute()) {
cc.compose(new CommandProxy(cmd1));
}
org.eclipse.gef.commands.Command cmd2 = getCommandFromRequest(deleteRequest, stateEditPart);
if(cmd2 != null && cmd2.canExecute()) {
cc.compose(new CommandProxy(cmd2));
}
refreshEditParts(cc, Collections.singleton((IGraphicalEditPart)stateEditPart));
return cc;
}
return null;
}
/**
* Handle the request passed in argument
* 1. Look for the command
* 2. Execute the command
*
* @param request
*/
protected org.eclipse.gef.commands.Command getCommandFromRequest(Request request, IGraphicalEditPart editPart) {
if(request != null) {
return editPart.getCommand(request);
}
return null;
}
/**
* Get the request to delete the EditPart of corresponding behavior
*
* @param notif
* @param request
* (
* @return
*/
private Request getDeleteRequest(Object oldObject, StateEditPart stateEditPart) {
Request request = null;
//When unset the feature
if(oldObject instanceof Behavior) {
Behavior oldBehavior = (Behavior)oldObject;
IGraphicalEditPart iGrapEditPart = getChildByEObject(oldBehavior, stateEditPart, false);
if(iGrapEditPart != null) {
request = new GroupRequest(RequestConstants.REQ_DELETE);
((GroupRequest)request).setEditParts(iGrapEditPart);
}
}
return request;
}
private Request getCreateRequest(Object object, StateEditPart stateEditPart) {
Request request;
Behavior behavior = (Behavior)object;
request = new DropObjectsRequest();
((DropObjectsRequest)request).setLocation(new Point(1, 1));
((DropObjectsRequest)request).setObjects(Collections.singletonList(behavior));
return request;
}
/**
* Get the containing edit part (stateEditPart)
*
* @param oldBehavior
* @return
*/
protected StateEditPart getContainingEditPart(Object toTest) {
//If not EObject found return null;
if(toTest == null && toTest instanceof EObject) {
return null;
}
IGraphicalEditPart found = getChildByEObject((EObject)toTest, getDiagramEditPart(), false);
if(found instanceof StateEditPart) {
return (StateEditPart)found;
}
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);
}
}
}
}