jbpm4.4根据.jpdl.xml流程定义文件,得到流程图.png (转)

文章来源: http://www.oecp.cn/hi/yangtaoorange/blog/5804

只需将.jpdl.xml文件传过来,就可以根据这个文件解析出来.png图

节点定义:

public class Node {    
  private String name;    
  private String type;    
  private Rectangle rectangle;    
  private List<Transition> transitions = new ArrayList<Transition>();    
   
  public Node(String name, String type) {    
    this.name = name;    
    this.type = type;    
  }    
   
  public Node(String name, String type, int x, int y, int w, int h) {    
    this.name = name;    
    this.type = type;    
    this.rectangle = new Rectangle(x, y, w, h);    
  }    
   
  public Rectangle getRectangle() {    
    return rectangle;    
  }    
   
  public void setRectangle(Rectangle rectangle) {    
    this.rectangle = rectangle;    
  }    
   
  public String getType() {    
    return type;    
  }    
   
  public void setType(String type) {    
    this.type = type;    
  }    
   
  public String getName() {    
    return name;    
  }    
   
  public void setName(String name) {    
    this.name = name;    
  }    
   
  public void addTransition(Transition transition) {    
    transitions.add(transition);    
  }    
   
  public List<Transition> getTransitions() {    
    return transitions;    
  }    
   
  public void setTransitions(List<Transition> transitions) {    
    this.transitions = transitions;    
  }    
   
  public int getX() {    
    return rectangle.x;    
  }    
   
  public int getY() {    
    return rectangle.y;    
  }    
   
  public int getCenterX() {    
    return (int) rectangle.getCenterX();    
  }    
   
  public int getCenterY() {    
    return (int) rectangle.getCenterY();    
  }    
   
  public int getWitdth() {    
    return rectangle.width;    
  }    
   
  public int getHeight() {    
    return rectangle.height;    
  }    
}   
public class Node {
  private String name;
  private String type;
  private Rectangle rectangle;
  private List<Transition> transitions = new ArrayList<Transition>();

  public Node(String name, String type) {
    this.name = name;
    this.type = type;
  }

  public Node(String name, String type, int x, int y, int w, int h) {
    this.name = name;
    this.type = type;
    this.rectangle = new Rectangle(x, y, w, h);
  }

  public Rectangle getRectangle() {
    return rectangle;
  }

  public void setRectangle(Rectangle rectangle) {
    this.rectangle = rectangle;
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void addTransition(Transition transition) {
    transitions.add(transition);
  }

  public List<Transition> getTransitions() {
    return transitions;
  }

  public void setTransitions(List<Transition> transitions) {
    this.transitions = transitions;
  }

  public int getX() {
    return rectangle.x;
  }

  public int getY() {
    return rectangle.y;
  }

  public int getCenterX() {
    return (int) rectangle.getCenterX();
  }

  public int getCenterY() {
    return (int) rectangle.getCenterY();
  }

  public int getWitdth() {
    return rectangle.width;
  }

  public int getHeight() {
    return rectangle.height;
  }
}

Transition的定义:

public class Transition {    
  private Point labelPosition;    
  private List<Point> lineTrace = new ArrayList<Point>();    
  private String label;    
  private String to;    
   
  public Transition(String label, String to) {    
    this.label = label;    
    this.to = to;    
  }    
   
  public Point getLabelPosition() {    
    return labelPosition;    
  }    
   
  public void setLabelPosition(Point labelPosition) {    
    this.labelPosition = labelPosition;    
  }    
   
  public List<Point> getLineTrace() {    
    return lineTrace;    
  }    
   
  public void setLineTrace(List<Point> lineTrace) {    
    this.lineTrace = lineTrace;    
  }    
   
  public void addLineTrace(Point lineTrace) {    
    if (lineTrace != null) {    
      this.lineTrace.add(lineTrace);    
    }    
  }    
   
  public String getLabel() {    
    return label;    
  }    
  public void setLabel(String label) {    
    this.label = label;    
  }    
   
  public String getTo() {    
    return to;    
  }    
   
  public void setTo(String to) {    
    this.to = to;    
  }    
   
}   
public class Transition {
  private Point labelPosition;
  private List<Point> lineTrace = new ArrayList<Point>();
  private String label;
  private String to;

