/*****************************************************************************
* Copyright (c) 2012 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.dnd.strategy;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.RefreshConnectionsRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.dnd.strategy.MoveDropStrategy;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassNestedClassifierCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassNestedClassifierCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ComponentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ComponentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ComponentNestedClassifierCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ComponentNestedClassifierCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InterfaceEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InterfaceEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InterfaceNestedClassifierCompartmentEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InterfaceNestedClassifierCompartmentEditPartCN;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.NestedClassForClassEditPart;
import org.eclipse.papyrus.uml.diagram.clazz.part.UMLVisualIDRegistry;
import org.eclipse.papyrus.uml.diagram.common.commands.ShowHideElementsRequest;
import org.eclipse.papyrus.uml.diagram.dnd.Activator;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.UMLPackage;
/**
* A DropStrategy to move a Classifier into a Class
*
* @author Camille Letavernier
*/
//FIXME: The Class diagram already automatically displays inner classes
//when they are added to the semantic model. There might be a conflict with this strategy.
public class MoveInnerClassDropStrategy extends MoveDropStrategy {
@Override
public String getLabel() {
return "Reparent";
}
public String getID() {
return Activator.PLUGIN_ID + ".move.innerClass";
}
@Override
public String getDescription() {
return "Move the selected class to the target class or package";
}
@Override
protected EStructuralFeature getTargetFeature(Request request, EditPart targetEditPart) {
EObject targetSemanticElement = getTargetSemanticElement(targetEditPart);
if(targetSemanticElement instanceof org.eclipse.uml2.uml.Class) {
//In this case, the service edit will create the GMF View for InnerClass
return UMLPackage.eINSTANCE.getClass_NestedClassifier();
}
if(targetSemanticElement instanceof Interface) {
return UMLPackage.eINSTANCE.getInterface_NestedClassifier();
}
return null;
}
public int getPriority() {
return 101;
}
/**
*
* @param request
* @param targetEditPart
* @return A command to edit the graphical view
*/
@Override
protected Command getGraphicalCommand(Request request, EditPart targetEditPart) {
DropObjectsRequest dropRequest = getDropObjectsRequest(request);
if(dropRequest == null) {
return null;
}
// Create a view request from the drop request and then forward getting
// the command for that.
List<CreateViewRequest.ViewDescriptor> viewDescriptors = new LinkedList<CreateViewRequest.ViewDescriptor>();
for(EObject eObject : getSourceEObjects(dropRequest)) {
if(eObject instanceof org.eclipse.uml2.uml.Class) {
viewDescriptors.add(new CreateViewRequest.ViewDescriptor(new EObjectAdapter(eObject), Node.class, Integer.toString(NestedClassForClassEditPart.VISUAL_ID), ((IGraphicalEditPart)targetEditPart).getDiagramPreferencesHint()));
}
}
if(viewDescriptors.isEmpty()) {
return null;
}
CreateViewRequest createViewRequest = new CreateViewRequest(viewDescriptors);
createViewRequest.setLocation(dropRequest.getLocation());
targetEditPart = getTargetEditPart(targetEditPart);
Command createCommand = targetEditPart.getCommand(createViewRequest);
if(createCommand != null) {
List<?> result = (List<?>)createViewRequest.getNewObject();
dropRequest.setResult(result);
RefreshConnectionsRequest refreshRequest = new RefreshConnectionsRequest(result);
Command refreshCommand = targetEditPart.getCommand(refreshRequest);
ArrangeRequest arrangeRequest = new ArrangeRequest(RequestConstants.REQ_ARRANGE_DEFERRED);
arrangeRequest.setViewAdaptersToArrange(result);
Command arrangeCommand = targetEditPart.getCommand(arrangeRequest);
CompoundCommand cc = new CompoundCommand(createCommand.getLabel());
cc.add(createCommand.chain(refreshCommand));
cc.add(arrangeCommand);
for(Object object : dropRequest.getObjects()) {
if(object instanceof EditPart) {
EditPart editPart = (EditPart)object;
ShowHideElementsRequest destroyViewRequest = new ShowHideElementsRequest(editPart);
Command destroyViewCommand = editPart.getCommand(destroyViewRequest);
if(destroyViewCommand != null) {
cc.add(destroyViewCommand);
}
}
}
return cc;
}
return null;
}
protected EditPart getTargetEditPart(final EditPart targetEditPart) {
if(targetEditPart instanceof IGraphicalEditPart) {
EditPart primaryEditPart = getPrimaryEditPart(targetEditPart);
View primaryView = ((IGraphicalEditPart)targetEditPart).getPrimaryView();
int nestedClassSemanticHint = -1;
switch(UMLVisualIDRegistry.getVisualID(primaryView)) {
case ClassEditPart.VISUAL_ID:
nestedClassSemanticHint = ClassNestedClassifierCompartmentEditPart.VISUAL_ID;
break;
case ClassEditPartCN.VISUAL_ID:
nestedClassSemanticHint = ClassNestedClassifierCompartmentEditPartCN.VISUAL_ID;
break;
case InterfaceEditPart.VISUAL_ID:
nestedClassSemanticHint = InterfaceNestedClassifierCompartmentEditPart.VISUAL_ID;
break;
case InterfaceEditPartCN.VISUAL_ID:
nestedClassSemanticHint = InterfaceNestedClassifierCompartmentEditPartCN.VISUAL_ID;
break;
case ComponentEditPart.VISUAL_ID:
nestedClassSemanticHint = ComponentNestedClassifierCompartmentEditPart.VISUAL_ID;
break;
case ComponentEditPartCN.VISUAL_ID:
nestedClassSemanticHint = ComponentNestedClassifierCompartmentEditPartCN.VISUAL_ID;
break;
}
if(nestedClassSemanticHint != -1) {
String type = UMLVisualIDRegistry.getType(nestedClassSemanticHint);
EditPart target = ((IGraphicalEditPart)primaryEditPart).getChildBySemanticHint(type);
if(target != null) {
return target;
}
}
}
return targetEditPart;
}
protected EditPart getPrimaryEditPart(final EditPart targetEditPart) {
EditPart currentPart = targetEditPart;
while(currentPart != null) {
if(currentPart instanceof IPrimaryEditPart) {
return currentPart;
}
currentPart = currentPart.getParent();
}
return targetEditPart;
}
public String getCategoryID() {
return "org.eclipse.papyrus.drop.classToClassifier";
}
public String getCategoryLabel() {
return "Drop a Class on a Classifier";
}
public String getCategory() {
// TODO Auto-generated method stub
return null;
}
}