xm
2024-06-14 722af26bc6fec32bb289b1df51a9016a4935610f
提交 | 用户 | 时间
722af2 1 package com.dl.flowable.flow;
X 2
3 import org.flowable.bpmn.model.AssociationDirection;
4 import org.flowable.bpmn.model.GraphicInfo;
5 import org.flowable.image.impl.DefaultProcessDiagramCanvas;
6 import org.flowable.image.util.ReflectUtil;
7
8 import javax.imageio.ImageIO;
9 import java.awt.*;
10 import java.awt.font.FontRenderContext;
11 import java.awt.font.LineBreakMeasurer;
12 import java.awt.font.TextAttribute;
13 import java.awt.font.TextLayout;
14 import java.awt.geom.Ellipse2D;
15 import java.awt.geom.Rectangle2D;
16 import java.awt.geom.RoundRectangle2D;
17 import java.awt.image.BufferedImage;
18 import java.io.IOException;
19 import java.text.AttributedCharacterIterator;
20 import java.text.AttributedString;
21
22 /**
23  * @author XuanXuan
24  * @date 2021/4/4 23:58
25  */
26 public class CustomProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
27     //定义走过流程连线颜色为绿色
28     protected static Color HIGHLIGHT_SequenceFlow_COLOR = Color.GREEN;
29     //设置未走过流程的连接线颜色
30     protected static Color CONNECTION_COLOR = Color.BLACK;
31     //设置flows连接线字体颜色red
32     protected static Color LABEL_COLOR = new Color(0, 0, 0);
33     //高亮显示task框颜色
34     protected static Color HIGHLIGHT_COLOR = Color.GREEN;
35     protected static Color HIGHLIGHT_COLOR1 = Color.RED;
36
37     public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
38         super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
39         this.initialize(imageType);
40     }
41
42     /**
43      * 重写绘制连线的方式,设置绘制颜色
44      * @param xPoints
45      * @param yPoints
46      * @param conditional
47      * @param isDefault
48      * @param connectionType
49      * @param associationDirection
50      * @param highLighted
51      * @param scaleFactor
52      */
53     @Override
54     public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor) {
55         Paint originalPaint = this.g.getPaint();
56         Stroke originalStroke = this.g.getStroke();
57         this.g.setPaint(CONNECTION_COLOR);
58         if (connectionType.equals("association")) {
59             this.g.setStroke(ASSOCIATION_STROKE);
60         } else if (highLighted) {
61             this.g.setPaint(HIGHLIGHT_SequenceFlow_COLOR);
62             this.g.setStroke(HIGHLIGHT_FLOW_STROKE);
63         }
64
65         for (int i = 1; i < xPoints.length; ++i) {
66             int sourceX = xPoints[i - 1];
67             int sourceY = yPoints[i - 1];
68             int targetX = xPoints[i];
69             int targetY = yPoints[i];
70             java.awt.geom.Line2D.Double line = new java.awt.geom.Line2D.Double((double) sourceX, (double) sourceY, (double) targetX, (double) targetY);
71             this.g.draw(line);
72         }
73
74         java.awt.geom.Line2D.Double line;
75         if (isDefault) {
76             line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]);
77             this.drawDefaultSequenceFlowIndicator(line, scaleFactor);
78         }
79
80         if (conditional) {
81             line = new java.awt.geom.Line2D.Double((double) xPoints[0], (double) yPoints[0], (double) xPoints[1], (double) yPoints[1]);
82             this.drawConditionalSequenceFlowIndicator(line, scaleFactor);
83         }
84
85         if (associationDirection.equals(AssociationDirection.ONE) || associationDirection.equals(AssociationDirection.BOTH)) {
86             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]);
87             this.drawArrowHead(line, scaleFactor);
88         }
89
90         if (associationDirection.equals(AssociationDirection.BOTH)) {
91             line = new java.awt.geom.Line2D.Double((double) xPoints[1], (double) yPoints[1], (double) xPoints[0], (double) yPoints[0]);
92             this.drawArrowHead(line, scaleFactor);
93         }
94
95         this.g.setPaint(originalPaint);
96         this.g.setStroke(originalStroke);
97     }
98
99     /**
100      * 设置字体大小图标颜色
101      * @param imageType
102      */
103     @Override
104     public void initialize(String imageType) {
105         if ("png".equalsIgnoreCase(imageType)) {
106             this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 2);
107         } else {
108             this.processDiagram = new BufferedImage(this.canvasWidth, this.canvasHeight, 1);
109         }
110
111         this.g = this.processDiagram.createGraphics();
112         if (!"png".equalsIgnoreCase(imageType)) {
113             this.g.setBackground(new Color(255, 255, 255, 0));
114             this.g.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
115         }
116
117         this.g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
118         //修改图标颜色,修改图标字体大小
119         this.g.setPaint(Color.black);
120         Font font = new Font(this.activityFontName, 10, 14);
121         this.g.setFont(font);
122         this.fontMetrics = this.g.getFontMetrics();
123         //修改连接线字体大小
124         LABEL_FONT = new Font(this.labelFontName, 10, 15);
125         ANNOTATION_FONT = new Font(this.annotationFontName, 0, 11);
126
127         try {
128             USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/userTask.png", this.customClassLoader));
129             SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/scriptTask.png", this.customClassLoader));
130             SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/serviceTask.png", this.customClassLoader));
131             RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/receiveTask.png", this.customClassLoader));
132             SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/sendTask.png", this.customClassLoader));
133             MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/manualTask.png", this.customClassLoader));
134             BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/businessRuleTask.png", this.customClassLoader));
135             SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/shellTask.png", this.customClassLoader));
136             DMN_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/dmnTask.png", this.customClassLoader));
137             CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/camelTask.png", this.customClassLoader));
138             MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/muleTask.png", this.customClassLoader));
139             HTTP_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/httpTask.png", this.customClassLoader));
140             TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/timer.png", this.customClassLoader));
141             COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate-throw.png", this.customClassLoader));
142             COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/compensate.png", this.customClassLoader));
143             ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error-throw.png", this.customClassLoader));
144             ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/error.png", this.customClassLoader));
145             MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message-throw.png", this.customClassLoader));
146             MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/message.png", this.customClassLoader));
147             SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal-throw.png", this.customClassLoader));
148             SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/flowable/icons/signal.png", this.customClassLoader));
149         } catch (IOException var4) {
150             LOGGER.warn("Could not load image for process diagram creation: {}", var4.getMessage());
151         }
152
153     }
154
155     /**
156      * 设置连接线字体
157      * @param text
158      * @param graphicInfo
159      * @param centered
160      */
161     @Override
162     public void drawLabel(String text, GraphicInfo graphicInfo, boolean centered) {
163         float interline = 1.0f;
164
165         // text
166         if (text != null && text.length() > 0) {
167             Paint originalPaint = g.getPaint();
168             Font originalFont = g.getFont();
169
170             g.setPaint(LABEL_COLOR);
171             g.setFont(LABEL_FONT);
172
173             int wrapWidth = 100;
174             int textY = (int) graphicInfo.getY();
175
176             // TODO: use drawMultilineText()
177             AttributedString as = new AttributedString(text);
178             as.addAttribute(TextAttribute.FOREGROUND, g.getPaint());
179             as.addAttribute(TextAttribute.FONT, g.getFont());
180             AttributedCharacterIterator aci = as.getIterator();
181             FontRenderContext frc = new FontRenderContext(null, true, false);
182             LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
183
184             while (lbm.getPosition() < text.length()) {
185                 TextLayout tl = lbm.nextLayout(wrapWidth);
186                 textY += tl.getAscent();
187
188                 Rectangle2D bb = tl.getBounds();
189                 double tX = graphicInfo.getX();
190
191                 if (centered) {
192                     tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2);
193                 }
194                 tl.draw(g, (float) tX, textY);
195                 textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent();
196             }
197
198             // restore originals
199             g.setFont(originalFont);
200             g.setPaint(originalPaint);
201         }
202     }
203
204     /**
205      * 高亮显示task框完成的
206      * @param x
207      * @param y
208      * @param width
209      * @param height
210      */
211     @Override
212     public void drawHighLight(int x, int y, int width, int height) {
213         Paint originalPaint = g.getPaint();
214         Stroke originalStroke = g.getStroke();
215
216         g.setPaint(HIGHLIGHT_COLOR);
217         g.setStroke(THICK_TASK_BORDER_STROKE);
218
219         RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
220         g.draw(rect);
221
222         g.setPaint(originalPaint);
223         g.setStroke(originalStroke);
224     }
225
226     /**
227      * 自定义task框当前的位置
228      * @param x
229      * @param y
230      * @param width
231      * @param height
232      */
233     public void drawHighLightNow(int x, int y, int width, int height) {
234         Paint originalPaint = g.getPaint();
235         Stroke originalStroke = g.getStroke();
236
237         g.setPaint(HIGHLIGHT_COLOR1);
238         g.setStroke(THICK_TASK_BORDER_STROKE);
239
240         RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
241         g.draw(rect);
242
243         g.setPaint(originalPaint);
244         g.setStroke(originalStroke);
245     }
246
247     /**
248      * 自定义结束节点
249      * @param x
250      * @param y
251      * @param width
252      * @param height
253      */
254     public void drawHighLightEnd(int x, int y, int width, int height) {
255         Paint originalPaint = g.getPaint();
256         Stroke originalStroke = g.getStroke();
257
258         g.setPaint(HIGHLIGHT_COLOR);
259         g.setStroke(THICK_TASK_BORDER_STROKE);
260
261         RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
262         g.draw(rect);
263
264         g.setPaint(originalPaint);
265         g.setStroke(originalStroke);
266     }
267
268     /**
269      * task框自定义文字
270      * @param name
271      * @param graphicInfo
272      * @param thickBorder
273      * @param scaleFactor
274      */
275     @Override
276     protected void drawTask(String name, GraphicInfo graphicInfo, boolean thickBorder, double scaleFactor) {
277
278         Paint originalPaint = g.getPaint();
279         int x = (int) graphicInfo.getX();
280         int y = (int) graphicInfo.getY();
281         int width = (int) graphicInfo.getWidth();
282         int height = (int) graphicInfo.getHeight();
283
284         // Create a new gradient paint for every task box, gradient depends on x and y and is not relative
285         g.setPaint(TASK_BOX_COLOR);
286
287         int arcR = 6;
288         if (thickBorder) {
289             arcR = 3;
290         }
291
292         // shape
293         RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, arcR, arcR);
294         g.fill(rect);
295         g.setPaint(TASK_BORDER_COLOR);
296
297         if (thickBorder) {
298             Stroke originalStroke = g.getStroke();
299             g.setStroke(THICK_TASK_BORDER_STROKE);
300             g.draw(rect);
301             g.setStroke(originalStroke);
302         } else {
303             g.draw(rect);
304         }
305
306         g.setPaint(originalPaint);
307         // text
308         if (scaleFactor == 1.0 && name != null && name.length() > 0) {
309             int boxWidth = width - (2 * TEXT_PADDING);
310             int boxHeight = height - 16 - ICON_PADDING - ICON_PADDING - MARKER_WIDTH - 2 - 2;
311             int boxX = x + width / 2 - boxWidth / 2;
312             int boxY = y + height / 2 - boxHeight / 2 + ICON_PADDING + ICON_PADDING - 2 - 2;
313
314             drawMultilineCentredText(name, boxX, boxY, boxWidth, boxHeight);
315         }
316     }
317
318     protected static Color EVENT_COLOR = new Color(255, 255, 255);
319
320     /**
321      * 重写开始事件
322      * @param graphicInfo
323      * @param image
324      * @param scaleFactor
325      */
326     @Override
327     public void drawStartEvent(GraphicInfo graphicInfo, BufferedImage image, double scaleFactor) {
328         Paint originalPaint = g.getPaint();
329         g.setPaint(EVENT_COLOR);
330         Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(),
331                 graphicInfo.getWidth(), graphicInfo.getHeight());
332         g.fill(circle);
333         g.setPaint(EVENT_BORDER_COLOR);
334         g.draw(circle);
335         g.setPaint(originalPaint);
336         if (image != null) {
337             // calculate coordinates to center image
338             int imageX = (int) Math.round(graphicInfo.getX() + (graphicInfo.getWidth() / 2) - (image.getWidth() / (2 * scaleFactor)));
339             int imageY = (int) Math.round(graphicInfo.getY() + (graphicInfo.getHeight() / 2) - (image.getHeight() / (2 * scaleFactor)));
340             g.drawImage(image, imageX, imageY,
341                     (int) (image.getWidth() / scaleFactor), (int) (image.getHeight() / scaleFactor), null);
342         }
343
344     }
345
346     /**
347      * 重写结束事件
348      * @param graphicInfo
349      * @param scaleFactor
350      */
351     @Override
352     public void drawNoneEndEvent(GraphicInfo graphicInfo, double scaleFactor) {
353         Paint originalPaint = g.getPaint();
354         Stroke originalStroke = g.getStroke();
355         g.setPaint(EVENT_COLOR);
356         Ellipse2D circle = new Ellipse2D.Double(graphicInfo.getX(), graphicInfo.getY(),
357                 graphicInfo.getWidth(), graphicInfo.getHeight());
358         g.fill(circle);
359         g.setPaint(EVENT_BORDER_COLOR);
360 //        g.setPaint(HIGHLIGHT_COLOR);
361         if (scaleFactor == 1.0) {
362             g.setStroke(END_EVENT_STROKE);
363         } else {
364             g.setStroke(new BasicStroke(2.0f));
365         }
366         g.draw(circle);
367         g.setStroke(originalStroke);
368         g.setPaint(originalPaint);
369     }
370 }