blob: 04f84fcd3eebfe48356ffae4dfa54e408f351b6e [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2005, 2010 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.internal.commands;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.ui.requests.DuplicateRequest;
import org.eclipse.gmf.runtime.emf.commands.core.commands.DuplicateEObjectsCommand;
import org.eclipse.gmf.runtime.notation.Bounds;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
/**
* This command duplicates a list of notational views and adds each duplicate to
* it's originator's container. It also duplicates the semantic element that the
* view references (if it does reference a semantic element). All references
* between views and elements that are duplicated are updated to refer to the
* new duplicated objects.
*
* <p>
* The command returns the new duplicated views.
* </p>
*
* @author cmahoney
*/
public class DuplicateViewsCommand
extends DuplicateEObjectsCommand {
/**
* This is a map passed in by the client of all the elements that have been
* duplicated (key is original element, value is duplicated element) so that
* the views that are duplicated can be updated to point to the
* corresponding duplicated element.
*/
Map duplicatedElements;
/**
* This will be populated with the views that are duplicated after the
* command executes.
*/
List duplicatedViewsToBeReturned = new ArrayList();
private Point offset = new Point(0, 0);
/**
* Creates a new <code>DuplicateViewsCommand</code>.
*
* @param editingDomain
* the editing domain through which model changes are made
* @param label
* the command label
* @param request
* the <code>DuplicateElementsRequest</code> whose list of
* duplicated views will be populated
* @param viewsToDuplicate
* the views to be duplicated
* @param duplicatedElements
* the map of elements that were duplicated that should be used
* to change the duplicated views to reference its dupliated
* element (if applicable)
* @param offset
* the offset from the location of the original views where the
* new views will be placed.
*/
public DuplicateViewsCommand(TransactionalEditingDomain editingDomain, String label, DuplicateRequest request,
List viewsToDuplicate, Map duplicatedElements, Point offset) {
super(editingDomain, label, viewsToDuplicate);
this.duplicatedElements = duplicatedElements;
duplicatedViewsToBeReturned = request.getDuplicatedViews();
this.offset = offset;
}
/**
* Creates a new <code>DuplicateViewsCommand</code>.
*
* @param editingDomain
* the editing domain through which model changes are made
* @param label
* the command label
* @param request
* the <code>DuplicateElementsRequest</code> whose list of
* duplicated views will be populated
* @param viewsToDuplicate
* the views to be duplicated
* @param offset
* the offset from the location of the original views where the
* new views will be placed.
*/
public DuplicateViewsCommand(TransactionalEditingDomain editingDomain, String label, DuplicateRequest request,
List viewsToDuplicate, Point offset) {
this(editingDomain, label, request, viewsToDuplicate, null, offset);
}
/**
* Overridden to association the duplicated views with the duplicated
* elements.
*/
protected CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
CommandResult result = super.doExecuteWithResult(progressMonitor, info);
if (!result.getStatus().isOK()) {
return result;
}
for (Iterator iter = getObjectsToBeDuplicated().iterator(); iter
.hasNext();) {
View originalView = (View) iter.next();
View duplicateView = (View) getAllDuplicatedObjectsMap().get(
originalView);
// Update the duplicated views to reference the duplicated elements.
assignSementicElementsDownViewTree(duplicateView);
/**
* TODO: sourceRefs and targetRefs seem to be completely
* unnecessary. Look into removing the code below.
* Commented out for now.
*/
// Remove source and target edges that were not duplicated.
// List sourceRefs = new ArrayList(ViewUtil.getSourceConnections(duplicateView));
// for (Iterator iterator = sourceRefs.iterator(); iterator.hasNext();) {
// EObject edge = (EObject) iterator.next();
// if (!getAllDuplicatedObjectsMap().containsValue(edge)) {
// sourceRefs.remove(edge);
// }
// }
// List targetRefs = new ArrayList(ViewUtil.getTargetConnections(duplicateView));
// for (Iterator iterator = targetRefs.iterator(); iterator.hasNext();) {
// EObject edge = (EObject) iterator.next();
// if (!getAllDuplicatedObjectsMap().containsValue(edge)) {
// targetRefs.remove(edge);
// }
// }
if (duplicateView instanceof Node) {
// Change the location of the duplicated views.
LayoutConstraint layoutConstraint = ((Node) duplicateView)
.getLayoutConstraint();
if (layoutConstraint instanceof Bounds) {
Bounds bounds = (Bounds) layoutConstraint;
int x = bounds.getX();
bounds.setX(x + offset.x);
int y = bounds.getY();
bounds.setY(y + offset.y);
}
} else if (duplicateView instanceof Edge) {
assert originalView instanceof Edge;
// If the source/target wasn't duplicated, then the copier
// would not have set the source/target.
Edge duplicateEdge = (Edge) duplicateView;
Edge originalEdge = (Edge) originalView;
boolean sourceDuplicated = duplicateEdge.getSource() != null;
boolean targetDuplicated = duplicateEdge.getTarget() != null;
if (!sourceDuplicated) {
duplicateEdge.setSource(originalEdge.getSource());
}
if (!targetDuplicated) {
duplicateEdge.setTarget(originalEdge.getTarget());
}
}
if (duplicateView != null) {
duplicatedViewsToBeReturned.add(duplicateView);
}
}
return CommandResult.newOKCommandResult(duplicatedViewsToBeReturned);
}
/**
* Assign semantic elements (if there are any to add)
* to all children of a view down the view tree hierarchy
*
* @param view the view tree hierarchy root
*/
private void assignSementicElementsDownViewTree(View view) {
EObject originalElement = view.getElement();
if (originalElement != null) {
Object duplicateElement = duplicatedElements.get(originalElement);
if (duplicateElement != null) {
view.setElement((EObject) duplicateElement);
}
}
for (Iterator itr = view.getChildren().iterator(); itr.hasNext();) {
assignSementicElementsDownViewTree((View) itr.next());
}
}
}