blob: 71a5f88d51a6acc547da0ab128d8903f9e010b43 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2012 Red Hat, Inc.
* All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.bpmn2.modeler.core.features;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.modeler.core.model.ModelDecorator;
import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskImageProvider;
import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskImageProvider.IconSize;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.graphiti.IExecutionInfo;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IDirectEditingFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.ILayoutFeature;
import org.eclipse.graphiti.features.IMoveShapeFeature;
import org.eclipse.graphiti.features.IRemoveFeature;
import org.eclipse.graphiti.features.IResizeShapeFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.IAreaContext;
import org.eclipse.graphiti.features.context.ICreateContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.custom.ICustomFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Image;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.osgi.util.NLS;
/**
* The Feature Container for Custom Shapes.
* <p>
* This class must be extended by contributing plug-ins that want to extend any
* of the BPMN2 shape elements, e.g. {@link org.eclipse.bpmn2.Task}, {@link org.eclipse.bpmn2.Gateway},
* {@link org.eclipse.bpmn2.Event}, etc.
* <p>
* See the {@code <customTask>} element of the
* {@code org.eclipse.bpmn2.modeler.runtime} extension point.
*/
public class CustomShapeFeatureContainer extends CustomElementFeatureContainer implements IShapeFeatureContainer {
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getDescription()
*/
public String getDescription() {
if (customTaskDescriptor!=null)
return customTaskDescriptor.getDescription();
return Messages.CustomShapeFeatureContainer_Description;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#createFeatureContainer(org.eclipse.graphiti.features.IFeatureProvider)
*/
protected IFeatureContainer createFeatureContainer(IFeatureProvider fp) {
EClass eClass = (EClass) ModelDecorator.findEClassifier(
customTaskDescriptor.getRuntime().getModelDescriptor().getEPackage(), customTaskDescriptor.getType());
return ((IBpmn2FeatureProvider)fp).getFeatureContainer(eClass.getInstanceClass());
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getFeatureContainer(org.eclipse.graphiti.features.IFeatureProvider)
*/
protected IFeatureContainer getFeatureContainer(IFeatureProvider fp) {
if (featureContainerDelegate==null) {
featureContainerDelegate = createFeatureContainer(fp);
}
return featureContainerDelegate;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IShapeFeatureContainer#getCreateFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public ICreateFeature getCreateFeature(IFeatureProvider fp) {
return new CreateCustomShapeFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getAddFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IAddFeature getAddFeature(IFeatureProvider fp) {
return new AddCustomShapeFeature(fp);
}
/**
* Base class for Custom Shape Feature construction.
* <p>
* Custom Connections contributed to the editor <b>MUST</b> subclass this in
* their FeatureContainer implementation.
* <p>
* This class is intended for creation of BPMN2 objects that have custom model
* extensions. This is for any object considered to be a "shape", e.g. Activities,
* Data Objects, Gateways, Events, etc.
* <p>
* The creation process copies the modelObject ID string into the Graphiti create
* context during the construction phase, then migrates that ID into the created
* PictogramElement. This is necessary because the ID must be associated with the
* PE to allow our BPMNFeatureProvider to correctly identify the Custom Task.
*/
public class CreateCustomShapeFeature extends AbstractBpmn2CreateFeature<BaseElement> {
/** The create feature delegate. */
protected AbstractBpmn2CreateFeature<BaseElement> createFeatureDelegate;
/** Our own copies of create name and description because the ones in super are private **/
protected String name;
protected String description;
/**
* Instantiates a new {@code CreateFeature} for custom shapes. If the
* name and/or description are null or empty strings then they are
* fetched from the Create Feature delegate when required.
*
* @param fp the Feature Provider
* @param name the name of the element being created
* @param description the description of the Create Feature
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public CreateCustomShapeFeature(IFeatureProvider fp, String name, String description) {
super(fp);
IShapeFeatureContainer fc = (IShapeFeatureContainer)getFeatureContainer(fp);
createFeatureDelegate = (AbstractBpmn2CreateFeature)fc.getCreateFeature(fp);
Assert.isNotNull(createFeatureDelegate);
this.name = name;
this.description = description;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2CreateFeature#getCreateName()
*/
@Override
public String getCreateName() {
if (name!=null && !name.isEmpty())
return name;
return createFeatureDelegate.getCreateName();
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2CreateFeature#getCreateDescription()
*/
@Override
public String getCreateDescription() {
if (description!=null && !description.isEmpty())
return description;
return createFeatureDelegate.getCreateDescription();
}
/**
* Alternate constructor.
*
* @param fp the Feature Provider
*/
public CreateCustomShapeFeature(IFeatureProvider fp) {
this(fp, customTaskDescriptor.getName(),
NLS.bind(Messages.CustomElementFeatureContainer_Create, customTaskDescriptor.getName()));
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.features.impl.AbstractFeature#addGraphicalRepresentation(org.eclipse.graphiti.features.context.IAreaContext, java.lang.Object)
*/
@Override
protected PictogramElement addGraphicalRepresentation(IAreaContext context, Object newObject) {
// create a new AddContext and copy our ID into it.
IAddContext addContext = new AddContext(context, newObject);
setId(addContext, getId());
// create the PE and copy our ID into its properties.
PictogramElement pe = getFeatureProvider().addIfPossible(addContext);
FeatureSupport.setPropertyValue(pe,GraphitiConstants.CUSTOM_ELEMENT_ID,id);
return pe;
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.func.ICreate#canCreate(org.eclipse.graphiti.features.context.ICreateContext)
*/
@Override
public boolean canCreate(ICreateContext context) {
// copy our ID into the CreateContext - this is where it all starts!
setId(context, id);
return createFeatureDelegate.canCreate(context);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2CreateFeature#createBusinessObject(org.eclipse.graphiti.features.context.ICreateContext)
*/
@Override
public BaseElement createBusinessObject(ICreateContext context) {
BaseElement businessObject = createFeatureDelegate.createBusinessObject(context);
return businessObject;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractCreateFlowElementFeature#getFlowElementClass()
*/
@Override
public EClass getBusinessObjectClass() {
return createFeatureDelegate.getBusinessObjectClass();
}
/**
* This delegates to the CreateFeature implementation defined by the
* extension plugin. Note that the create() method of this delegate MUST
* return an array of two objects: the first object is the BPMN2
* element, the second object is the ContainerShape that is the
* graphical representation of that element.
*
* @see org.eclipse.graphiti.func.ICreate#create(org.eclipse.graphiti.features.context.ICreateContext)
*/
@Override
public Object[] create(ICreateContext context) {
// Our Custom Task ID should have already been set in canCreate()
// if not, we have a problem; in other words, canCreate() MUST have
// been called by the framework before create()
Assert.isNotNull(getId(context));
return createFeatureDelegate.create(context);
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.features.impl.AbstractCreateFeature#getCreateImageId()
*/
@Override
public String getCreateImageId() {
String icon = customTaskDescriptor.getIcon();
if (icon!=null) {
String id = customTaskDescriptor.getImageId(icon, IconSize.SMALL);
if (id!=null)
return id;
}
return createFeatureDelegate.getCreateImageId();
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.features.impl.AbstractCreateFeature#getCreateLargeImageId()
*/
@Override
public String getCreateLargeImageId() {
String icon = customTaskDescriptor.getIcon();
if (icon!=null) {
String id = customTaskDescriptor.getImageId(icon, IconSize.LARGE);
if (id!=null)
return id;
}
return createFeatureDelegate.getCreateLargeImageId();
}
}
/**
* The {@code AddFeature} base class for creating custom shapes.
* <p>
* Custom shapes contributed to the editor <b>MUST</b> subclass this in
* their FeatureContainer implementation.
*/
public class AddCustomShapeFeature extends AbstractBpmn2AddFeature<BaseElement> {
/** The add feature delegate. */
protected AbstractBpmn2AddFeature<BaseElement> addFeatureDelegate;
/**
* Instantiates a new {@code AddConnectionFeature} for custom connections.
*
* @param fp the Feature Provider
*/
public AddCustomShapeFeature(IFeatureProvider fp) {
super(fp);
addFeatureDelegate = (AbstractBpmn2AddFeature)getFeatureContainer(fp).getAddFeature(fp);
Assert.isNotNull(addFeatureDelegate);
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.func.IAdd#add(org.eclipse.graphiti.features.context.IAddContext)
*/
@Override
public PictogramElement add(IAddContext context) {
PictogramElement pe = addFeatureDelegate.add(context);
// make sure everyone knows that this PE is a custom task
if (pe!=null)
FeatureSupport.setPropertyValue(pe,GraphitiConstants.CUSTOM_ELEMENT_ID,getId());
// add an icon to the top-left corner if applicable, and if the implementing
// addFeatureDelegate hasn't already done so.
String icon = customTaskDescriptor.getIcon();
if (icon!=null && pe instanceof ContainerShape) {
boolean addImage = true;
ContainerShape containerShape = (ContainerShape)pe;
GraphicsAlgorithm ga = (GraphicsAlgorithm)AbstractBpmn2AddFeature.getGraphicsAlgorithm(containerShape);
for (PictogramElement child : containerShape.getChildren()) {
if (child.getGraphicsAlgorithm() instanceof Image) {
addImage = false;
break;
}
}
if (ga!=null) {
for (GraphicsAlgorithm g : ga.getGraphicsAlgorithmChildren()) {
if (g instanceof Image) {
addImage = false;
break;
}
}
}
else
addImage = false;
if (addImage) {
Image img = CustomTaskImageProvider.createImage(customTaskDescriptor, ga, icon, 24, 24);
Graphiti.getGaService().setLocationAndSize(img, 2, 2, 24, 24);
}
}
return pe;
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IBpmn2AddFeature#getBusinessObject(org.eclipse.graphiti.features.context.IAddContext)
*/
@Override
public BaseElement getBusinessObject(IAddContext context) {
// TODO Auto-generated method stub
return addFeatureDelegate.getBusinessObject(context);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IBpmn2AddFeature#putBusinessObject(org.eclipse.graphiti.features.context.IAddContext, org.eclipse.emf.ecore.EObject)
*/
@Override
public void putBusinessObject(IAddContext context, BaseElement businessObject) {
addFeatureDelegate.putBusinessObject(context, businessObject);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IBpmn2AddFeature#postExecute(org.eclipse.graphiti.IExecutionInfo)
*/
@Override
public void postExecute(IExecutionInfo executionInfo) {
addFeatureDelegate.postExecute(executionInfo);
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.func.IAdd#canAdd(org.eclipse.graphiti.features.context.IAddContext)
*/
@Override
public boolean canAdd(IAddContext context) {
return addFeatureDelegate.canAdd(context);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2AddFeature#getAddLabelFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IAddFeature getAddLabelFeature(IFeatureProvider fp) {
return addFeatureDelegate.getAddLabelFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2AddFeature#getHeight()
*/
@Override
public int getHeight(IAddContext context) {
return addFeatureDelegate.getHeight(context);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2AddFeature#getWidth()
*/
@Override
public int getWidth(IAddContext context) {
return addFeatureDelegate.getWidth(context);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2AddFeature#getBusinessObjectType()
*/
@Override
public Class getBusinessObjectType() {
return addFeatureDelegate.getBusinessObjectType();
}
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getUpdateFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IUpdateFeature getUpdateFeature(IFeatureProvider fp) {
return getFeatureContainer(fp).getUpdateFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getDirectEditingFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IDirectEditingFeature getDirectEditingFeature(IFeatureProvider fp) {
return getFeatureContainer(fp).getDirectEditingFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getLayoutFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public ILayoutFeature getLayoutFeature(IFeatureProvider fp) {
return getFeatureContainer(fp).getLayoutFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getRemoveFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IRemoveFeature getRemoveFeature(IFeatureProvider fp) {
return getFeatureContainer(fp).getRemoveFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IShapeFeatureContainer#getMoveFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IMoveShapeFeature getMoveFeature(IFeatureProvider fp) {
IShapeFeatureContainer fc = (IShapeFeatureContainer)getFeatureContainer(fp);
return fc.getMoveFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.IShapeFeatureContainer#getResizeFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IResizeShapeFeature getResizeFeature(IFeatureProvider fp) {
IShapeFeatureContainer fc = (IShapeFeatureContainer)getFeatureContainer(fp);
return fc.getResizeFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getDeleteFeature(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public IDeleteFeature getDeleteFeature(IFeatureProvider fp) {
return getFeatureContainer(fp).getDeleteFeature(fp);
}
/* (non-Javadoc)
* @see org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer#getCustomFeatures(org.eclipse.graphiti.features.IFeatureProvider)
*/
@Override
public ICustomFeature[] getCustomFeatures(IFeatureProvider fp) {
return getFeatureContainer(fp).getCustomFeatures(fp);
}
}