/*****************************************************************************
* Copyright (c) 2009 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.editpolicies;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.UnexecutableCommand;
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.ConnectionEditPart;
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.ListItemEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ContainerEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.commands.DuplicateViewsCommand;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.DuplicateRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.diagram.ui.requests.PasteViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardSupportUtil;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
import org.eclipse.gmf.runtime.emf.type.core.requests.DuplicateElementsRequest;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.commands.PapyrusDuplicateViewsCommand;
import org.eclipse.papyrus.uml.pastemanager.request.PasteRequest;
import org.eclipse.uml2.uml.Element;
/**
* this class has in charge to give a paste command, ie to copy graphically
* element
*/
@SuppressWarnings({ "rawtypes", "restriction" })
public class DuplicatePasteEditPolicy extends ContainerEditPolicy {
public final static String PASTE_ROLE = "PASTE_ROLE";
/**
* @see org.eclipse.gef.EditPolicy#getCommand(Request)
*/
@Override
public Command getCommand(Request request) {
if(PasteRequest.REQ_PAPYRUS_PASTE.equals(request.getType())) {
if(request instanceof PasteRequest) {
return getPasteCommand((PasteRequest)request);
} else {
return getPasteCommand((PasteViewRequest)request);
}
}
if(RequestConstants.REQ_DUPLICATE.equals(request.getType())) {
return null; //Does not work as expected. Seems redundant with Paste.
}
return super.getCommand(request);
}
@SuppressWarnings("unchecked")
protected Command getPasteCommand(PasteRequest request) {
List notationView = new ArrayList();
if(request.getElementToPaste() != null && request.getElementToPaste().size() > 0) {
notationView.addAll(request.getElementToPaste());
HashSet semanticElement = new HashSet();
return constructDuplicationCommand(notationView, semanticElement, request.getDuplicate(), ((IGraphicalEditPart)getHost()).getEditingDomain());
}
return null;
}
/**
* Returns a command to to duplicate views and their underlying semantic
* elements (if applicable) of the given editparts.
*
* @param request
* the <code>DuplicateElementsRequest</code> whose list of
* duplicated views will be populated when the command is
* executed
* @return the command to perform the duplication
*/
@SuppressWarnings("unchecked")
private Command getDuplicateCommand(DuplicateRequest request) {
List notationViewsToDuplicate = new ArrayList();
Set elementsToDuplicate = new HashSet();
for(Iterator iter = request.getEditParts().iterator(); iter.hasNext();) {
Object ep = iter.next();
// Disable duplicate on groups for now. See bugzilla 182972.
if(ep instanceof GroupEditPart) {
return UnexecutableCommand.INSTANCE;
}
if(ep instanceof ConnectionEditPart || ep instanceof ShapeEditPart || ep instanceof ListItemEditPart) {
View notationView = (View)((IGraphicalEditPart)ep).getModel();
if(notationView != null) {
notationViewsToDuplicate.add(notationView);
}
}
}
// Remove views whose container view is getting copied.
ClipboardSupportUtil.getCopyElements(notationViewsToDuplicate);
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain();
for(Iterator iter = notationViewsToDuplicate.iterator(); iter.hasNext();) {
View view = (View)iter.next();
EObject element = view.getElement();
if(element != null) {
EObject resolvedElement = EMFCoreUtil.resolve(editingDomain, element);
if(resolvedElement != null) {
elementsToDuplicate.add(resolvedElement);
}
}
}
return constructDuplicationCommand(notationViewsToDuplicate, elementsToDuplicate, request, editingDomain);
}
/**
* code comes from superclass {@inheritDoc}
*/
@SuppressWarnings("unchecked")
protected Command constructDuplicationCommand(List notationViewsToDuplicate, Set elementsToDuplicate, DuplicateRequest request, TransactionalEditingDomain editingDomain) {
/*
* We must append all inner edges of a node being duplicated. Edges are
* non-containment references, hence they won't be duplicated for free.
* Therefore, we add them here to the list views to duplicate. We don't
* add semantic elements of the edges to the list of semantic elements
* to duplicate since we assume that their semantic elements are owned
* by source or target or their semantic containers.
*/
/**
* Until duplicate views action enablement is driven by the created
* duplicate views command, we can't look for edges to duplicate. It's a
* performance hit.
*/
// List<Edge> allInnerEdges = new LinkedList<Edge>();
// for (Iterator itr = notationViewsToDuplicate.iterator();
// itr.hasNext();) {
// allInnerEdges.addAll(ViewUtil.getAllInnerEdges((View) itr.next()));
// }
// notationViewsToDuplicate.addAll(allInnerEdges);
if(!notationViewsToDuplicate.isEmpty()) {
if(!elementsToDuplicate.isEmpty()) {
ArrayList<EObject> stereotypedSelection = new ArrayList<EObject>();
// copy stereotype contained into
Iterator<EObject> iter = elementsToDuplicate.iterator();
while(iter.hasNext()) {
EObject subeObject = iter.next();
if(subeObject instanceof Element) {
stereotypedSelection.addAll(((Element)subeObject).getStereotypeApplications());
}
}
ArrayList<EObject> resultToCopy = new ArrayList(elementsToDuplicate);
resultToCopy.addAll(stereotypedSelection);
org.eclipse.gmf.runtime.emf.type.core.requests.DuplicateElementsRequest duplicateElementsRequest = new DuplicateElementsRequest(editingDomain, new ArrayList(resultToCopy));
Command duplicateElementsCommand = getHost().getCommand(new EditCommandRequestWrapper(duplicateElementsRequest, request.getExtendedData()));
if(duplicateElementsCommand != null && duplicateElementsCommand.canExecute()) {
CompositeCommand cc = new CompositeCommand(DiagramUIMessages.Commands_Duplicate_Label);
cc.compose(new CommandProxy(duplicateElementsCommand));
cc.compose(new DuplicateViewsCommand(editingDomain, DiagramUIMessages.Commands_Duplicate_Label, request, notationViewsToDuplicate, duplicateElementsRequest.getAllDuplicatedElementsMap(), getDuplicateViewsOffset(request)));
return new ICommandProxy(cc);
}
} else {
return new ICommandProxy(new PapyrusDuplicateViewsCommand(editingDomain, DiagramUIMessages.Commands_Duplicate_Label, request, notationViewsToDuplicate, new HashMap(), getDuplicateViewsOffset(request), (View)getHost().getModel()));
}
}
return null;
}
/**
* code comes from super class
*/
protected Point getDuplicateViewsOffset(DuplicateRequest request) {
if(request.getOffset() != null) {
return request.getOffset();
}
int offset = MapModeUtil.getMapMode(((org.eclipse.gef.GraphicalEditPart)getHost()).getFigure()).DPtoLP(10);
return new Point(offset, offset);
}
}