blob: 1c7faac83bc71bc4b031607fd1fe7f2513730059 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2007 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.actions.internal;
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.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.Animation;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
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.actions.ActionIds;
import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsMessages;
import org.eclipse.gmf.runtime.diagram.ui.actions.internal.l10n.DiagramUIActionsPluginImages;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
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.ShapeCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.IEditableEditPart;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.diagram.ui.requests.ArrangeRequest;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.IWorkbenchPage;
/**
* The Arrange Action: arranges a container editpart or a set of selected editparts
*
* @author melaasar
* @canBeSeenBy %level1
*/
public class ArrangeAction extends DiagramAction {
private boolean selectionOnly;
/**
* @param workbenchPage
*/
protected ArrangeAction(
IWorkbenchPage workbenchPage,
boolean selectionOnly) {
super(workbenchPage);
this.selectionOnly = selectionOnly;
}
/* (non-Javadoc)
* @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createTargetRequest()
*/
protected Request createTargetRequest() {
return new ArrangeRequest(getId());
}
/* (non-Javadoc)
* @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#updateTargetRequest()
*/
protected void updateTargetRequest() {
ArrangeRequest request = (ArrangeRequest) getTargetRequest();
request.setPartsToArrange(getOperationSet());
}
private boolean isArrangeAll() {
return !selectionOnly;
}
protected Command getCommand() {
CompoundCommand arrangeCC = new CompoundCommand(getLabel());
if (isArrangeAll()) {
List elements = getOperationSet();
for (Iterator iter = elements.iterator(); iter.hasNext();) {
EditPart element = (EditPart) iter.next();
Command cmd = element.getCommand(getTargetRequest());
if (cmd != null)
arrangeCC.add(cmd);
}
} else if (getOperationSet().size() >= 2) {
EditPart parent = getSelectionParent(getOperationSet());
if (parent != null) {
Command cmd = parent.getCommand(getTargetRequest());
if (cmd != null)
arrangeCC.add(cmd);
}
}
return arrangeCC;
}
/**
* Action is enabled if arrange all. If arrange selection, action is enabled
* if the operation set's parent has XYLayout and there is atleast 2
* siblings to arrange
*
* @see org.eclipse.gef.ui.actions.EditorPartAction#calculateEnabled()
*/
protected boolean calculateEnabled() {
List operationSet = getOperationSet();
//arrange all, always enable
if( isArrangeAll() && !operationSet.isEmpty()){
return true;
}
EditPart parentEP = getSelectionParent(operationSet);
// bugzilla 156733: disable this action if the parent or selected edit parts are not editable
if ((parentEP instanceof IEditableEditPart)
&& !((IEditableEditPart) parentEP)
.isEditModeEnabled()) {
return false;
}
for (Iterator i = operationSet.iterator(); i.hasNext();) {
Object next = i.next();
if ((next instanceof IEditableEditPart)
&& !((IEditableEditPart) next)
.isEditModeEnabled()) {
return false;
}
}
//arrange selection
if (operationSet.size() >= 2) {
if (parentEP instanceof GraphicalEditPart) {
GraphicalEditPart parent = (GraphicalEditPart)parentEP;
if ((parent != null) &&(parent.getContentPane().getLayoutManager() instanceof XYLayout))
return true;
}
} else if (operationSet.size() == 1
&& operationSet.get(0) instanceof GroupEditPart) {
return true;
}
return false;
}
/*
* The operation set is the shapes, connections or both on the diagrm edit part
* (non-Javadoc)
* @see org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction#createOperationSet()
*/
protected List createOperationSet() {
List selection = getSelectedObjects();
if( isArrangeAll() ) {
if( !selection.isEmpty()){
return getElementsToArrange(selection);
}
if( getDiagramEditPart() != null )
return createOperationSet(getDiagramEditPart().getChildren());
return Collections.EMPTY_LIST;
}
if (selection.isEmpty() ||
!(selection.get(0) instanceof IGraphicalEditPart))
return Collections.EMPTY_LIST;
selection = ToolUtilities.getSelectionWithoutDependants(selection);
return createOperationSet(selection);
}
/**
* 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.
*/
private 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;
}
private List createOperationSet(List editparts) {
if (editparts == null || editparts.isEmpty())
return Collections.EMPTY_LIST;
EditPart parent;
if (editparts.size() == 1 && editparts.get(0) instanceof GroupEditPart) {
GroupEditPart groupEP = (GroupEditPart) editparts.get(0);
parent = groupEP;
editparts = groupEP.getChildren();
} else {
parent = getSelectionParent(editparts);
}
if (parent == null)
return Collections.EMPTY_LIST;
for (int i = 1; i < editparts.size(); i++) {
EditPart part = (EditPart) editparts.get(i);
if (part instanceof ConnectionEditPart){
continue;
}
if (part.getParent() != parent)
return Collections.EMPTY_LIST;
}
return editparts;
}
/* (non-Javadoc)
* @see org.eclipse.gmf.runtime.common.ui.action.AbstractActionHandler#isSelectionListener()
*/
protected boolean isSelectionListener() {
return true;
}
/**
* Creates the Arrange All action
* @param workbenchPage
*/
public static ArrangeAction createArrangeAllAction(IWorkbenchPage workbenchPage) {
ArrangeAction action = new ArrangeAction(workbenchPage,false);
action.setId(ActionIds.ACTION_ARRANGE_ALL);
action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionLabelText);
action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeAll_ActionToolTipText);
action
.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
action
.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
action
.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
return action;
}
/**
* Creates the Arrange All action for the toolbar menu
* @param workbenchPage
*/
public static ArrangeAction createToolbarArrangeAllAction(IWorkbenchPage workbenchPage) {
ArrangeAction action = new ArrangeAction(workbenchPage, false);
action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_ALL);
action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionLabelText);
action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeAll_ActionToolTipText);
action
.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
action
.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL_DISABLED);
action
.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_ALL);
return action;
}
/**
* Creates the Arrange Selection Only action
* @param workbenchPage
*/
public static ArrangeAction createArrangeSelectionAction(IWorkbenchPage workbenchPage) {
ArrangeAction action = new ArrangeAction(workbenchPage, true);
action.setId(ActionIds.ACTION_ARRANGE_SELECTION);
action.setText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionLabelText);
action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_ArrangeSelection_ActionToolTipText);
action
.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
action
.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
action
.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
return action;
}
/**
* Creates the Arrange Selection Only action for the toolbar menu
* @param workbenchPage
*/
public static ArrangeAction createToolbarArrangeSelectionAction(IWorkbenchPage workbenchPage) {
ArrangeAction action = new ArrangeAction(workbenchPage, true);
action.setId(ActionIds.ACTION_TOOLBAR_ARRANGE_SELECTION);
action.setText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionLabelText);
action.setToolTipText(DiagramUIActionsMessages.ArrangeAction_toolbar_ArrangeSelection_ActionToolTipText);
action
.setImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
action
.setDisabledImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED_DISABLED);
action
.setHoverImageDescriptor(DiagramUIActionsPluginImages.DESC_ARRANGE_SELECTED);
return action;
}
protected void doRun(IProgressMonitor progressMonitor) {
IPreferenceStore preferenceStore = (IPreferenceStore) getDiagramEditPart().getDiagramPreferencesHint().getPreferenceStore();
boolean animatedLayout = preferenceStore.getBoolean(
IPreferenceConstants.PREF_ENABLE_ANIMATED_LAYOUT);
if (animatedLayout)
Animation.markBegin();
super.doRun(progressMonitor);
if (animatedLayout) {
int durationInc = 800;
int factor = 10;
int size = 0;
List operationSet = getOperationSet();
if (isArrangeAll()){
for (Iterator iter = operationSet.iterator(); iter.hasNext();) {
IGraphicalEditPart element = (IGraphicalEditPart) iter.next();
size += element.getFigure().getChildren().size();
}
}
else if (operationSet != null && !operationSet.isEmpty()) {
IGraphicalEditPart container = (IGraphicalEditPart)getSelectionParent(operationSet);
size += container.getFigure().getChildren().size();
}
int totalDuration = Math.min(durationInc * factor / 2, Math.max(durationInc, (size /
factor) * durationInc));
Animation.run(totalDuration);
}
}
/**
* @param selection
* @return
*/
private List getElementsToArrange(List selection) {
Set parentsSet = new HashSet();
for (Iterator iter = selection.iterator(); iter.hasNext();) {
Object element = iter.next();
if (element instanceof ShapeCompartmentEditPart || element instanceof DiagramEditPart){
parentsSet.add(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(parentEditPart);
}
}
}
if (parentsSet.isEmpty())
return Collections.EMPTY_LIST;
List elements = new ArrayList();
elements.addAll(parentsSet);
return elements;
}
}