package org.activiti.designer.features;
import java.util.List;
import org.activiti.bpmn.model.Association;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.Gateway;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.designer.util.editor.Bpmn2MemoryModel;
import org.activiti.designer.util.editor.ModelHandler;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IAddConnectionContext;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.impl.AbstractAddFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.algorithms.styles.LineStyle;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
import org.eclipse.graphiti.mm.algorithms.styles.StylesFactory;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.ChopboxAnchor;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
import org.eclipse.graphiti.services.IPeCreateService;
import org.eclipse.graphiti.util.IColorConstant;
public class AddAssociationFeature extends AbstractAddFeature {
public AddAssociationFeature(final IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canAdd(final IAddContext context) {
return context instanceof IAddConnectionContext
&& context.getNewObject() instanceof Association;
}
@Override
public PictogramElement add(final IAddContext context) {
final IAddConnectionContext addConnectionContext = (IAddConnectionContext) context;
final Association association = (Association) context.getNewObject();
Anchor sourceAnchor = addConnectionContext.getSourceAnchor();
Anchor targetAnchor = addConnectionContext.getTargetAnchor();
if (sourceAnchor == null) {
final List<Shape> shapes = getDiagram().getChildren();
for (final Shape shape : shapes) {
final BaseElement baseElement
= (BaseElement) getBusinessObjectForPictogramElement(shape.getGraphicsAlgorithm()
.getPictogramElement());
if (baseElement == null || baseElement.getId() == null
|| association.getSourceRef() == null || association.getTargetRef() == null) {
continue;
}
if (baseElement.getId().equals(association.getSourceRef())) {
final List<Anchor> anchors = ((ContainerShape) shape).getAnchors();
for (final Anchor anchor : anchors) {
if (anchor instanceof ChopboxAnchor) {
sourceAnchor = anchor;
break;
}
}
}
if (baseElement.getId().equals(association.getTargetRef())) {
final List<Anchor> anchors = ((ContainerShape) shape).getAnchors();
for (final Anchor anchor : anchors) {
if (anchor instanceof ChopboxAnchor) {
targetAnchor = anchor;
break;
}
}
}
}
}
if (sourceAnchor == null || targetAnchor == null) {
return null;
}
final IPeCreateService peCreateService = Graphiti.getPeCreateService();
// CONNECTION WITH POLYLINE
final FreeFormConnection connection = peCreateService.createFreeFormConnection(getDiagram());
connection.setStart(sourceAnchor);
connection.setEnd(targetAnchor);
sourceAnchor.getOutgoingConnections().add(connection);
targetAnchor.getIncomingConnections().add(connection);
Bpmn2MemoryModel model = ModelHandler.getModel(EcoreUtil.getURI(getDiagram()));
BaseElement sourceElement = model.getFlowElement(association.getSourceRef());
if (sourceElement == null) {
sourceElement = model.getArtifact(association.getSourceRef());
}
BaseElement targetElement = model.getFlowElement(association.getTargetRef());
if (targetElement == null) {
targetElement = model.getArtifact(association.getTargetRef());
}
final GraphicsAlgorithm sourceGraphics = getPictogramElement(sourceElement).getGraphicsAlgorithm();
GraphicsAlgorithm targetGraphics = getPictogramElement(targetElement).getGraphicsAlgorithm();
@SuppressWarnings("unchecked")
List<GraphicInfo> bendpointList = (List<GraphicInfo>) addConnectionContext.getProperty("org.activiti.designer.bendpoints");
if(bendpointList != null && bendpointList.size() >= 0) {
for (GraphicInfo graphicInfo : bendpointList) {
Point bendPoint = StylesFactory.eINSTANCE.createPoint();
bendPoint.setX((int)graphicInfo.getX());
bendPoint.setY((int)graphicInfo.getY());
connection.getBendpoints().add(bendPoint);
}
} else {
Shape sourceShape = (Shape) getPictogramElement(sourceElement);
ILocation sourceShapeLocation = Graphiti.getLayoutService().getLocationRelativeToDiagram(sourceShape);
int sourceX = sourceShapeLocation.getX();
int sourceY = sourceShapeLocation.getY();
Shape targetShape = (Shape) getPictogramElement(targetElement);
ILocation targetShapeLocation = Graphiti.getLayoutService().getLocationRelativeToDiagram(targetShape);
int targetX = targetShapeLocation.getX();
int targetY = targetShapeLocation.getY();
if (sourceElement instanceof Gateway && targetElement instanceof Gateway == false) {
if (((sourceGraphics.getY() + 10) < targetGraphics.getY()
|| (sourceGraphics.getY() - 10) > targetGraphics.getY()) &&
(sourceGraphics.getX() + (sourceGraphics.getWidth() / 2)) < targetGraphics.getX()) {
boolean subProcessWithBendPoint = false;
if(targetElement instanceof SubProcess) {
int middleSub = targetGraphics.getY() + (targetGraphics.getHeight() / 2);
if((sourceGraphics.getY() + 20) < middleSub || (sourceGraphics.getY() - 20) > middleSub) {
subProcessWithBendPoint = true;
}
}
if(targetElement instanceof SubProcess == false || subProcessWithBendPoint == true) {
Point bendPoint = StylesFactory.eINSTANCE.createPoint();
bendPoint.setX(sourceX + 20);
bendPoint.setY(targetY + (targetGraphics.getHeight() / 2));
connection.getBendpoints().add(bendPoint);
}
}
} else if (targetElement instanceof Gateway) {
if (((sourceGraphics.getY() + 10) < targetGraphics.getY()
|| (sourceGraphics.getY() - 10) > targetGraphics.getY()) &&
(sourceGraphics.getX() + sourceGraphics.getWidth()) < targetGraphics.getX()) {
boolean subProcessWithBendPoint = false;
if(sourceElement instanceof SubProcess) {
int middleSub = sourceGraphics.getY() + (sourceGraphics.getHeight() / 2);
if((middleSub + 20) < targetGraphics.getY() || (middleSub - 20) > targetGraphics.getY()) {
subProcessWithBendPoint = true;
}
}
if(sourceElement instanceof SubProcess == false || subProcessWithBendPoint == true) {
Point bendPoint = StylesFactory.eINSTANCE.createPoint();
bendPoint.setX(targetX + 20);
bendPoint.setY(sourceY + (sourceGraphics.getHeight() / 2));
connection.getBendpoints().add(bendPoint);
}
}
} else if (targetElement instanceof EndEvent) {
int middleSource = sourceGraphics.getY() + (sourceGraphics.getHeight() / 2);
int middleTarget = targetGraphics.getY() + (targetGraphics.getHeight() / 2);
if (((middleSource + 10) < middleTarget &&
(sourceGraphics.getX() + sourceGraphics.getWidth()) < targetGraphics.getX()) ||
((middleSource - 10) > middleTarget &&
(sourceGraphics.getX() + sourceGraphics.getWidth()) < targetGraphics.getX())) {
Point bendPoint = StylesFactory.eINSTANCE.createPoint();
bendPoint.setX(targetX + (targetGraphics.getWidth() / 2));
bendPoint.setY(sourceY + (sourceGraphics.getHeight() / 2));
connection.getBendpoints().add(bendPoint);
}
}
}
IGaService gaService = Graphiti.getGaService();
Polyline polyline = gaService.createPolyline(connection);
polyline.setLineStyle(LineStyle.DOT);
polyline.setLineWidth(2);
polyline.setForeground(Graphiti.getGaService().manageColor(getDiagram(), IColorConstant.BLACK));
// create link and wire it
link(connection, association);
return connection;
}
private PictogramElement getPictogramElement(final Object businessObject) {
return getFeatureProvider().getPictogramElementForBusinessObject(businessObject);
}
}