/*****************************************************************************
* Copyright (c) 2010 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:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.menu.actions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import org.eclipse.gef.ConnectionEditPart;
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.gef.tools.ToolUtilities;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
/**
* This action is used to arrange editparts on the diagram
* Copied from {@link ArrangeAction}
*
*
*/
public class ArrangeAction extends AbstractGraphicalParametricAction {
/** possible parameters for this action */
public static final String ARRANGE_ALL = "arrangeAll"; //$NON-NLS-1$
public static final String ARRANGE_SELECTION = "arrangeSelection"; //$NON-NLS-1$
/**
*
* Constructor.
*
* @param parameter
*/
public ArrangeAction(String parameter, List<IGraphicalEditPart> selection) {
super(parameter, selection);
}
/**
*
* @see org.eclipse.papyrus.uml.diagram.menu.actions.AbstractParametricAction#getBuildedCommand()
*
* @return
*/
@Override
protected Command getBuildedCommand() {
CompoundCommand command = new CompoundCommand("Arrange Command"); //$NON-NLS-1$
if(getParameter().equals(ARRANGE_ALL)) {
ArrangeRequest request = new ArrangeRequest("arrangeAllAction"); //$NON-NLS-1$
request.setPartsToArrange(createOperationSetForArrangeAll(getSelection()));
for(Iterator<IGraphicalEditPart> iter = getSelection().iterator(); iter.hasNext();) {
EditPart element = iter.next();
Command cmd = element.getCommand(request);
if(cmd != null && cmd.canExecute())
command.add(cmd);
}
} else if(getParameter().equals(ARRANGE_SELECTION)) {
ArrangeRequest request = new ArrangeRequest("arrangeSelectionAction"); //$NON-NLS-1$
request.setPartsToArrange(getSelection());
EditPart commonAncestor = getTargetEditPartForArrangeSelection(getSelection(), request);
if(commonAncestor != null) {
Command cmd = commonAncestor.getCommand(request);
if(cmd != null)
command.add(cmd);
}
}
return command.isEmpty() ? null : command;
}
/**
*
* Copied from {@link org.eclipse.gmf.runtime.diagram.ui.actions.internal.ArrangeAction}
*
* @param editparts
* the list of the selected editparts
* @param request
* the request to arrange the edit part
* @return
* the EditPart, which can arrange the selection
*/
@SuppressWarnings("restriction")
private EditPart getTargetEditPartForArrangeSelection(List<?> editparts, Request request) {
if(editparts.size() == 1) {
// If there is only one editpart selected, then the Arrange
// Selected request gets sent to this editpart's target editpart to
// allow clients to do as they wish.
return ((EditPart)editparts.get(0)).getTargetEditPart(request);
} else {
// If there is more than one editpart selected, then the Arrange
// Selected request gets sent to the common parent.
EditPart parentEP = getSelectionParent(editparts);
if(parentEP == null)
return null;
for(int i = 1; i < editparts.size(); i++) {
EditPart part = (EditPart)editparts.get(i);
if(part instanceof ConnectionEditPart) {
continue;
}
// if there is no common parent, then Arrange Selected isn't
// supported.
if(part.getParent() != parentEP)
return null;
}
return parentEP;
}
}
/**
*
* @see org.eclipse.papyrus.uml.diagram.menu.actions.AbstractParametricAction#isEnabled()
*
* @return
*/
@Override
public boolean isEnabled() {
//we don't need selection to do arrange all
if(getParameter().equals(ARRANGE_ALL)) {
return true;
}
return super.isEnabled();
}
/**
*
* Copied from {@link ArrangeAction} getSelectionParent Utility to return the logical parent of the selection
* list
*
* @param editparts
* List to parse for a common parent.
* @return EditPart that is the parent or null if a common parent doesn't
* exist.
*/
protected EditPart getSelectionParent(List<?> editparts) {
ListIterator<?> li = editparts.listIterator();
while(li.hasNext()) {
Object obj = li.next();
if(!(obj instanceof ConnectionEditPart) && obj instanceof EditPart) {
return ((EditPart)obj).getParent();
}
}
return null;
}
/**
* @param selection
* @return the selection for the arrange all command
*/
@SuppressWarnings("unchecked")
protected List<IGraphicalEditPart> createOperationSetForArrangeAll(List<IGraphicalEditPart> selection) {
Set<IGraphicalEditPart> parentsSet = new HashSet<IGraphicalEditPart>();
for(Iterator<IGraphicalEditPart> iter = selection.iterator(); iter.hasNext();) {
Object element = iter.next();
if(element instanceof ShapeCompartmentEditPart || element instanceof DiagramEditPart) {
parentsSet.add((IGraphicalEditPart)element);
} else if(element instanceof EditPart) {
EditPart gEditPart = (EditPart)element;
EditPart parentEditPart = gEditPart.getParent();
if(parentEditPart instanceof ShapeCompartmentEditPart || parentEditPart instanceof DiagramEditPart) {
if(!parentsSet.contains(parentEditPart))
parentsSet.add((IGraphicalEditPart)parentEditPart);
}
}
}
if(parentsSet.isEmpty()) {
return Collections.EMPTY_LIST;
}
List<IGraphicalEditPart> elements = new ArrayList<IGraphicalEditPart>();
elements.addAll(parentsSet);
return elements;
}
/**
*
* @see org.eclipse.papyrus.uml.diagram.menu.actions.AbstractParametricAction#getSelection()
*
* @return
*/
@SuppressWarnings("unchecked")
@Override
protected List<IGraphicalEditPart> getSelection() {
List<IGraphicalEditPart> selection = super.getSelection();
if(ArrangeAction.ARRANGE_ALL.equals(getParameter())) {
if(!selection.isEmpty()) {
return createOperationSetForArrangeAll(selection);
}
if(getDiagramEditPart() != null) {
return getDiagramEditPart().getChildren();
}
return Collections.EMPTY_LIST;
} else {
// this is the case of Arrange Selection
if(selection.isEmpty() || !(selection.get(0) instanceof IGraphicalEditPart))
return Collections.EMPTY_LIST;
selection = ToolUtilities.getSelectionWithoutDependants(selection);
return selection;
}
}
}