  public Transition(String label, String to) {
    this.label = label;
    this.to = to;
  }

  public Point getLabelPosition() {
    return labelPosition;
  }

  public void setLabelPosition(Point labelPosition) {
    this.labelPosition = labelPosition;
  }

  public List<Point> getLineTrace() {
    return lineTrace;
  }

  public void setLineTrace(List<Point> lineTrace) {
    this.lineTrace = lineTrace;
  }

  public void addLineTrace(Point lineTrace) {
    if (lineTrace != null) {
      this.lineTrace.add(lineTrace);
    }
  }

  public String getLabel() {
    return label;
  }
  public void setLabel(String label) {
    this.label = label;
  }

  public String getTo() {
    return to;
  }

  public void setTo(String to) {
    this.to = to;
  }

}

类JpdlModel

/**   
 * CopyRight (C) 2006-2009 yy   
 * @author yy   
 * @project jbpm   
 * @version 1.0   
 * @mail yy629_86 at 163 dot com   
 * @date 2009-9-6 下午06:00:14   
 * @description   
 */   
package sofocus.bpm.jbpm.jpdl.model;    
   
import java.awt.Point;    
import java.io.InputStream;    
import java.util.HashMap;    
import java.util.LinkedHashMap;    
import java.util.List;    
import java.util.Map;    
   
import org.dom4j.Element;    
import org.dom4j.io.SAXReader;    
   
public class JpdlModel {    
  private Map<String, Node> nodes = new LinkedHashMap<String, Node>();    
  public static final int RECT_OFFSET_X = -7;    
  public static final int RECT_OFFSET_Y = -8;    
  public static final int DEFAULT_PIC_SIZE = 48;    
   
  private final static Map<String, Object> nodeInfos = new HashMap<String, Object>();    
  static {    
    nodeInfos.put("start", "start_event_empty.png");    
    nodeInfos.put("end", "end_event_terminate.png");    
    nodeInfos.put("end-cancel", "end_event_cancel.png");    
    nodeInfos.put("end-error", "end_event_error.png");    
    nodeInfos.put("decision", "gateway_exclusive.png");    
    nodeInfos.put("fork", "gateway_parallel.png");    
    nodeInfos.put("join", "gateway_parallel.png");    
    nodeInfos.put("state", null);    
    nodeInfos.put("hql", null);    
    nodeInfos.put("sql", null);    
    nodeInfos.put("java", null);    
    nodeInfos.put("script", null);    
    nodeInfos.put("task", null);    
    nodeInfos.put("sub-process", null);    
    nodeInfos.put("custom", null);    
  }    
   
  public JpdlModel(InputStream is) throws Exception {    
    this(new SAXReader().read(is).getRootElement());    
  }    
   
  @SuppressWarnings("unchecked")    
  private JpdlModel(Element rootEl) throws Exception {    
    for (Element el : (List<Element>) rootEl.elements()) {    
      String type = el.getQName().getName();    
      if (!nodeInfos.containsKey(type)) { // 不是可展示的节点    
        continue;    
      }    
      String name = null;    
      if (el.attribute("name") != null) {    
        name = el.attributeValue("name");    
      }    
      String[] location = el.attributeValue("g").split(",");    
      int x = Integer.parseInt(location[0]);    
      int y = Integer.parseInt(location[1]);    
      int w = Integer.parseInt(location[2]);    
      int h = Integer.parseInt(location[3]);    
   
      if (nodeInfos.get(type) != null) {    
        w = DEFAULT_PIC_SIZE;    
        h = DEFAULT_PIC_SIZE;    
      } else {    
        x -= RECT_OFFSET_X;    
        y -= RECT_OFFSET_Y;    
        w += (RECT_OFFSET_X + RECT_OFFSET_X);    
        h += (RECT_OFFSET_Y + RECT_OFFSET_Y);    
      }    
      Node node = new Node(name, type, x, y, w, h);    
      parserTransition(node, el);    
      nodes.put(name, node);    
    }    
  }    
   
