
org.yaoqiang.graph.shape.SubProcessShape Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yaoqiang-bpmn-editor Show documentation
Show all versions of yaoqiang-bpmn-editor Show documentation
an Open Source BPMN 2.0 Modeler
package org.yaoqiang.graph.shape;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Map;
import org.yaoqiang.bpmn.model.BPMNModelUtils;
import org.yaoqiang.bpmn.model.elements.activities.Activity;
import org.yaoqiang.bpmn.model.elements.activities.AdHocSubProcess;
import org.yaoqiang.bpmn.model.elements.activities.CallActivity;
import org.yaoqiang.bpmn.model.elements.activities.LoopCharacteristics;
import org.yaoqiang.bpmn.model.elements.activities.MultiInstanceLoopCharacteristics;
import org.yaoqiang.bpmn.model.elements.activities.StandardLoopCharacteristics;
import org.yaoqiang.bpmn.model.elements.activities.SubProcess;
import org.yaoqiang.bpmn.model.elements.activities.Transaction;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyActivity;
import org.yaoqiang.bpmn.model.elements.core.common.FlowElementsContainer;
import org.yaoqiang.bpmn.model.elements.core.common.FlowNode;
import org.yaoqiang.bpmn.model.elements.events.EventDefinitions;
import org.yaoqiang.bpmn.model.elements.events.StartEvent;
import org.yaoqiang.graph.model.GraphModel;
import org.yaoqiang.util.Constants;
import com.mxgraph.canvas.mxGraphics2DCanvas;
import com.mxgraph.model.mxICell;
import com.mxgraph.shape.mxRectangleShape;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
/**
* SubProcessShape
*
* @author Shi Yaoqiang([email protected])
*/
public class SubProcessShape extends mxRectangleShape {
public void paintShape(mxGraphics2DCanvas canvas, mxCellState state) {
if (!(((mxICell) state.getCell()).getValue() instanceof FlowNode)) {
super.paintShape(canvas, state);
return;
}
FlowNode flowNode = (FlowNode) ((mxICell) state.getCell()).getValue();
Map style = state.getStyle();
double scale = canvas.getScale();
Rectangle rect = state.getRectangle();
if (flowNode instanceof SubProcess && ((SubProcess) flowNode).isTriggeredByEvent()) {
style.put(mxConstants.STYLE_DASHED, "1");
canvas.getGraphics().setStroke(canvas.createStroke(style));
} else {
style.put(mxConstants.STYLE_DASHED, "0");
canvas.getGraphics().setStroke(canvas.createStroke(style));
}
super.paintShape(canvas, state);
if (flowNode instanceof SubProcess && ((SubProcess) flowNode).isTriggeredByEvent()) {
StartEvent startEvent = BPMNModelUtils.getStartEvent((FlowElementsContainer) flowNode);
if (startEvent != null) {
GraphModel model = (GraphModel) state.getView().getGraph().getModel();
String styleName = model.getStyle(model.getCell(startEvent.getId()));
String image = null;
if (styleName.equals("startMultipleEvent")) {
image = Constants.SHAPE_MARKER + "event_multiple.png";
} else if (styleName.equals("startParallelMultipleEvent")) {
image = Constants.SHAPE_MARKER + "event_parallel_multiple.png";
} else {
EventDefinitions eventDefinitions = startEvent.getEventDefinitions();
if (eventDefinitions.size() == 1) {
String eventDef = startEvent.getEventDefinition().toName();
image = Constants.SHAPE_MARKER + "event_" + eventDef.substring(0, eventDef.indexOf("EventDefinition")) + ".png";
}
}
if (image != null && (rect.width <= Constants.FOLDED_SUBPROCESS_WIDTH * scale + 1)
&& (rect.height <= Constants.FOLDED_SUBPROCESS_HEIGHT * scale + 1)) {
float pw = (float) (mxUtils.getFloat(style, mxConstants.STYLE_STROKEWIDTH, 1) * scale);
Graphics2D g = canvas.getGraphics();
Color color = getStrokeColor(canvas, state);
g.setColor(color);
if (startEvent.isInterrupting()) {
g.setStroke(new BasicStroke(pw));
}
int x = rect.x + 2;
int y = rect.y + 2;
int w = (int) (25 * scale);
int h = (int) (25 * scale);
g.drawOval(x, y, w, h);
canvas.drawImage(new Rectangle(x + (int) (3 * scale), y + (int) (3 * scale), (int) (20 * scale), (int) (20 * scale)), image);
}
}
}
if (flowNode instanceof Transaction) {
int inset = (int) Math.round((mxUtils.getFloat(style, mxConstants.STYLE_STROKEWIDTH, 1) + 3) * canvas.getScale());
int x = rect.x + inset;
int y = rect.y + inset;
int w = rect.width - 2 * inset;
int h = rect.height - 2 * inset;
canvas.getGraphics().drawRoundRect(x, y, w, h, Constants.RECTANGLE_ARCSIZE - 2, Constants.RECTANGLE_ARCSIZE - 2);
}
String marker = null;
String adHocMarker = null;
String compensationMarker = null;
String loopMarker = null;
if (flowNode instanceof Activity) {
Activity subProcess = (Activity) flowNode;
compensationMarker = subProcess.isForCompensation() ? Constants.SHAPE_MARKER + "compensation.png" : null;
if (subProcess instanceof AdHocSubProcess) {
adHocMarker = Constants.SHAPE_MARKER + "adhoc_subprocess.png";
}
LoopCharacteristics loopType = subProcess.getLoopCharacteristics();
if (loopType instanceof StandardLoopCharacteristics) {
loopMarker = Constants.SHAPE_MARKER + "loop_standard.png";
} else if (loopType instanceof MultiInstanceLoopCharacteristics) {
if (((MultiInstanceLoopCharacteristics) loopType).isSequential()) {
loopMarker = Constants.SHAPE_MARKER + "loop_multiple_sequential.png";
} else {
loopMarker = Constants.SHAPE_MARKER + "loop_multiple.png";
}
}
} else if (flowNode instanceof ChoreographyActivity) {
ChoreographyActivity subProcess = (ChoreographyActivity) flowNode;
if (subProcess.getLoopType().equals("Standard")) {
loopMarker = Constants.SHAPE_MARKER + "loop_standard.png";
} else if (subProcess.getLoopType().equals("MultiInstanceSequential")) {
loopMarker = Constants.SHAPE_MARKER + "loop_multiple_sequential.png";
} else if (subProcess.getLoopType().equals("MultiInstanceParallel")) {
loopMarker = Constants.SHAPE_MARKER + "loop_multiple.png";
}
}
if (flowNode instanceof CallActivity
|| ((rect.width < Constants.FOLDED_SUBPROCESS_WIDTH * scale) && (rect.height < Constants.FOLDED_SUBPROCESS_HEIGHT * scale))) {
marker = Constants.SHAPE_MARKER + "subprocess.png";
}
drawMarker(canvas, state, loopMarker, compensationMarker, marker, adHocMarker);
}
private void drawMarker(mxGraphics2DCanvas canvas, mxCellState state, String... marker) {
double scale = canvas.getScale();
int imgWidth = (int) (16 * scale);
int imgHeight = (int) (16 * scale);
Rectangle imageBounds = state.getRectangle();
int num = marker.length;
for (String m : marker) {
if (m == null) {
num--;
}
}
imageBounds.setRect(imageBounds.x + (imageBounds.width - num * imgWidth) / 2, imageBounds.y + imageBounds.height - imgHeight, imgWidth, imgHeight);
for (String m : marker) {
if (m == null) {
continue;
}
canvas.drawImage(imageBounds, m);
moveImageBoundsToRight(imageBounds, imgWidth);
}
}
private void moveImageBoundsToRight(Rectangle imageBounds, int imgWidth) {
imageBounds.setLocation(imageBounds.x + imgWidth, imageBounds.y);
}
public int getArcSize(int w, int h) {
return Constants.RECTANGLE_ARCSIZE;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy