blob: a0e7bd9a92ba88ebbdf6844ae967a970dd43391e [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2005, 2019 SAP SE
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* SAP SE - initial API, implementation and documentation
* mwenz - Bug 520392 - Hard coded error message when entering an empty string in direct editing
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.graphiti.examples.tutorial.diagram;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.examples.tutorial.TutorialImageProvider;
import org.eclipse.graphiti.examples.tutorial.features.TutorialCollapseDummyFeature;
import org.eclipse.graphiti.examples.tutorial.features.TutorialDirectEditEClassFeature;
import org.eclipse.graphiti.examples.tutorial.features.TutorialRenameEClassFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IDirectEditingFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.features.context.IDirectEditingContext;
import org.eclipse.graphiti.features.context.IDoubleClickContext;
import org.eclipse.graphiti.features.context.IPictogramElementContext;
import org.eclipse.graphiti.features.context.impl.CreateConnectionContext;
import org.eclipse.graphiti.features.context.impl.CustomContext;
import org.eclipse.graphiti.features.custom.ICustomFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.AnchorContainer;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.palette.IPaletteCompartmentEntry;
import org.eclipse.graphiti.palette.impl.ConnectionCreationToolEntry;
import org.eclipse.graphiti.palette.impl.ObjectCreationToolEntry;
import org.eclipse.graphiti.palette.impl.PaletteCompartmentEntry;
import org.eclipse.graphiti.palette.impl.StackEntry;
import org.eclipse.graphiti.platform.IPlatformImageConstants;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.tb.ContextButtonEntry;
import org.eclipse.graphiti.tb.ContextEntryHelper;
import org.eclipse.graphiti.tb.ContextMenuEntry;
import org.eclipse.graphiti.tb.DefaultToolBehaviorProvider;
import org.eclipse.graphiti.tb.IContextButtonEntry;
import org.eclipse.graphiti.tb.IContextButtonPadData;
import org.eclipse.graphiti.tb.IContextMenuEntry;
import org.eclipse.graphiti.tb.IDecorator;
import org.eclipse.graphiti.tb.ImageDecorator;
public class TutorialToolBehaviorProvider extends DefaultToolBehaviorProvider {
public TutorialToolBehaviorProvider(IDiagramTypeProvider dtp) {
super(dtp);
}
@Override
public IContextButtonPadData getContextButtonPad(IPictogramElementContext context) {
IContextButtonPadData data = super.getContextButtonPad(context);
PictogramElement pe = context.getPictogramElement();
// 1. set the generic context buttons
// note, that we do not add 'remove' (just as an example)
setGenericContextButtons(data, pe, CONTEXT_BUTTON_DELETE | CONTEXT_BUTTON_UPDATE);
// 2. set the collapse button
// simply use a dummy custom feature (senseless example)
CustomContext cc = new CustomContext(new PictogramElement[] { pe });
ICustomFeature[] cf = getFeatureProvider().getCustomFeatures(cc);
for (int i = 0; i < cf.length; i++) {
ICustomFeature iCustomFeature = cf[i];
if (iCustomFeature instanceof TutorialCollapseDummyFeature) {
IContextButtonEntry collapseButton = ContextEntryHelper.createCollapseContextButton(true, iCustomFeature, cc);
data.setCollapseContextButton(collapseButton);
break;
}
}
// 3. add one domain specific context-button, which offers all
// available connection-features as drag&drop features...
// 3.a. create new CreateConnectionContext
CreateConnectionContext ccc = new CreateConnectionContext();
ccc.setSourcePictogramElement(pe);
Anchor anchor = null;
if (pe instanceof Anchor) {
anchor = (Anchor) pe;
} else if (pe instanceof AnchorContainer) {
// assume, that our shapes always have chopbox anchors
anchor = Graphiti.getPeService().getChopboxAnchor((AnchorContainer) pe);
}
ccc.setSourceAnchor(anchor);
// 3.b. create context button and add all applicable features
ContextButtonEntry button = new ContextButtonEntry(null, context);
button.setText("Create connection"); //$NON-NLS-1$
button.setIconId(TutorialImageProvider.IMG_EREFERENCE);
ICreateConnectionFeature[] features = getFeatureProvider().getCreateConnectionFeatures();
for (ICreateConnectionFeature feature : features) {
if (feature.isAvailable(ccc) && feature.canStartConnection(ccc))
button.addDragAndDropFeature(feature);
}
// 3.c. add context button, if it contains at least one feature
if (button.getDragAndDropFeatures().size() > 0) {
data.getDomainSpecificContextButtons().add(button);
}
return data;
}
@Override
public IContextMenuEntry[] getContextMenu(ICustomContext context) {
// create a sub-menu for all custom features
ContextMenuEntry subMenu = new ContextMenuEntry(null, context);
subMenu.setText("Cu&stom"); //$NON-NLS-1$
subMenu.setDescription("Custom features submenu"); //$NON-NLS-1$
// display sub-menu hierarchical or flat
subMenu.setSubmenu(true);
// create a menu-entry in the sub-menu for each custom feature
ICustomFeature[] customFeatures = getFeatureProvider().getCustomFeatures(context);
for (int i = 0; i < customFeatures.length; i++) {
ICustomFeature customFeature = customFeatures[i];
if (customFeature.isAvailable(context)) {
ContextMenuEntry menuEntry = new ContextMenuEntry(customFeature, context);
subMenu.add(menuEntry);
}
}
IContextMenuEntry ret[] = new IContextMenuEntry[] { subMenu };
return ret;
}
@Override
public IPaletteCompartmentEntry[] getPalette() {
List<IPaletteCompartmentEntry> ret = new ArrayList<IPaletteCompartmentEntry>();
// add compartments from super class
IPaletteCompartmentEntry[] superCompartments = super.getPalette();
for (int i = 0; i < superCompartments.length; i++)
ret.add(superCompartments[i]);
// add new compartment at the end of the existing compartments
PaletteCompartmentEntry compartmentEntry = new PaletteCompartmentEntry("Stacked", null); //$NON-NLS-1$
ret.add(compartmentEntry);
// add new stack entry to new compartment
StackEntry stackEntry = new StackEntry("EObject", "EObject", null); //$NON-NLS-1$ //$NON-NLS-2$
compartmentEntry.addToolEntry(stackEntry);
// add all create-features to the new stack-entry
IFeatureProvider featureProvider = getFeatureProvider();
ICreateFeature[] createFeatures = featureProvider.getCreateFeatures();
for (ICreateFeature cf : createFeatures) {
ObjectCreationToolEntry objectCreationToolEntry = new ObjectCreationToolEntry(cf.getCreateName(), cf.getCreateDescription(),
cf.getCreateImageId(), cf.getCreateLargeImageId(), cf);
stackEntry.addCreationToolEntry(objectCreationToolEntry);
}
// add all create-connection-features to the new stack-entry
ICreateConnectionFeature[] createConnectionFeatures = featureProvider.getCreateConnectionFeatures();
for (ICreateConnectionFeature cf : createConnectionFeatures) {
ConnectionCreationToolEntry connectionCreationToolEntry = new ConnectionCreationToolEntry(cf.getCreateName(),
cf.getCreateDescription(), cf.getCreateImageId(), cf.getCreateLargeImageId());
connectionCreationToolEntry.addCreateConnectionFeature(cf);
stackEntry.addCreationToolEntry(connectionCreationToolEntry);
}
return ret.toArray(new IPaletteCompartmentEntry[ret.size()]);
}
@Override
public ICustomFeature getDoubleClickFeature(IDoubleClickContext context) {
ICustomFeature customFeature = new TutorialRenameEClassFeature(getFeatureProvider());
// canExecute() tests especially if the context contains a EClass
if (customFeature.canExecute(context)) {
return customFeature;
}
return super.getDoubleClickFeature(context);
}
@Override
public IDecorator[] getDecorators(PictogramElement pe) {
IFeatureProvider featureProvider = getFeatureProvider();
Object bo = featureProvider.getBusinessObjectForPictogramElement(pe);
if (bo instanceof EClass) {
EClass eClass = (EClass) bo;
String name = eClass.getName();
if (name != null && name.length() > 0 && !(name.charAt(0) >= 'A' && name.charAt(0) <= 'Z')) {
IDecorator imageRenderingDecorator = new ImageDecorator(IPlatformImageConstants.IMG_ECLIPSE_WARNING_TSK);
imageRenderingDecorator.setMessage("Name should start with upper case letter"); //$NON-NLS-1$
return new IDecorator[] { imageRenderingDecorator };
}
}
return super.getDecorators(pe);
}
@Override
public GraphicsAlgorithm[] getClickArea(PictogramElement pe) {
IFeatureProvider featureProvider = getFeatureProvider();
Object bo = featureProvider.getBusinessObjectForPictogramElement(pe);
if (bo instanceof EClass) {
GraphicsAlgorithm invisible = pe.getGraphicsAlgorithm();
GraphicsAlgorithm rectangle = invisible.getGraphicsAlgorithmChildren().get(0);
return new GraphicsAlgorithm[] { rectangle };
}
return super.getClickArea(pe);
}
@Override
public GraphicsAlgorithm getSelectionBorder(PictogramElement pe) {
if (pe instanceof ContainerShape) {
GraphicsAlgorithm invisible = pe.getGraphicsAlgorithm();
if (!invisible.getLineVisible()) {
EList<GraphicsAlgorithm> graphicsAlgorithmChildren = invisible.getGraphicsAlgorithmChildren();
if (!graphicsAlgorithmChildren.isEmpty()) {
return graphicsAlgorithmChildren.get(0);
}
}
}
return super.getSelectionBorder(pe);
}
@Override
public Object getToolTip(GraphicsAlgorithm ga) {
PictogramElement pe = ga.getPictogramElement();
Object bo = getFeatureProvider().getBusinessObjectForPictogramElement(pe);
if (bo instanceof EClass) {
String name = ((EClass) bo).getName();
if (name != null && !(name.length() == 0)) {
return name;
}
}
return super.getToolTip(ga);
}
@Override
public String getDirectEditingInvalidNotificationTitle(IDirectEditingFeature feature,
IDirectEditingContext context) {
if (feature instanceof TutorialDirectEditEClassFeature) {
return "Cannot change name of EClass";
} else {
return super.getDirectEditingInvalidNotificationTitle(feature, context);
}
}
}