シーケンス図をJGraph X化してみた。
JGraphで描いていたシーケンス図を、JGraph Xで描き直してみた。
何よりもまず、できあがるシーケンスがかっこよくなったし、
ノードを動かした時のパフォーマンスも幾分か向上したみたい。
JGraphを使ってた時に感じていた、「これ、不要だろ」っていうAPI呼び出し
(例えばgraph.getGraphLayoutCache().insertとか)を使わなくて良くなったり、
ノードを作る時にnewを呼ばなくて良くなったりしたので、コードがすっきりした。
ただ、スタイルの扱いがちょっとイケてなくなった(APIがよく分からない)のが残念。
あと、長すぎるノードの文字列を自動的に省略をする方法も良く分からない。
この辺りはただの勉強不足かも知れないので、もうちょっと調べてみるけど。
そういえば、やっぱりGenericsとかは使えず、
むしろノードやエッジをjava.lang.Objectとして扱うことが逆に増えたんだけど
この辺りは「Swingでグラフを描きたい」っていう要望があるような現場は
そもそもJava1.4だろっていう事を考えれば、妥当なのかも。
とりあえず、ソースを貼っとく。
package cerot.blight.sequence; import java.awt.Color; import java.util.HashMap; import java.util.List; import java.util.Map; import cerot.blight.sequence.entity.Connector; import cerot.blight.sequence.entity.ConnectorType; import cerot.blight.sequence.entity.EndPoint; import cerot.blight.sequence.entity.Node; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxConstants; import com.mxgraph.util.mxRectangle; import com.mxgraph.view.mxGraph; public class SequenceCreator { /** 呼び出し線のスタイル */ private static final String STYLE_CALL = mxConstants.STYLE_ENDARROW + "=" + mxConstants.ARROW_OPEN + ";" + mxConstants.STYLE_VERTICAL_ALIGN + "=" + mxConstants.ALIGN_BOTTOM + ";"; /** 戻り線のスタイル */ private static final String STYLE_RETURN = mxConstants.STYLE_DASHED + "=1;" + mxConstants.STYLE_ENDARROW + "=" + mxConstants.ARROW_OPEN + ";" + mxConstants.STYLE_VERTICAL_ALIGN + "=" + mxConstants.ALIGN_BOTTOM + ";"; /** 生存線のスタイル */ private static final String STYLE_LIFELINE = mxConstants.STYLE_ENDARROW + "=" + mxConstants.NONE; /** ノードの幅 */ private int nodeWidth = 80; /** ノードの高さ */ private int nodeHeight = 20; /** ノードの間隔 */ private int nodeInterval = 10; /** 結線の間隔 */ private int edgeInterval = 25; private mxGraph graph; /** ノードセルのマップ */ private Map<Node, Object> nodeMap = new HashMap<Node, Object>(); /** 結線の数 */ private int edgeCount; /** * コンストラクタ。モデルの変換を行います。 * @param connectorList 結線のリスト */ public SequenceCreator(List<Connector> connectorList) { graph = new mxGraph(); for (Connector connector : connectorList) { createConnectorCell(connector); } // 生存線の作成 Object parent = this.graph.getDefaultParent(); for (Object nodeCell : this.nodeMap.values()) { Object endCell = createEndPointCell(nodeCell); graph.insertEdge(parent, null, null, nodeCell, endCell, STYLE_LIFELINE); } } /** * グラフの描画を行います。 */ public mxGraphComponent createGraphComponent() { mxGraphComponent component = new mxGraphComponent(this.graph); component.getViewport().setBackground(Color.WHITE); return component; } private void createConnectorCell(Connector connector) { EndPoint from = connector.getFrom(); EndPoint to = connector.getTo(); Object fromNodeCell = findParentNodeCell(from); Object fromCell = createEndPointCell(fromNodeCell); Object toNodeCell = findParentNodeCell(to); Object toCell = createEndPointCell(toNodeCell); Object parent = this.graph.getDefaultParent(); if (connector.getConnectorType() == ConnectorType.METHOD_RETURN) { graph.insertEdge(parent, null, connector.getName(), fromCell, toCell, STYLE_RETURN); } else { graph.insertEdge(parent, null, connector.getName(), fromCell, toCell, STYLE_CALL); } this.edgeCount++; } private Object findParentNodeCell(EndPoint endPoint) { Node node = endPoint.getParentNode(); Object result = findNodeCell(node); return result; } private Object createEndPointCell(Object nodeCell) { // X座標 = ノードの中央値 mxRectangle rectangle = this.graph.getCellBounds(nodeCell); double x = rectangle.getCenterX(); // Y座標 = 上端からの余白 + ノードの高さ + (結線の数 + 1) * 結線の間隔 int y = this.nodeInterval + this.nodeHeight + (this.edgeCount + 1) * edgeInterval; Object parent = this.graph.getDefaultParent(); Object result = this.graph.insertVertex(parent, null, null, x, y, 0, 0); return result; } private Object findNodeCell(Node node) { Object result = this.nodeMap.get(node); if (result == null) { Object parent = this.graph.getDefaultParent(); // X座標 = 左端からの余白 + ノード数 * (ノード幅 + ノード間隔) int x = this.nodeInterval + this.nodeMap.size() * (this.nodeWidth + this.nodeInterval); // Y座標 = 上端からの余白 int y = this.nodeInterval; result = this.graph.insertVertex(parent, null, node.getName(), x, y, nodeWidth, nodeHeight); this.nodeMap.put(node, result); } return result; } }
興味がある人は、以前のエントリで書いたJGraphのソースと比べてみると良いかも。
JGraphでシーケンス図を描いてみた。 - 谷本 心 in せろ部屋
SourceForgeの方にもコミットしといたので、Diffで見たほうが見やすいかも。
http://svn.sourceforge.jp/view/b-light/trunk/B-Light/src/main/java/cerot/blight/sequence/SequenceCreator.java?root=b-light&r1=2&r2=9