blob: 2389563c1b62cc8538f8b183b7f0ea96e6b3566b [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2012 SAP AG.
* 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:
* SAP AG - initial API, implementation and documentation
* mwenz - Bug 323155 - Check usage scenarios for DefaultPrintFeature and
* DefaultSaveImageFeature
* mwenz - Bug 339525 - Enrich paste context with location information
* Bug 336488 - DiagramEditor API
* Benjamin Schmeling - mwenz - Bug 367483 - Support composite connections
* cbrand - Bug 377783 - Dump for figures in connection layer needed
* fvelasco - Bug 396247 - ImageDescriptor changes
* pjpaulin - Bug 352120 - Add certain menu options only if local transaction
* pjpaulin - Bug 352120 - Now uses IDiagramContainerUI interface
*
* </copyright>
*
*******************************************************************************/
package org.eclipse.graphiti.ui.editor;
import java.util.List;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.features.IFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IPrintFeature;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.features.context.impl.CustomContext;
import org.eclipse.graphiti.features.custom.ICustomFeature;
import org.eclipse.graphiti.internal.pref.GFPreferences;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.pictograms.CompositeConnection;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.tb.ContextMenuEntry;
import org.eclipse.graphiti.tb.IContextMenuEntry;
import org.eclipse.graphiti.tb.IToolBehaviorProvider;
import org.eclipse.graphiti.ui.internal.Messages;
import org.eclipse.graphiti.ui.internal.action.CustomAction;
import org.eclipse.graphiti.ui.internal.action.DeleteAction;
import org.eclipse.graphiti.ui.internal.action.IAvailable;
import org.eclipse.graphiti.ui.internal.action.RemoveAction;
import org.eclipse.graphiti.ui.internal.action.SaveImageAction;
import org.eclipse.graphiti.ui.internal.action.UpdateAction;
import org.eclipse.graphiti.ui.internal.feature.DebugFeature;
import org.eclipse.graphiti.ui.internal.parts.CompositeConnectionEditPart;
import org.eclipse.graphiti.ui.platform.IConfigurationProvider;
import org.eclipse.graphiti.ui.services.GraphitiUi;
import org.eclipse.graphiti.util.ILocationInfo;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.ActionFactory;
/**
* Provides a standard-context-menu and adds it to the given EditPartViewer.
* Another feature is, that it can set the menu-location to all Actions.
* <p>
* Some of the standard-menu-items are: undo/redo, delete, copy/paste,
* alignment, zooming.
*
*/
public class DiagramEditorContextMenuProvider extends ContextMenuProvider {
private final ActionRegistry actionRegistry;
private final IConfigurationProvider configurationProvider;
/**
* Creates a new DiagramEditorContextMenuProvider.
*
* @param viewer
* The EditPartViewer, for which the context-menu shall be
* displayed.
* @param registry
* The action-registry, which contains the actions corresponding
* to the menu-items.
* @param configurationProvider
* the configuration provider
* @since 0.10
*/
public DiagramEditorContextMenuProvider(EditPartViewer viewer, ActionRegistry registry,
IConfigurationProvider configurationProvider) {
super(viewer);
if (registry == null) {
throw new IllegalArgumentException("Argument registry must not be null"); //$NON-NLS-1$
}
this.actionRegistry = registry;
if (configurationProvider == null) {
throw new IllegalArgumentException("Argument configurationProvider must not be null"); //$NON-NLS-1$
}
this.configurationProvider = configurationProvider;
}
/**
* Adds the Actions to the given IMenuManager, which is displayed as a
* context-menu.
*
* @param manager
* the manager
* @see ContextMenuProvider#buildContextMenu(IMenuManager)
*/
@Override
public void buildContextMenu(IMenuManager manager) {
GEFActionConstants.addStandardActionGroups(manager);
addDefaultMenuGroupUndo(manager);
addDefaultMenuGroupSave(manager);
addDefaultMenuGroupEdit(manager);
addDefaultMenuGroupPrint(manager);
addDefaultMenuGroupRest(manager);
}
// ====================== add default menu-groups =========================
/**
* Adds the default menu group undo.
*
* @param manager
* the manager
*/
protected void addDefaultMenuGroupUndo(IMenuManager manager) {
addActionToMenu(manager, ActionFactory.UNDO.getId(), GEFActionConstants.GROUP_UNDO);
addActionToMenu(manager, ActionFactory.REDO.getId(), GEFActionConstants.GROUP_UNDO);
}
/**
* Adds the default menu group save.
*
* @param manager
* the manager
*/
protected void addDefaultMenuGroupSave(IMenuManager manager) {
addActionToMenu(manager, SaveImageAction.ACTION_ID, GEFActionConstants.GROUP_SAVE);
}
/**
* Adds the default menu group edit.
*
* @param manager
* the manager
*/
protected void addDefaultMenuGroupEdit(IMenuManager manager) {
addActionToMenuIfAvailable(manager, ActionFactory.COPY.getId(), GEFActionConstants.GROUP_EDIT);
addActionToMenuIfAvailable(manager, ActionFactory.PASTE.getId(), GEFActionConstants.GROUP_EDIT);
}
/**
* Adds the default menu group print.
*
* @param manager
* the manager
*/
protected void addDefaultMenuGroupPrint(IMenuManager manager) {
IFeatureProvider fp = configurationProvider.getDiagramTypeProvider().getFeatureProvider();
if (fp != null) {
IPrintFeature pf = fp.getPrintFeature();
if (pf != null) {
addActionToMenu(manager, ActionFactory.PRINT.getId(), GEFActionConstants.GROUP_PRINT);
}
}
}
/**
* Adds the default menu group rest.
*
* @param manager
* the manager
*/
protected void addDefaultMenuGroupRest(IMenuManager manager) {
addAlignmentSubMenu(manager, GEFActionConstants.GROUP_REST);
addActionToMenuIfAvailable(manager, UpdateAction.ACTION_ID, GEFActionConstants.GROUP_REST);
addActionToMenuIfAvailable(manager, RemoveAction.ACTION_ID, GEFActionConstants.GROUP_REST);
addActionToMenuIfAvailable(manager, DeleteAction.ACTION_ID, GEFActionConstants.GROUP_REST);
PictogramElement pes[] = getEditor().getSelectedPictogramElements();
ICustomContext context = new CustomContext(pes);
boolean diagramSelected = false;
if (pes.length == 1) {
extendCustomContext(pes[0], (CustomContext) context);
if (pes[0] instanceof Diagram) {
diagramSelected = true;
}
}
IToolBehaviorProvider tb = configurationProvider.getDiagramTypeProvider().getCurrentToolBehaviorProvider();
IContextMenuEntry[] contextMenuEntries = tb.getContextMenu(context);
if (GFPreferences.getInstance().areDebugActionsActive()) {
IFeatureProvider fp = configurationProvider.getDiagramTypeProvider().getFeatureProvider();
ContextMenuEntry debugEntry = new ContextMenuEntry(null, context);
debugEntry.setText("Debug"); //$NON-NLS-1$
debugEntry.setSubmenu(true);
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp, DebugFeature.TYPE_DUMP_FIGURE_DATA), context));
if (diagramSelected) {
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp,
DebugFeature.TYPE_DUMP_FIGURE_INCL_CONNECTION_DATA), context));
}
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp, DebugFeature.TYPE_DUMP_PICTOGRAM_DATA), context));
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp, DebugFeature.TYPE_DUMP_EDIT_PART_DATA), context));
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp, DebugFeature.TYPE_DUMP_ALL), context));
debugEntry.add(new ContextMenuEntry(new DebugFeature(fp, DebugFeature.TYPE_REFRESH), context));
IContextMenuEntry[] contextMenuEntries2 = new IContextMenuEntry[contextMenuEntries.length + 1];
System.arraycopy(contextMenuEntries, 0, contextMenuEntries2, 0, contextMenuEntries.length);
contextMenuEntries2[contextMenuEntries2.length - 1] = debugEntry;
contextMenuEntries = contextMenuEntries2;
}
addEntries(manager, contextMenuEntries, context, GEFActionConstants.GROUP_REST, null);
}
private void addEntries(IMenuManager manager, IContextMenuEntry[] contextMenuEntries, ICustomContext context, String groupID,
String textParentEntry) {
for (int i = 0; i < contextMenuEntries.length; i++) {
IContextMenuEntry cmEntry = contextMenuEntries[i];
String text = cmEntry.getText();
if (cmEntry.getChildren().length == 0) {
IFeature feature = cmEntry.getFeature();
if (feature instanceof ICustomFeature && feature.isAvailable(context)) {
IAction action = new CustomAction((ICustomFeature) feature, context,
configurationProvider.getDiagramBehavior());
if (textParentEntry != null) {
text = textParentEntry + " " + text; //$NON-NLS-1$
}
action.setText(text);
action.setDescription(cmEntry.getDescription());
ImageDescriptor image = GraphitiUi.getImageService().getImageDescriptorForId(
configurationProvider.getDiagramTypeProvider().getProviderId(), cmEntry.getIconId());
action.setImageDescriptor(image);
appendContributionItem(manager, groupID, new ActionContributionItem(action));
}
} else {
if (cmEntry.isSubmenu()) {
MenuManager subMenu = new MenuManager(text);
addEntries(subMenu, cmEntry.getChildren(), context, null, null);
if (!subMenu.isEmpty()) {
appendContributionItem(manager, groupID, subMenu);
}
} else {
appendContributionItem(manager, groupID, new Separator());
addEntries(manager, cmEntry.getChildren(), context, groupID, text);
appendContributionItem(manager, groupID, new Separator());
}
}
}
}
private void appendContributionItem(IMenuManager manager, String groupID, IContributionItem contributionItem) {
if (groupID != null) {
manager.appendToGroup(groupID, contributionItem);
} else {
manager.add(contributionItem);
}
}
// ====================== add single menu-entries =========================
private void extendCustomContext(PictogramElement pe, CustomContext context) {
Point location = getEditor().getMouseLocation();
int mX = location.x;
int mY = location.y;
context.setX(mX);
context.setY(mY);
if (pe instanceof Shape && !(pe instanceof Diagram)) {
GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
if (ga != null) {
ILocation relLocation = Graphiti.getPeService().getLocationRelativeToDiagram((Shape) pe);
int x = relLocation.getX();
int y = relLocation.getY();
int width = ga.getWidth();
int height = ga.getHeight();
if (mX > x && mX < x + width && mY > y && mY < y + height) {
int relativeX = mX - x;
int relativeY = mY - y;
ILocationInfo locationInfo = Graphiti.getLayoutService().getLocationInfo((Shape) pe, relativeX, relativeY);
context.setInnerPictogramElement(locationInfo.getShape());
context.setInnerGraphicsAlgorithm(locationInfo.getGraphicsAlgorithm());
}
}
} else if (pe instanceof CompositeConnection) {
List<?> selectedEditParts = getViewer().getSelectedEditParts();
for (Object object : selectedEditParts) {
if (object instanceof CompositeConnectionEditPart) {
// Retrieve child selection info from the edit part
CompositeConnectionEditPart compEditPart = (CompositeConnectionEditPart) object;
org.eclipse.graphiti.ui.internal.parts.ConnectionEditPart originallySelectedChildConnection = compEditPart
.getOriginallySelectedChild();
if (originallySelectedChildConnection != null) {
// and provide the originally selection child connection
// as inner PE
Connection connectionPicto = (Connection) originallySelectedChildConnection.getModel();
context.setInnerGraphicsAlgorithm(connectionPicto.getGraphicsAlgorithm());
context.setInnerPictogramElement(connectionPicto);
}
}
}
}
}
/**
* Adds the alignment sub menu.
*
* @param manager
* the manager
* @param group
* the group
*/
protected void addAlignmentSubMenu(IMenuManager manager, String group) {
IAction action;
MenuManager alignmentSubMenu = new MenuManager(Messages.GraphicsContextMenuProvider_0_xmen);
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_LEFT);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_CENTER);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_RIGHT);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_TOP);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_MIDDLE);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.ALIGN_BOTTOM);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.MATCH_WIDTH);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
action = this.actionRegistry.getAction(GEFActionConstants.MATCH_HEIGHT);
if (action != null && action.isEnabled()) {
alignmentSubMenu.add(action);
}
if (!alignmentSubMenu.isEmpty()) {
manager.appendToGroup(group, alignmentSubMenu);
}
}
/**
* Adds the action to menu.
*
* @param manager
* the manager
* @param actionId
* the action id
* @param menuGroup
* the menu group
*/
protected void addActionToMenu(IMenuManager manager, String actionId, String menuGroup) {
IAction action;
action = this.actionRegistry.getAction(actionId);
if (action != null && action.isEnabled()) {
manager.appendToGroup(menuGroup, action);
}
}
/**
* Adds the action to menu if available.
*
* @param manager
* the manager
* @param actionId
* the action id
* @param menuGroup
* the menu group
*/
protected void addActionToMenuIfAvailable(IMenuManager manager, String actionId, String menuGroup) {
IAction action = this.actionRegistry.getAction(actionId);
if (action instanceof IAvailable) {
if (((IAvailable) action).isAvailable()) {
manager.appendToGroup(menuGroup, action);
// For Update Actions we have to trigger a refresh of the
// enablement, also if no selection change occurred:
//e.g. update was triggered, then update has to be disabled.
if (action instanceof UpdateAction) {
UpdateAction updateAction = (UpdateAction) action;
updateAction.setEnabled(updateAction.isEnabled());
}
}
}
}
@Override
protected boolean allowItem(IContributionItem itemToAdd) {
boolean ret = super.allowItem(itemToAdd);
if (ret) {
String itemId = itemToAdd.getId();
if (itemId != null) {
if (itemId.startsWith("org.eclipse.debug.ui.contextualLaunch.")) { //$NON-NLS-1$
return false;
}
}
}
return ret;
}
private DiagramBehavior getEditor() {
return configurationProvider.getDiagramBehavior();
}
}