  @SuppressWarnings("unchecked")    
  private void parserTransition(Node node, Element nodeEl) {    
    for (Element el : (List<Element>) nodeEl.elements("transition")) {    
      String label = el.attributeValue("name");    
      String to = el.attributeValue("to");    
      Transition transition = new Transition(label, to);    
      String g = el.attributeValue("g");    
      if (g != null && g.length() > 0) {    
        if (g.indexOf(":") < 0) {    
          transition.setLabelPosition(getPoint(g));    
        } else {    
          String[] p = g.split(":");    
          transition.setLabelPosition(getPoint(p[1]));    
          String[] lines = p[0].split(";");    
          for (String line : lines) {    
            transition.addLineTrace(getPoint(line));    
          }    
        }    
      }    
      node.addTransition(transition);    
    }    
  }    
   
  private Point getPoint(String exp) {    
    if (exp == null || exp.length() == 0) {    
      return null;    
    }    
    String[] p = exp.split(",");    
    return new Point(Integer.valueOf(p[0]), Integer.valueOf(p[1]));    
  }    
   
  public Map<String, Node> getNodes() {    
    return nodes;    
  }    
    public static Map<String, Object> getNodeInfos() {    
    return nodeInfos;    
  }    
}   
/**
 * CopyRight (C) 2006-2009 yy
 * @author yy
 * @project jbpm
 * @version 1.0
 * @mail yy629_86 at 163 dot com
 * @date 2009-9-6 下午06:00:14
 * @description
 */
package sofocus.bpm.jbpm.jpdl.model;

import java.awt.Point;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class JpdlModel {
  private Map<String, Node> nodes = new LinkedHashMap<String, Node>();
  public static final int RECT_OFFSET_X = -7;
  public static final int RECT_OFFSET_Y = -8;
  public static final int DEFAULT_PIC_SIZE = 48;

  private final static Map<String, Object> nodeInfos = new HashMap<String, Object>();
  static {
    nodeInfos.put("start", "start_event_empty.png");
    nodeInfos.put("end", "end_event_terminate.png");
    nodeInfos.put("end-cancel", "end_event_cancel.png");
    nodeInfos.put("end-error", "end_event_error.png");
    nodeInfos.put("decision", "gateway_exclusive.png");
    nodeInfos.put("fork", "gateway_parallel.png");
    nodeInfos.put("join", "gateway_parallel.png");
    nodeInfos.put("state", null);
    nodeInfos.put("hql", null);
    nodeInfos.put("sql", null);
    nodeInfos.put("java", null);
    nodeInfos.put("script", null);
    nodeInfos.put("task", null);
    nodeInfos.put("sub-process", null);
    nodeInfos.put("custom", null);
  }

  public JpdlModel(InputStream is) throws Exception {
    this(new SAXReader().read(is).getRootElement());
  }

  @SuppressWarnings("unchecked")
  private JpdlModel(Element rootEl) throws Exception {
    for (Element el : (List<Element>) rootEl.elements()) {
      String type = el.getQName().getName();
      if (!nodeInfos.containsKey(type)) { // 不是可展示的节点
        continue;
      }
      String name = null;
      if (el.attribute("name") != null) {
        name = el.attributeValue("name");
      }
      String[] location = el.attributeValue("g").split(",");
      int x = Integer.parseInt(location[0]);
      int y = Integer.parseInt(location[1]);
      int w = Integer.parseInt(location[2]);
      int h = Integer.parseInt(location[3]);

      if (nodeInfos.get(type) != null) {
        w = DEFAULT_PIC_SIZE;
        h = DEFAULT_PIC_SIZE;
      } else {
        x -= RECT_OFFSET_X;
        y -= RECT_OFFSET_Y;
        w += (RECT_OFFSET_X + RECT_OFFSET_X);
        h += (RECT_OFFSET_Y + RECT_OFFSET_Y);
      }
      Node node = new Node(name, type, x, y, w, h);
      parserTransition(node, el);
      nodes.put(name, node);
    }
  }

  @SuppressWarnings("unchecked")
  private void parserTransition(Node node, Element nodeEl) {
    for (Element el : (List<Element>) nodeEl.elements("transition")) {
      String label = el.attributeValue("name");
      String to = el.attributeValue("to");
      Transition transition = new Transition(label, to);
      String g = el.attributeValue("g");
      if (g != null && g.length() > 0) {
        if (g.indexOf(":") < 0) {
          transition.setLabelPosition(getPoint(g));
        } else {
          String[] p = g.split(":");
          transition.setLabelPosition(getPoint(p[1]));
          String[] lines = p[0].split(";");
          for (String line : lines) {
            transition.addLineTrace(getPoint(line));
          }
        }
      }
      node.addTransition(transition);
    }
  }

  private Point getPoint(String exp) {
    if (exp == null || exp.length() == 0) {
      return null;
    }
    String[] p = exp.split(",");
    return new Point(Integer.valueOf(p[0]), Integer.valueOf(p[1]));
  }

  public Map<String, Node> getNodes() {
    return nodes;
  }
    public static Map<String, Object> getNodeInfos() {
    return nodeInfos;
  }
}

根据JpdlModel绘制出流程图

/**   
 * CopyRight (C) 2006-2009 yy   
 * @author yy   
 * @project Jbpm   
 * @version 1.0   
 * @mail yy629_86 at 163 dot com   
 * @date 2009-9-6 下午06:00:14   
 * @description   
 */   
package sofocus.bpm.jbpm.jpdl;    
   
import java.awt.*;    
import java.awt.font.FontRenderContext;    
import java.awt.geom.Rectangle2D;    
import java.awt.image.BufferedImage;    
import java.io.IOException;    
import java.util.List;    
import java.util.Map;    
   
import javax.imageio.ImageIO;    
   
import sofocus.bpm.jbpm.jpdl.model.JpdlModel;    
import sofocus.bpm.jbpm.jpdl.model.Node;    
import sofocus.bpm.jbpm.jpdl.model.Transition;    
   
/** 
 * @author yeyong   
 *    
 */   
public class JpdlModelDrawer {    
  public static final int RECT_OFFSET_X = JpdlModel.RECT_OFFSET_X;    
  public static final int RECT_OFFSET_Y = JpdlModel.RECT_OFFSET_Y;    
  public static final int RECT_ROUND = 25;    
   
