activiti源码剖析之使用图片生成器设置流程图高亮显示
在一个流程流转的过程中,可能已经经过多个节点,或者正在停留在某个任务节点。那么我们如何直观的显示当前流程已经完成了哪些节点,或者此时当前流程流转到了哪里?那么这里就用到了activiti提供的图片生成器ProcessDiagramGenerator。使用它可以对流程中的节点或者连线等进行高亮标识(也就是用显著的颜色圈起来)后生成图片的输入流,当然也可以对流程图中各个节点的图标,字体之类进行设置。
一、使用ProcessDiagramGenerator对流程运转到的节点进行高亮显示
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
ProcessEngineConfigurationImpl processEngineConfiguration = (ProcessEngineConfigurationImpl) defaultProcessEngine.getProcessEngineConfiguration();
//获取默认图片生成器
ProcessDiagramGenerator processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
//获取要生成的流程图的BpmnModel
BpmnModel bpmnModel = defaultProcessEngine.getRepositoryService().getBpmnModel("delegateTest:1:4");
//设置需要标注高亮的节点
List<String> hightLightElements = new ArrayList<>();
hightLightElements.add("usertask1");
InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, "PNG", hightLightElements);
- 大致的步骤就是:
- 获取流程引擎
- 获取流程引擎配置实现类
- 通过流程引擎配置实现类获取图片默认生成器ProcessDiagramGenerator
- 获取流程模型BpmnModel
- 创建需要高亮展示的节点的集合,元素为节点ID值
- 调用ProcessDiagramGenerator的generateDiagram获取生成图片的输入流
- 客户端展示
二、通过扩展源码实现设置自定义高亮图颜色,字体等绘制属性
如果默认的图片生成器满足不了我们的业务需求,比如我要求用户任务被标注高亮的时候颜色使用蓝色或者其他颜色,我想要图片中显示的字体是黑体、楷体?那么如果是这样应该怎么实现呢?
- 场景:使用蓝色标注流程图已经走过的连线。
-
实战
1、扩展DefaultProcessDiagramCanvas
自定义类继承DefaultProcessDiagramCanvas,这里业务需求是连线标注为蓝色所以需要重写drawConnection方法,只需要修改当highLighted为true时,调用this.g.setPaint()参数为连线的颜色。
public class CFProcessDiagramCanvasExt extends DefaultProcessDiagramCanvas {
//定义连线颜色为蓝色
protected static Color HIGHLIGHT_SequenceFlow_COLOR = Color.BLUE;
public CFProcessDiagramCanvasExt(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
}
/**
* 重写绘制连线的方式,设置绘制颜色
*/
@Override
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor) {
Paint originalPaint = this.g.getPaint();
Stroke originalStroke = this.g.getStroke();
this.g.setPaint(CONNECTION_COLOR);
if (connectionType.equals("association")) {
this.g.setStroke(ASSOCIATION_STROKE);
} else if (highLighted) {
this.g.setPaint(HIGHLIGHT_SequenceFlow_COLOR);
this.g.setStroke(HIGHLIGHT_FLOW_STROKE);
}
for(int i = 1; i < xPoints.length; ++i) {
Integer sourceX = xPoints[i - 1];
Integer sourceY = yPoints[i - 1];
Integer targetX = xPoints[i];
Integer targetY = yPoints[i];
java.awt.geom.Line2D.Double line = new java.awt.geom.Line2D.Double((double)sourceX, (double)sourceY, (double)targetX, (double)targetY);
this.g.draw(line);
}
java.awt.geom.Line2D.Double line;
if (isDefault) {
line = new java.awt.geom.Line2D.Double((double)xPoints[0], (double)yPoints[0], (double)xPoints[1], (double)yPoints[1]);
this.drawDefaultSequenceFlowIndicator(line, scaleFactor);
}
if (conditional) {
line = new java.awt.geom.Line2D.Double((double)xPoints[0], (double)yPoints[0], (double)xPoints[1], (double)yPoints[1]);
this.drawConditionalSequenceFlowIndicator(line, scaleFactor);
}
if (associationDirection.equals(AssociationDirection.ONE) || associationDirection.equals(AssociationDirection.BOTH)) {
line = new java.awt.geom.Line2D.Double((double)xPoints[xPoints.length - 2], (double)yPoints[xPoints.length - 2], (double)xPoints[xPoints.length - 1], (double)yPoints[xPoints.length - 1]);
this.drawArrowHead(line, scaleFactor);
}
if (associationDirection.equals(AssociationDirection.BOTH)) {
line = new java.awt.geom.Line2D.Double((double)xPoints[1], (double)yPoints[1], (double)xPoints[0], (double)yPoints[0]);
this.drawArrowHead(line, scaleFactor);
}
this.g.setPaint(originalPaint);
this.g.setStroke(originalStroke);
}
}
2. 扩展DefaultProcessDiagramGenerator,当initProcessDiagramCanvas时候,使用自定义的ProcessDiagramCanvas,只需要修改initProcessDiagramCanvas方法中最后一行为创建我们自定义的initProcessDiagramCanvas
注意:这里必须同时定义generateProcessDiagram方法,实现与DefaultProcessDiagramGenerator中的实现相同。如果不定义,程序依然会调用DefaultProcessDiagramGenerator中的generateProcessDiagram方法生成默认的DefaultProcessDiagramCanvas
public class ProcessDiagramGenarateExt extends DefaultProcessDiagramGenerator {
@Override
protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
this.prepareBpmnModel(bpmnModel);
DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
....
实现同父类实现一模一样
}
protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
。。。。这里与父类代码一模一样
//设置返回自定义ProcessDiagramCanvas
return new CFProcessDiagramCanvasExt((int)maxX + 10, (int)maxY + 10, (int)minX, (int)minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
}
}
3. 使用自定义图片生成器进行流程运转图的生成
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
ProcessEngineConfigurationImpl processEngineConfiguration = (ProcessEngineConfigurationImpl) defaultProcessEngine.getProcessEngineConfiguration();
//获取自定义图片生成器
ProcessDiagramGenerator processDiagramGenerator = new ProcessDiagramGenarateExt();
//获取要生成的流程图的BpmnModel
BpmnModel bpmnModel = defaultProcessEngine.getRepositoryService().getBpmnModel("delegateTest:1:4");
//设置需要标注高亮的节点
List<String> hightLightElements = new ArrayList<>();
hightLightElements.add("usertask1");
//设置需要标注高亮的连线
List<String> hightLightFlows = new ArrayList<>();
hightLightFlows.add("flow1");
InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, "PNG", hightLightElements,hightLightFlows);
- 生成结果