I modify some code and make ProcessInstance Diagram better
Zhe org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator class
modify like this:
package org.activiti.engine.impl.bpmn.diagram;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.imageio.ImageIO;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
public class ProcessDiagramGenerator
{
public static InputStream generateDiagram(ProcessDefinitionEntity processDefinition, String imageType, List<String> highLightedActivities)
{
return generateDiagram(processDefinition, highLightedActivities).generateImage(imageType);
}
protected static ProcessDiagramCanvas generateDiagram(ProcessDefinitionEntity processDefinition, List<String> highLightedActivities)
{
ProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(processDefinition);
drawProcessDiagram(processDiagramCanvas,processDefinition,highLightedActivities);
return processDiagramCanvas;
}
protected static ProcessDiagramCanvas initProcessDiagramCanvas(ProcessDefinitionEntity processDefinition)
{
int minX = Integer.MAX_VALUE;
int maxX = 0;
int minY = Integer.MAX_VALUE;
int maxY = 0;
BufferedImage image=null;
InputStream resource = ProcessEngines.getDefaultProcessEngine().getRepositoryService().getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
try {
image = ImageIO.read(resource);
maxX =image.getWidth();
maxY =image.getHeight();
}
catch(IOException ex)
{
ex.printStackTrace();
}
for (ActivityImpl activity : processDefinition.getActivities()) {
// width
if (activity.getX() + activity.getWidth() > maxX) {
maxX = activity.getX() + activity.getWidth();
}
if (activity.getX() < minX) {
minX = activity.getX();
}
// height
if (activity.getY() + activity.getHeight() > maxY) {
maxY = activity.getY() + activity.getHeight();
}
if (activity.getY() < minY) {
minY = activity.getY();
}
for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
for (int i=0; i < waypoints.size(); i+=2) {
// width
if (waypoints.get(i) > maxX) {
maxX = waypoints.get(i);
}
if (waypoints.get(i) < minX) {
minX = waypoints.get(i);
}
// height
if (waypoints.get(i+1) > maxY) {
maxY = waypoints.get(i+1);
}
if (waypoints.get(i+1) < minY) {
minY = waypoints.get(i+1);
}
}
}
}
ProcessDiagramCanvas processDiagramCanvas =new ProcessDiagramCanvas(maxX, maxY, minX, minY);
processDiagramCanvas.drawProcessDiagramCanvas(image);
return processDiagramCanvas;
}
protected static void drawProcessDiagram(ProcessDiagramCanvas processDiagramCanvas, ProcessDefinitionEntity process, List<String> highLightedActivities)
{
for(ActivityImpl activity : process.getActivities())
{
if(highLightedActivities.contains(activity.getId()))
processDiagramCanvas.drawHighLight(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight()) ;
}
}
}
The org.activiti.engine.impl.bpmn.diagram.ProcessDiagramCanvas class modify like this:
package org.activiti.engine.impl.bpmn.diagram;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.util.IoUtil;
public class ProcessDiagramCanvas
{
protected int canvasWidth = -1;
protected int canvasHeight = -1;
protected int minX = -1;
protected int minY = -1;
protected BufferedImage processDiagram;
protected Graphics2D g;
protected FontMetrics fontMetrics;
protected boolean closed;
protected static Color HIGHLIGHT_COLOR = Color.RED;
protected static Stroke THICK_TASK_BORDER_STROKE = new BasicStroke(3.0f);
public ProcessDiagramCanvas(int width, int height) {
this.canvasWidth = width;
this.canvasHeight = height;
this.processDiagram = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
this.g = (Graphics2D) processDiagram.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setPaint(Color.black);
Font font = new Font("Arial", Font.BOLD, 11);
g.setFont(font);
this.fontMetrics = g.getFontMetrics();
}
public ProcessDiagramCanvas(int width, int height, int minX, int minY) {
this(width, height);
this.minX = minX;
this.minY = minY;
}
public InputStream generateImage(String imageType) {
if (closed) {
throw new ActivitiException("ProcessDiagramGenerator already closed");
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
// Try to remove white space
minX = (minX <= 5) ? 5 : minX;
minY = (minY <= 5) ? 5 : minY;
BufferedImage imageToSerialize = processDiagram;
if (minX >= 0 && minY >= 0) {
imageToSerialize = processDiagram.getSubimage(minX - 5, minY - 5,
canvasWidth - minX + 5 , canvasHeight - minY + 5);
}
ImageIO.write(imageToSerialize, imageType, out);
} catch (IOException e) {
throw new ActivitiException("Error while generating process image" , e);
} finally {
IoUtil.closeSilently(out);
}
return new ByteArrayInputStream(out.toByteArray());
}
public void drawProcessDiagramCanvas(Image processDiagram)
{
g.drawImage(processDiagram, 0, 0, canvasWidth, canvasHeight, null);
}
public void drawHighLight(int x, int y, int width, int height)
{
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
g.setPaint(HIGHLIGHT_COLOR);
g.setStroke(THICK_TASK_BORDER_STROKE);
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
g.draw(rect);
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
}