activiti6.0源码剖析之使用图片生成器设置流程图高亮显示

在一个流程流转的过程中,可能已经经过多个节点,或者正在停留在某个任务节点。那么我们如何直观的显示当前流程已经完成了哪些节点,或者此时当前流程流转到了哪里?那么这里就用到了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);
  • 大致的步骤就是:
  1. 获取流程引擎
  2. 获取流程引擎配置实现类
  3. 通过流程引擎配置实现类获取图片默认生成器ProcessDiagramGenerator
  4. 获取流程模型BpmnModel
  5. 创建需要高亮展示的节点的集合,元素为节点ID值
  6. 调用ProcessDiagramGenerator的generateDiagram获取生成图片的输入流
  7. 客户端展示
流程运转图.png

二、通过扩展源码实现设置自定义高亮图颜色,字体等绘制属性

如果默认的图片生成器满足不了我们的业务需求,比如我要求用户任务被标注高亮的时候颜色使用蓝色或者其他颜色,我想要图片中显示的字体是黑体、楷体?那么如果是这样应该怎么实现呢?

  • 场景:使用蓝色标注流程图已经走过的连线
  • 实战
    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);

- 生成结果

自定义生成结果.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32
  • 6月5号,死党们通过学习、碰撞和交流,使得大家不仅支持到了跃跃,同时也提升了自己,跃跃的主题是:如何快速...
    创凌WiFi方案定制阅读 334评论 1 0
  • 我们经常说社会会在我们正式踏入社会的几个月里迅速的磨平我们所有的棱角,我们将之称为走向成熟的蜕变。 但是在这个世界...
    兰菲儿阅读 641评论 0 1
  • 【书名】《写出我心》 【作者】威廉.津瑟 【金句】 001最好的实践方式是出去采访人,采访本身就是受欢迎的非虚构形...
    鲁曼啊漫阅读 104评论 0 3