  public static final int DEFAULT_FONT_SIZE = 12;    
   
  public static final Color DEFAULT_STROKE_COLOR = Color.decode("#03689A");    
  public static final Stroke DEFAULT_STROKE = new BasicStroke(2);    
   
  public static final Color DEFAULT_LINE_STROKE_COLOR = Color.decode("#808080");    
  public static final Stroke DEFAULT_LINE_STROKE = new BasicStroke(1);    
   
  public static final Color DEFAULT_FILL_COLOR = Color.decode("#F6F7FF");    
   
  private final static Map<String, Object> nodeInfos = JpdlModel.getNodeInfos();    
   
  public BufferedImage draw(JpdlModel jpdlModel) throws IOException {    
    Rectangle dimension = getCanvasDimension(jpdlModel);    
    BufferedImage bi = new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB);    
    Graphics2D g2 = bi.createGraphics();    
    g2.setColor(Color.WHITE);    
    g2.fillRect(0, 0, dimension.width, dimension.height);    
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);    
    Font font = new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE);    
    g2.setFont(font);    
    Map<String, Node> nodes = jpdlModel.getNodes();    
    drawNode(nodes, g2, font);    
    drawTransition(nodes, g2);    
    return bi;    
  }    
   
  /** 
   * 获得图片的矩形大小   
   *    
   * @return   
   */   
  private Rectangle getCanvasDimension(JpdlModel jpdlModel) {    
    Rectangle rectangle = new Rectangle();    
    Rectangle rect;    
    for (Node node : jpdlModel.getNodes().values()) {    
      rect = node.getRectangle();    
      if (rect.getMaxX() > rectangle.getMaxX()) {    
        rectangle.width = (int) rect.getMaxX();    
      }    
      if (rect.getMaxY() > rectangle.getMaxY()) {    
        rectangle.height = (int) rect.getMaxY();    
      }    
      for (Transition transition : node.getTransitions()) {    
        List<Point> trace = transition.getLineTrace();    
        for (Point point : trace) {    
          if (rectangle.getMaxX() < point.x) {    
            rectangle.width = point.x;    
          }    
          if (rectangle.getMaxY() < point.y) {    
            rectangle.height = point.y;    
          }    
        }    
      }    
    }    
    rectangle.width += 60;    
    rectangle.height += 20;    
    return rectangle;    
  }    
   
  /** 
   * @param g2   
   * @throws IOException   
   */   
  private void drawTransition(Map<String, Node> nodes, Graphics2D g2) throws IOException {    
    g2.setStroke(DEFAULT_LINE_STROKE);    
    g2.setColor(DEFAULT_LINE_STROKE_COLOR);    
    for (Node node : nodes.values()) {    
      for (Transition transition : node.getTransitions()) {    
        String to = transition.getTo();    
        Node toNode = nodes.get(to);    
        List<Point> trace = new LinkedList<Point>(transition.getLineTrace());    
        int len = trace.size() + 2;    
        trace.add(0, new Point(node.getCenterX(), node.getCenterY()));    
        trace.add(new Point(toNode.getCenterX(), toNode.getCenterY()));    
        int[] xPoints = new int[len];    
        int[] yPoints = new int[len];    
        for (int i = 0; i < len; i++) {    
          xPoints[i] = trace.get(i).x;    
          yPoints[i] = trace.get(i).y;    
        }    
        final int taskGrow = 4;    
        final int smallGrow = -2;    
        int grow = 0;    
        if (nodeInfos.get(node.getType()) != null) {    
          grow = smallGrow;    
        } else {    
          grow = taskGrow;    
        }    
        Point p = GeometryUtils.getRectangleLineCrossPoint(node.getRectangle(), new Point(xPoints[1],    
            yPoints[1]), grow);    
        if (p != null) {    
          xPoints[0] = p.x;    
          yPoints[0] = p.y;    
        }    
        if (nodeInfos.get(toNode.getType()) != null) {    
          grow = smallGrow;    
        } else {    
          grow = taskGrow;    
        }    
        p = GeometryUtils.getRectangleLineCrossPoint(toNode.getRectangle(), new Point(xPoints[len - 2],    
            yPoints[len - 2]), grow);    
        if (p != null) {    
          xPoints[len - 1] = p.x;    
          yPoints[len - 1] = p.y;    
        }    
        g2.drawPolyline(xPoints, yPoints, len);    
        drawArrow(g2, xPoints[len - 2], yPoints[len - 2], xPoints[len - 1], yPoints[len - 1]);    
        String label = transition.getLabel();    
        if (label != null && label.length() > 0) {    
          int cx, cy;    
          if (len % 2 == 0) {    
            cx = (xPoints[len / 2 - 1] + xPoints[len / 2]) / 2;    
            cy = (yPoints[len / 2 - 1] + yPoints[len / 2]) / 2;    
          } else {    
            cx = xPoints[len / 2];    
            cy = yPoints[len / 2];    
          }    
          Point labelPoint = transition.getLabelPosition();    
          if (labelPoint != null) {    
            cx += labelPoint.x;    
            cy += labelPoint.y;    
          }    
          cy -= RECT_OFFSET_Y + RECT_OFFSET_Y / 2;    
          g2.drawString(label, cx, cy);    
        }    
      }    
    }    
  }    
   
  private void drawArrow(Graphics2D g2, int x1, int y1, int x2, int y2) {    
    final double len = 8.0;    
    double slopy = Math.atan2(y2 - y1, x2 - x1);    
    double cosy = Math.cos(slopy);    
    double siny = Math.sin(slopy);    
    int[] xPoints = { 0, x2, 0 };    
    int[] yPoints = { 0, y2, 0 };    
    double a = len * siny, b = len * cosy;    
    double c = len / 2.0 * siny, d = len / 2.0 * cosy;    
    xPoints[0] = x2 - (int) (b + c);    
    yPoints[0] = y2 - (int) (a - d);    
    xPoints[2] = x2 - (int) (b - c);    
    yPoints[2] = y2 - (int) (d + a);    
        
    g2.fillPolygon(xPoints, yPoints, 3);    
  }    
   
  /** 
   * @param g2   
   * @throws IOException   
   */   
  private void drawNode(Map<String, Node> nodes, Graphics2D g2, Font font) throws IOException {    
    for (Node node : nodes.values()) {    
      String name = node.getName();    
      if (nodeInfos.get(node.getType()) != null) {    
        BufferedImage bi2 = ImageIO.read(getClass().getResourceAsStream(    
            "/icons/48/" + nodeInfos.get(node.getType())));    
        g2.drawImage(bi2, node.getX(), node.getY(), null);    
      } else {    
        int x = node.getX();    
        int y = node.getY();    
        int w = node.getWitdth();    
        int h = node.getHeight();    
        g2.setColor(DEFAULT_FILL_COLOR);    
        g2.fillRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);    
        g2.setColor(DEFAULT_STROKE_COLOR);    
        g2.setStroke(DEFAULT_STROKE);    
        g2.drawRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);    
   
        FontRenderContext frc = g2.getFontRenderContext();    
        Rectangle2D r2 = font.getStringBounds(name, frc);    
        int xLabel = (int) (node.getX() + ((node.getWitdth() - r2.getWidth()) / 2));    
        int yLabel = (int) ((node.getY() + ((node.getHeight() - r2.getHeight()) / 2)) - r2.getY());    
        g2.setStroke(DEFAULT_LINE_STROKE);    
        g2.setColor(Color.black);    
        g2.drawString(name, xLabel, yLabel);    
      }    
    }    
  }    
}   
/**
 * CopyRight (C) 2006-2009 yy
 * @author yy
 * @project Jbpm
 * @version 1.0
 * @mail yy629_86 at 163 dot com
 * @date 2009-9-6 下午06:00:14
 * @description
 */
