All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yaoqiang.graph.shape.SubProcessShape Maven / Gradle / Ivy

There is a newer version: 2.2.18
Show newest version
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