/*******************************************************************************
* Copyright (c) 2011 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.lane;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.Lane;
import org.eclipse.bpmn2.LaneSet;
import org.eclipse.bpmn2.Participant;
import org.eclipse.bpmn2.SubProcess;
import org.eclipse.bpmn2.modeler.core.di.DIImport;
import org.eclipse.bpmn2.modeler.core.features.AbstractBpmnAddFeature;
import org.eclipse.bpmn2.modeler.core.utils.AnchorUtil;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.bpmn2.modeler.core.utils.StyleUtil;
import org.eclipse.graphiti.datatypes.ILocation;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ITargetContext;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
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.ILayoutService;
import org.eclipse.graphiti.services.IPeCreateService;
public class AddLaneFeature extends AbstractBpmnAddFeature {
public AddLaneFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canAdd(IAddContext context) {
boolean isLane = context.getNewObject() instanceof Lane;
boolean intoDiagram = context.getTargetContainer().equals(getDiagram());
boolean intoLane = FeatureSupport.isTargetLane(context);
boolean intoParticipant = FeatureSupport.isTargetParticipant(context);
boolean intoSubprocess = FeatureSupport.isTargetSubProcess(context);
return isLane && (intoDiagram || intoLane || intoParticipant || intoSubprocess);
}
@Override
public PictogramElement add(IAddContext context) {
Lane lane = (Lane) context.getNewObject();
IPeCreateService peCreateService = Graphiti.getPeCreateService();
ContainerShape containerShape = peCreateService.createContainerShape(context.getTargetContainer(), true);
IGaService gaService = Graphiti.getGaService();
int width = context.getWidth() > 0 ? context.getWidth() : 600;
int height = context.getHeight() > 0 ? context.getHeight() : 100;
Rectangle rect = gaService.createRectangle(containerShape);
StyleUtil.applyBGStyle(rect, this);
if (FeatureSupport.isTargetLane(context) || FeatureSupport.isTargetParticipant(context)) {
GraphicsAlgorithm ga = context.getTargetContainer().getGraphicsAlgorithm();
if (getNumberOfLanes(context) == 1) {
gaService.setLocationAndSize(rect, 15, 0, width - 15, height);
for (Shape s : getFlowNodeShapes(context, lane)) {
Graphiti.getPeService().sendToFront(s);
s.setContainer(containerShape);
}
} else {
if (context.getWidth() == -1 || context.getHeight() == -1) {
gaService.setLocationAndSize(rect, 15, ga.getWidth() - 1, ga.getHeight() - 15, height);
// gaService.setLocationAndSize(rect, context.getX(), context.getY(), width, height);
} else {
ILayoutService layoutService = Graphiti.getLayoutService();
ILocation loc = layoutService.getLocationRelativeToDiagram(containerShape);
int x = context.getX() - loc.getX();
int y = context.getY() - loc.getY();
gaService.setLocationAndSize(rect, x - 15, y, ga.getWidth() - 15, height);
}
}
containerShape.setContainer(context.getTargetContainer());
} else {
gaService.setLocationAndSize(rect, context.getX(), context.getY(), width, height);
}
Shape textShape = peCreateService.createShape(containerShape, false);
Text text = gaService.createText(textShape, lane.getName());
text.setStyle(StyleUtil.getStyleForText(getDiagram()));
text.setVerticalAlignment(Orientation.ALIGNMENT_CENTER);
text.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER);
text.setAngle(-90);
gaService.setLocationAndSize(text, 0, 0, 15, height);
createDIShape(containerShape, lane);
link(textShape, lane);
peCreateService.createChopboxAnchor(containerShape);
AnchorUtil.addFixedPointAnchors(containerShape, rect);
if (context.getProperty(DIImport.IMPORT_PROPERTY) == null
&& (FeatureSupport.isTargetLane(context) || FeatureSupport.isTargetParticipant(context))) {
FeatureSupport.redraw(context.getTargetContainer());
}
return containerShape;
}
private List<Shape> getFlowNodeShapes(IAddContext context, Lane lane) {
List<FlowNode> nodes = lane.getFlowNodeRefs();
List<Shape> shapes = new ArrayList<Shape>();
for (Shape s : context.getTargetContainer().getChildren()) {
Object bo = getBusinessObjectForPictogramElement(s);
if (bo != null && nodes.contains(bo)) {
shapes.add(s);
}
}
return shapes;
}
private int getNumberOfLanes(ITargetContext context) {
ContainerShape targetContainer = context.getTargetContainer();
Object bo = getBusinessObjectForPictogramElement(targetContainer);
if (bo instanceof Lane) {
Lane lane = (Lane) bo;
return lane.getChildLaneSet().getLanes().size();
} else if (bo instanceof Participant) {
List<LaneSet> laneSets = ((Participant) bo).getProcessRef().getLaneSets();
if (laneSets.size() > 0) {
return laneSets.get(0).getLanes().size();
}
return laneSets.size();
} else if (bo instanceof SubProcess) {
List<LaneSet> laneSets = ((SubProcess) bo).getLaneSets();
if (laneSets.size() > 0) {
return laneSets.get(0).getLanes().size();
}
return laneSets.size();
}
return 0;
}
}