package sofocus.bpm.jbpm.jpdl;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import sofocus.bpm.jbpm.jpdl.model.JpdlModel;
import sofocus.bpm.jbpm.jpdl.model.Node;
import sofocus.bpm.jbpm.jpdl.model.Transition;

/**
 * @author yeyong
 * 
 */
public class JpdlModelDrawer {
  public static final int RECT_OFFSET_X = JpdlModel.RECT_OFFSET_X;
  public static final int RECT_OFFSET_Y = JpdlModel.RECT_OFFSET_Y;
  public static final int RECT_ROUND = 25;

  public static final int DEFAULT_FONT_SIZE = 12;

  public static final Color DEFAULT_STROKE_COLOR = Color.decode("#03689A");
  public static final Stroke DEFAULT_STROKE = new BasicStroke(2);

  public static final Color DEFAULT_LINE_STROKE_COLOR = Color.decode("#808080");
  public static final Stroke DEFAULT_LINE_STROKE = new BasicStroke(1);

  public static final Color DEFAULT_FILL_COLOR = Color.decode("#F6F7FF");

  private final static Map<String, Object> nodeInfos = JpdlModel.getNodeInfos();

  public BufferedImage draw(JpdlModel jpdlModel) throws IOException {
    Rectangle dimension = getCanvasDimension(jpdlModel);
    BufferedImage bi = new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = bi.createGraphics();
    g2.setColor(Color.WHITE);
    g2.fillRect(0, 0, dimension.width, dimension.height);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Font font = new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE);
    g2.setFont(font);
    Map<String, Node> nodes = jpdlModel.getNodes();
    drawNode(nodes, g2, font);
    drawTransition(nodes, g2);
    return bi;
  }

  /**
   * 获得图片的矩形大小
   * 
   * @return
   */
  private Rectangle getCanvasDimension(JpdlModel jpdlModel) {
    Rectangle rectangle = new Rectangle();
    Rectangle rect;
    for (Node node : jpdlModel.getNodes().values()) {
      rect = node.getRectangle();
      if (rect.getMaxX() > rectangle.getMaxX()) {
        rectangle.width = (int) rect.getMaxX();
      }
      if (rect.getMaxY() > rectangle.getMaxY()) {
        rectangle.height = (int) rect.getMaxY();
      }
      for (Transition transition : node.getTransitions()) {
        List<Point> trace = transition.getLineTrace();
        for (Point point : trace) {
          if (rectangle.getMaxX() < point.x) {
            rectangle.width = point.x;
          }
          if (rectangle.getMaxY() < point.y) {
            rectangle.height = point.y;
          }
        }
      }
    }
    rectangle.width += 60;
    rectangle.height += 20;
    return rectangle;
  }

  /**
   * @param g2
   * @throws IOException
   */
  private void drawTransition(Map<String, Node> nodes, Graphics2D g2) throws IOException {
    g2.setStroke(DEFAULT_LINE_STROKE);
    g2.setColor(DEFAULT_LINE_STROKE_COLOR);
    for (Node node : nodes.values()) {
      for (Transition transition : node.getTransitions()) {
        String to = transition.getTo();
        Node toNode = nodes.get(to);
        List<Point> trace = new LinkedList<Point>(transition.getLineTrace());
        int len = trace.size() + 2;
        trace.add(0, new Point(node.getCenterX(), node.getCenterY()));
        trace.add(new Point(toNode.getCenterX(), toNode.getCenterY()));
        int[] xPoints = new int[len];
        int[] yPoints = new int[len];
        for (int i = 0; i < len; i++) {
          xPoints[i] = trace.get(i).x;
          yPoints[i] = trace.get(i).y;
        }
        final int taskGrow = 4;
        final int smallGrow = -2;
        int grow = 0;
        if (nodeInfos.get(node.getType()) != null) {
          grow = smallGrow;
        } else {
          grow = taskGrow;
        }
        Point p = GeometryUtils.getRectangleLineCrossPoint(node.getRectangle(), new Point(xPoints[1],
            yPoints[1]), grow);
        if (p != null) {
          xPoints[0] = p.x;
          yPoints[0] = p.y;
        }
        if (nodeInfos.get(toNode.getType()) != null) {
          grow = smallGrow;
        } else {
          grow = taskGrow;
        }
        p = GeometryUtils.getRectangleLineCrossPoint(toNode.getRectangle(), new Point(xPoints[len - 2],
            yPoints[len - 2]), grow);
        if (p != null) {
          xPoints[len - 1] = p.x;
          yPoints[len - 1] = p.y;
        }
        g2.drawPolyline(xPoints, yPoints, len);
        drawArrow(g2, xPoints[len - 2], yPoints[len - 2], xPoints[len - 1], yPoints[len - 1]);
        String label = transition.getLabel();
        if (label != null && label.length() > 0) {
          int cx, cy;
          if (len % 2 == 0) {
            cx = (xPoints[len / 2 - 1] + xPoints[len / 2]) / 2;
            cy = (yPoints[len / 2 - 1] + yPoints[len / 2]) / 2;
          } else {
            cx = xPoints[len / 2];
            cy = yPoints[len / 2];
          }
          Point labelPoint = transition.getLabelPosition();
          if (labelPoint != null) {
            cx += labelPoint.x;
            cy += labelPoint.y;
          }
          cy -= RECT_OFFSET_Y + RECT_OFFSET_Y / 2;
          g2.drawString(label, cx, cy);
        }
      }
    }
  }

  private void drawArrow(Graphics2D g2, int x1, int y1, int x2, int y2) {
    final double len = 8.0;
    double slopy = Math.atan2(y2 - y1, x2 - x1);
    double cosy = Math.cos(slopy);
    double siny = Math.sin(slopy);
    int[] xPoints = { 0, x2, 0 };
    int[] yPoints = { 0, y2, 0 };
    double a = len * siny, b = len * cosy;
    double c = len / 2.0 * siny, d = len / 2.0 * cosy;
    xPoints[0] = x2 - (int) (b + c);
    yPoints[0] = y2 - (int) (a - d);
    xPoints[2] = x2 - (int) (b - c);
    yPoints[2] = y2 - (int) (d + a);
    
    g2.fillPolygon(xPoints, yPoints, 3);
  }

  /**
   * @param g2
   * @throws IOException
   */
  private void drawNode(Map<String, Node> nodes, Graphics2D g2, Font font) throws IOException {
    for (Node node : nodes.values()) {
      String name = node.getName();
      if (nodeInfos.get(node.getType()) != null) {
        BufferedImage bi2 = ImageIO.read(getClass().getResourceAsStream(
            "/icons/48/" + nodeInfos.get(node.getType())));
        g2.drawImage(bi2, node.getX(), node.getY(), null);
      } else {
        int x = node.getX();
        int y = node.getY();
        int w = node.getWitdth();
        int h = node.getHeight();
        g2.setColor(DEFAULT_FILL_COLOR);
        g2.fillRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);
        g2.setColor(DEFAULT_STROKE_COLOR);
        g2.setStroke(DEFAULT_STROKE);
        g2.drawRoundRect(x, y, w, h, RECT_ROUND, RECT_ROUND);

        FontRenderContext frc = g2.getFontRenderContext();
        Rectangle2D r2 = font.getStringBounds(name, frc);
        int xLabel = (int) (node.getX() + ((node.getWitdth() - r2.getWidth()) / 2));
        int yLabel = (int) ((node.getY() + ((node.getHeight() - r2.getHeight()) / 2)) - r2.getY());
        g2.setStroke(DEFAULT_LINE_STROKE);
        g2.setColor(Color.black);
        g2.drawString(name, xLabel, yLabel);
      }
    }
  }
}

