/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.designer.features;
import java.util.ArrayList;
import java.util.List;
import org.activiti.bpmn.model.Activity;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Lane;
import org.activiti.bpmn.model.Pool;
import org.activiti.bpmn.model.Process;
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.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IResizeShapeContext;
import org.eclipse.graphiti.features.impl.DefaultResizeShapeFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Text;
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;
/**
* @author Tijs Rademakers
*/
public class ContainerResizeFeature extends DefaultResizeShapeFeature {
public ContainerResizeFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canResizeShape(IResizeShapeContext context) {
boolean canResize = super.canResizeShape(context);
// perform further check only if move allowed by default feature
if (canResize == true) {
// don't allow resize if the class name has the length of 1
Shape shape = context.getShape();
Object bo = getBusinessObjectForPictogramElement(shape);
if (bo instanceof SubProcess || bo instanceof Pool || bo instanceof Lane) {
canResize = true;
} else {
canResize = false;
}
}
return canResize;
}
@Override
public void resizeShape(IResizeShapeContext context) {
int height = context.getHeight();
int width = context.getWidth();
if(height < 55) {
height = 55;
}
if(width < 105) {
width = 105;
}
Shape shape = context.getShape();
int oldX = shape.getGraphicsAlgorithm().getX();
int oldY = shape.getGraphicsAlgorithm().getY();
int deltaWidth = width - shape.getGraphicsAlgorithm().getWidth();
int deltaHeight = height - shape.getGraphicsAlgorithm().getHeight();
setSize(shape, width, height);
Object bo = getBusinessObjectForPictogramElement(shape);
if(bo instanceof Lane || bo instanceof Pool) {
centerText((ContainerShape) shape);
}
if (bo instanceof Lane) {
Lane lane = (Lane) bo;
ContainerShape poolShape = shape.getContainer();
setSize(poolShape, poolShape.getGraphicsAlgorithm().getWidth() + deltaWidth,
poolShape.getGraphicsAlgorithm().getHeight() + deltaHeight);
centerText(poolShape);
int laneY = shape.getGraphicsAlgorithm().getY();
for (Lane otherLane : lane.getParentProcess().getLanes()) {
if(lane.equals(otherLane)) continue;
ContainerShape otherLaneShape = (ContainerShape) getFeatureProvider().getPictogramElementForBusinessObject(otherLane);
setSize(otherLaneShape, otherLaneShape.getGraphicsAlgorithm().getWidth() + deltaWidth,
otherLaneShape.getGraphicsAlgorithm().getHeight());
centerText(otherLaneShape);
if(laneY < otherLaneShape.getGraphicsAlgorithm().getY()) {
otherLaneShape.getGraphicsAlgorithm().setY(otherLaneShape.getGraphicsAlgorithm().getY() + deltaHeight);
}
}
} else if (bo instanceof Pool) {
if(context.getProperty("org.activiti.designer.lane.create") == null) {
Bpmn2MemoryModel model = ModelHandler.getModel(EcoreUtil.getURI(getDiagram()));
Pool pool = (Pool) bo;
Process process = model.getBpmnModel().getProcess(pool.getId());
if (process != null) {
int deltaLaneHeight = deltaHeight / process.getLanes().size();
List<Lane> sortedLanes = sortLanesByHorizontalOrder(process.getLanes());
int yShift = 0;
for (Lane lane : sortedLanes) {
ContainerShape laneShape = (ContainerShape) getFeatureProvider().getPictogramElementForBusinessObject(lane);
setSize(laneShape, laneShape.getGraphicsAlgorithm().getWidth() + deltaWidth,
laneShape.getGraphicsAlgorithm().getHeight() + deltaLaneHeight);
centerText(laneShape);
laneShape.getGraphicsAlgorithm().setY(laneShape.getGraphicsAlgorithm().getY() + yShift);
yShift += deltaLaneHeight;
}
}
}
}
super.resizeShape(context);
int newX = shape.getGraphicsAlgorithm().getX();
int newY = shape.getGraphicsAlgorithm().getY();
if (bo instanceof SubProcess) {
SubProcess subProcess = (SubProcess) bo;
for (BoundaryEvent boundaryEvent : subProcess.getBoundaryEvents()) {
PictogramElement boundaryElement = getFeatureProvider().getPictogramElementForBusinessObject(boundaryEvent);
boundaryElement.getGraphicsAlgorithm().setX(boundaryElement.getGraphicsAlgorithm().getX() + newX - oldX);
if (newY - oldY == 0) {
boundaryElement.getGraphicsAlgorithm().setY(boundaryElement.getGraphicsAlgorithm().getY() + deltaHeight);
}
}
for (FlowElement flowElement : subProcess.getFlowElements()) {
if (flowElement instanceof Activity) {
Activity activity = (Activity) flowElement;
for (BoundaryEvent boundaryEvent : activity.getBoundaryEvents()) {
if (oldX != newX) {
PictogramElement boundaryElement = getFeatureProvider().getPictogramElementForBusinessObject(boundaryEvent);
boundaryElement.getGraphicsAlgorithm().setX(boundaryElement.getGraphicsAlgorithm().getX() + newX - oldX);
}
if (oldY != newY) {
PictogramElement boundaryElement = getFeatureProvider().getPictogramElementForBusinessObject(boundaryEvent);
boundaryElement.getGraphicsAlgorithm().setY(boundaryElement.getGraphicsAlgorithm().getY() + newY - oldY);
}
}
}
}
}
}
protected void centerText(ContainerShape shape) {
for (Shape shapeChild : shape.getChildren()) {
if (shapeChild.getGraphicsAlgorithm() instanceof Text) {
Text text = (Text) shapeChild.getGraphicsAlgorithm();
Graphiti.getGaService().setLocationAndSize(text, 0, 0, 20, shape.getGraphicsAlgorithm().getHeight());
}
}
}
protected void setSize(Shape shape, int width, int height) {
shape.getGraphicsAlgorithm().setHeight(height);
shape.getGraphicsAlgorithm().setWidth(width);
for (GraphicsAlgorithm graphicsAlgorithm : shape.getGraphicsAlgorithm().getGraphicsAlgorithmChildren()) {
graphicsAlgorithm.setHeight(height);
graphicsAlgorithm.setWidth(width);
}
}
protected List<Lane> sortLanesByHorizontalOrder(List<Lane> lanes) {
List<Lane> sortedLanes = new ArrayList<Lane>();
for (Lane lane : lanes) {
int index = -1;
ContainerShape laneShape = (ContainerShape) getFeatureProvider().getPictogramElementForBusinessObject(lane);
for (int i = 0; i < sortedLanes.size(); i++) {
Lane sortedLane = sortedLanes.get(i);
ContainerShape sortedLaneShape = (ContainerShape) getFeatureProvider().getPictogramElementForBusinessObject(sortedLane);
if(sortedLaneShape.getGraphicsAlgorithm().getY() > laneShape.getGraphicsAlgorithm().getY()) {
index = i;
break;
}
}
if (index == -1) {
sortedLanes.add(lane);
} else {
sortedLanes.add(index, lane);
}
}
return sortedLanes;
}
}