文章来源: 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(); } }