工具类,用来计算一些坐标的:

/**   
 * CopyRight (C) 2006-2009 yy   
 * @author yy   
 * @project jbpm   
 * @version 1.0   
 * @mail yy629_86 at 163 dot com   
 * @date 2009-9-11 上午06:16:26   
 * @description   
 */   
package sofocus.bpm.jbpm.jpdl;    
   
import java.awt.Point;    
import java.awt.Rectangle;    
   
/** 
 * @author yeyong   
 *    
 */   
public class GeometryUtils {    
  /** 
   * 获得直线(x1,y1)-(x2,y2)的斜率   
   *    
   * @param x1   
   * @param y1   
   * @param x2   
   * @param y2   
   * @return   
   */   
  public static double getSlope(int x1, int y1, int x2, int y2) {    
    return ((double) y2 - y1) / (x2 - x1);    
  }    
   
  /** 
   * 获得直线(x1,y1)-(x2,y2)的y轴截距   
   *    
   * @param x1   
   * @param y1   
   * @param x2   
   * @param y2   
   * @return   
   */   
  public static double getYIntercep(int x1, int y1, int x2, int y2) {    
    return y1 - x1 * getSlope(x1, y1, x2, y2);    
  }    
  /** 
   * 获得矩形的中点   
   *    
   * @param rect   
   * @return   
   */   
  public static Point getRectangleCenter(Rectangle rect) {    
    return new Point((int) rect.getCenterX(), (int) rect.getCenterY());    
  }    
   
  /** 
   * 获得矩形中心p0与p1的线段和矩形的交点   
   *    
   * @param rectangle   
   * @param p1   
   * @return   
   */   
  public static Point getRectangleLineCrossPoint(Rectangle rectangle, Point p1, int grow) {    
    Rectangle rect = rectangle.getBounds();    
    rect.grow(grow, grow);    
    Point p0 = GeometryUtils.getRectangleCenter(rect);    
   
    if (p1.x == p0.x) {    
      if (p1.y < p0.y) {    
        return new Point(p0.x, rect.y);    
      }    
      return new Point(p0.x, rect.y + rect.height);    
    }    
   
    if (p1.y == p0.y) {    
      if (p1.x < p0.x) {    
        return new Point(rect.x, p0.y);    
      }    
      return new Point(rect.x + rect.width, p0.y);    
    }    
   
    double slope = GeometryUtils.getSlope(p0.x, p0.y, rect.x, rect.y);    
    double slopeLine = GeometryUtils.getSlope(p0.x, p0.y, p1.x, p1.y);    
    double yIntercep = GeometryUtils.getYIntercep(p0.x, p0.y, p1.x, p1.y);    
   
    if (Math.abs(slopeLine) > slope - 1e-2) {    
      if (p1.y < rect.y) {    
        return new Point((int) ((rect.y - yIntercep) / slopeLine), rect.y);    
      } else {    
        return new Point((int) ((rect.y + rect.height - yIntercep) / slopeLine), rect.y + rect.height);    
      }    
    }    
    if (p1.x < rect.x) {    
      return new Point(rect.x, (int) (slopeLine * rect.x + yIntercep));    
    } else {    
      return new Point(rect.x + rect.width, (int) (slopeLine * (rect.x + rect.width) + yIntercep));    
    }    
  }    
}   

测试:

public static void main(String[] args) {   // TODO Auto-generated method stub   try {    File file = new File("D:/test.jpdl.xml");    InputStream is = new FileInputStream(file);    JpdlModel jpdlModel = new JpdlModel (is);        ImageIO.write(new JpdlModelDrawer().draw(jpdlModel), "png", new File("D:/test.png"));   } catch (FileNotFoundException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (IOException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (Exception e) {    // TODO Auto-generated catch block    e.printStackTrace();   }

 }

猜你喜欢

转载自squall140.iteye.com/blog/1311717