2015-04-28 48 views
2

我的图形包含具有单个传出边的矩形顶点和具有两个传出边的菱形形状的顶点。如何在jgraphx图形中创建所需表单的边界?

我使用的是mxCompactTreeLayout,除了第二种类型的顶点边缘对我来说看起来是错误的,大多数情况都可以。

我希望他们看起来像在画面rhombus shaped vertex with two edges

相反,边连接到菱形的底部段。

我该怎么做才能使边缘看起来像所需。

编辑:添加源代码。

PtNodeVertex.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.model.mxCell; 
import com.mxgraph.model.mxGeometry; 
import com.mxgraph.util.mxPoint; 
import com.mxgraph.util.mxRectangle; 
import com.mxgraph.util.mxUtils; 
import org.jsc.core.ast.IResult; 
import org.jsc.core.ptree.INodeCompleter; 
import org.jsc.core.ptree.PtNode; 
import org.jsc.core.term.ITerm; 
import org.jsc.core.term.MethodInvocationTerm; 
import org.jsc.core.term.expressions.ConditionalExpression; 
import org.jsc.core.term.expressions.InstanceCreationExpression; 
import org.jsc.core.term.expressions.VariableDeclarationTerm; 
import org.jsc.core.term.statement.BlockTerm; 
import org.jsc.core.term.statement.IfElse; 
import org.jsc.core.term.statement.SwitchStatement; 
import org.jsc.core.visualization.jgraphx.Edge.EdgeType; 

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import static java.lang.Math.max; 
import static java.lang.String.format; 

class PtNodeVertex extends mxCell 
{ 
    private static Map<PtNode, PtNodeVertex> completingNodesToViews = new HashMap<PtNode, PtNodeVertex>(); 

    private final PtNode node; 

    protected mxCell[] labels; 

    private List<PtNodeVertex> successors = new ArrayList<PtNodeVertex>(1); 

    private PtNodeVertex predecessor; 

    protected Edge[] edgeArray; 

    private int index; 

    PtNodeVertex(Object parent, PtNode value, String style) 
    { 
     super(parent, null, style); 

     node = value; 

     setVertex(true); 
     setVisible(true); 
     setGeometry(new mxGeometry()); 
     setStyle("defaultVertex;fillColor=none;strokeColor=black;strokeWidth=2.5"); 

     labels = new mxCell[ getLabelsCount() ]; 

     createLabels(); 
     calcBounds(); 
     createEdges(); 
    } 

    protected Edge[] createEdges() 
    { 
     int n = getMaxSuccessorsCount(); 
     if (n == 0) 
     { 
      return new Edge[ 0 ]; 
     } 
     edgeArray = new Edge[ n ]; 
     Edge edge = new Edge(null, this); 
     edgeArray[ 0 ] = edge; 

     return edgeArray; 
    } 

    int getLabelsCount() 
    { 
     return 4; 
    } 

    int getMaxSuccessorsCount() 
    { 
     return 1; 
    } 

    final PtNode getNode() 
    { 
     return node; 
    } 

    protected void createLabels() 
    { 
     ITerm t = node.getTerm(); 
     IResult tv = node.getTermValue(); 

     labels[ 0 ] = createTextLabel(format("Term [%s]:", t.getClass().getSimpleName())); 
     labels[ 1 ] = createTextLabel(node.getTerm().toString(), true); 
     labels[ 2 ] = createTextLabel(format("Term value: %s", tv == null ? "n/a" : tv)); 
     labels[ 3 ] = createTextLabel(format("State: %s", node.getState())); 
    } 

    protected void calcBounds() 
    { 
     mxGeometry b0 = labels[ 0 ].getGeometry(); 
     mxGeometry b1 = labels[ 1 ].getGeometry(); 
     mxGeometry b2 = labels[ 2 ].getGeometry(); 
     mxGeometry b3 = labels[ 3 ].getGeometry(); 

     double w = Math.max(b0.getWidth(), Math.max(b1.getWidth(), Math.max(b2.getWidth(), b3.getWidth()))); 
     double h = b0.getHeight() + b1.getHeight() + b2.getHeight() + b3.getHeight(); 


     mxGeometry b = getGeometry(); 
     double x = b.getX() + 5; 
     double y = b.getY() + 5; 

     double x2 = x;//+ 5 + w01 + 5; 
     double y2 = y; 

     double x3 = x2; 
     double y3 = y2 + b2.getHeight(); 

     double x0 = x; 
     double y0 = y3 + b3.getHeight(); 

     double x1 = x0; 
     double y1 = y0 + b0.getHeight(); 

     b.setWidth(w + 10); 
     b.setHeight(h + 10); 

     b0.setX(x0); 
     b0.setY(y0); 

     b1.setX(x1); 
     b1.setY(y1); 

     b2.setX(x2); 
     b2.setY(y2); 

     b3.setX(x3); 
     b3.setY(y3); 
    } 

    private static String prepareText(String s) 
    { 
     s = adjustNL(s); 
     // s = StringEscapeUtils.unescapeHtml4(s); 

     return s; 
    } 

    private static String adjustNL(String s) 
    { 
     s = s.replaceAll("\r\n", "\n"); 
     s = s.replaceAll("\r", "\n"); 

     return s; 
    } 

    protected mxCell createTextLabel(String text) 
    { 
     return createTextLabel(text, false); 
    } 

    protected mxCell createTextLabel(String text, boolean framed) 
    { 
     mxCell label = new mxCell(); 
     // System.out.print(text); 
     text = prepareText(text); 
     //  text = mxUtils.createHtmlDocument(new HashMap<String, Object>(), text, 1, 0, 
     //    "<style type=\"text/css\">.selectRef { " + 
     //      "font-size:9px;font-weight:normal; }</style>"); 
     label.setValue(text); 
     mxRectangle b = mxUtils.getLabelSize(text, new HashMap<String, Object>(), false, 1.0); 
     mxGeometry geometry = new mxGeometry(b.getX(), b.getY(), b.getWidth(), b.getHeight()); 

     label.setVertex(true); 
     label.setGeometry(geometry); 
     label.setVisible(true); 
     label.setParent(this); 
     this.insert(label); 
     label.setConnectable(false); 
     label.setStyle(format("defaultVertex;fillColor=none%s", (framed ? ";strokeColor=blue" : ";strokeColor=none"))); 

     return label; 
    } 

    public static mxCell create(Object parent, PtNode node, String style) 
    { 
     PtNodeVertex vertex; 

     if (isCompletingNode(node)) 
     { 
      vertex = new PtNodeVertex(parent, node, style); 

      completingNodesToViews.put(node, vertex); 
     } 
     else if (node instanceof INodeCompleter) 
     { 
      vertex = new NodeCompleterVertex(parent, node, style); 
      completingNodesToViews.put(node, vertex); 
     } 
     else if (node.getTerm() instanceof IfElse) 
     { 
      vertex = new IfElseNodeVertex(parent, node, style); 
     } 
     else if (node.getTerm() instanceof ConditionalExpression) 
     { 
      vertex = new ConditionalNodeVertex(parent, node, style); 
     } 
     else if (node.getTerm() instanceof SwitchStatement) 
     { 
      vertex = new SwitchNodeVertex(parent, node, style); 
     } 
     else 
     { 
      vertex = new PtNodeVertex(parent, node, style); 
     } 

     return vertex; 
    } 

    private static boolean isCompletingNode(PtNode node) 
    { 
     return node.getTerm() instanceof BlockTerm || 
       node.getTerm() instanceof VariableDeclarationTerm || 
       node.getTerm() instanceof InstanceCreationExpression || 
       node.getTerm() instanceof MethodInvocationTerm; 
    } 

    Object getLabel(int i) 
    { 
     return labels[ i ]; 
    } 

    final int getSuccessorCount() 
    { 
     return successors.size(); 
    } 

    void addSuccessor(PtNodeVertex successor) 
    { 
     successors.add(successor); 
     successor.predecessor = this; 
    } 

    final PtNodeVertex getSuccessor(int i) 
    { 
     return successors.get(i); 
    } 

    final Edge getEdge(int i) 
    { 
     return edgeArray[ i ]; 
    } 

    protected EdgeType getDefaultEdgeType() 
    { 
     return EdgeType.TYPE_1; 
    } 

    public void setIndex(int index) 
    { 
     this.index = index; 
    } 

    public int getIndex() 
    { 
     return index; 
    } 
} 
` 

IfElseNodeVertex.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.model.mxGeometry; 
import com.mxgraph.util.mxPoint; 
import org.jsc.core.ptree.PtNode; 
import org.jsc.core.term.statement.IfElse; 
import org.jsc.core.visualization.jgraphx.Edge.EdgeType; 

import static java.lang.Math.max; 
import static java.lang.String.format; 
import static org.jsc.core.visualization.jgraphx.Direction.LEFT; 
import static org.jsc.core.visualization.jgraphx.Direction.RIGHT; 

class IfElseNodeVertex extends PtNodeVertex 
{ 
    private Edge thenEdge; 
    private Edge elseEdge; 


    IfElseNodeVertex(Object parent, PtNode value, String style) 
    { 
     super(parent, value, style); 

     if (value.getTerm().getClass() != IfElse.class) 
     { 
      throw new Error("IfElse term expected"); 
     } 
     if (value.getOuts().size() != 2) 
     { 
      throw new Error("IfElse must have 2 successors\n" + value.getTerm()); //or mat have 1 (without else 
     } 
     setStyle("vRhombus;`fillColor=none;strokeColor=green"); 
    } 

    @Override 
    protected void createLabels() 
    { 
     IfElse ifElse = (IfElse) getNode().getTerm(); 
     String termString = format("if(%s)", ifElse.getCondition()); 
     labels[ 0 ] = createTextLabel(termString); 
     labels[ 0 ].setStyle("\"vRhombus;shape=rhombus;fillColor=none;strokeColor=none"); 
     labels[ 0 ].setGeometry(new mxGeometry(0, 0, 300, 150)); 
    } 

    @Override 
    protected void calcBounds() 
    { 
     mxGeometry b0 = labels[ 0 ].getGeometry(); 

     double w = 50 + b0.getWidth() + 50; 
     double h = max(b0.getHeight(), w * 0.618); 

     mxGeometry b = getGeometry(); 
     double x = b.getX(); 
     double y = b.getY(); 

     double x0 = b0.getCenterX() - b0.getWidth()/2; 
     double y0 = b0.getCenterY(); 

     b.setWidth(300); 
     b.setHeight(150); 
    } 

    @Override 
    public int getLabelsCount() 
    { 
     return 1; 
    } 

    protected Edge[] createEdges() 
    { 
     int n = getMaxSuccessorsCount(); 
     if (n == 0) 
     { 
      return new Edge[ 0 ]; 
     } 
     edgeArray = new Edge[ n ]; 

     thenEdge = new IfElseEdge(null, this, "then", EdgeType.TYPE_2, LEFT); 
     elseEdge = new IfElseEdge(null, this, "else", EdgeType.TYPE_2, RIGHT); 

     edgeArray[ 0 ] = thenEdge; 
     edgeArray[ 1 ] = elseEdge; 

     return edgeArray; 
    } 

    @Override 
    public int getMaxSuccessorsCount() 
    { 
     return 2; 
    } 

    protected EdgeType getDefaultEdgeType() 
    { 
     return EdgeType.TYPE_2; 
    } 
} 

PtGraph.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.canvas.mxICanvas; 
import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.model.mxCell; 
import com.mxgraph.model.mxGeometry; 
import com.mxgraph.view.mxCellState; 
import com.mxgraph.view.mxGraph; 
import org.jsc.core.ptree.PtEdge; 
import org.jsc.core.ptree.PtNode; 

public class PtGraph extends mxGraph 
{ 
    private mxCompactTreeLayout layout; 

    @Override 
    public Object insertVertex(Object parent, 
           String id, 
           Object value, 
           double x, 
           double y, 
           double width, 
           double height, 
           String style, 
           boolean relative) 
    { 
     Object v = super.insertVertex(parent, id, value, x, y, width, height, style, relative); 

     if (v instanceof PtNodeVertex) 
     { 
      insertLabels((PtNodeVertex) v); 
     } 

     return v; 
    } 

    protected void insertLabels(PtNodeVertex v) 
    { 
     for (int i = 0; i < v.getLabelsCount(); i++) 
     { 
      addCell(v.getLabel(i), v); 
     } 
    } 

    @Override 
    public Object createVertex(Object parent, 
           String id, 
           Object value, 
           double x, 
           double y, 
           double width, 
           double height, 
           String style, 
           boolean relative 
    ) 
    { 
     if (!(value instanceof PtNode)) 
     { 
      return super.createVertex(parent, id, value, x, y, width, height, style, relative); 
     } 

     mxCell vertex; 
     PtNode node = (PtNode) value; 
     if (node == ProcessTreeSVGView.dummyNode) 
     { 
      vertex = new HaltVertex(parent); 
     } 
     else 
     { 
      vertex = PtNodeVertex.create(parent, node, null); 
     } 
     vertex.setId(id); 
     vertex.setVertex(true); 
     vertex.setConnectable(true); 
     mxGeometry geometry = new mxGeometry(x, y, width, height); 
     vertex.setGeometry(geometry); 

     return vertex; 
    } 
    @Override 
    public Object createEdge(Object parent, 
           String id, 
           Object value, 
           Object source, 
           Object target, 
           String style) 
    { 
     if (!(value instanceof PtEdge)) 
     { 
      return super.createEdge(parent, id, value, source, target, style); 
     } 
     PtEdge ptEdge = (PtEdge) value; 
     Edge edge = (Edge) Edge.create(parent, (PtNodeVertex) source, (PtNodeVertex)target, ptEdge.getContext(), null, layout); 
     edge.setId(id); 

     edge.setConnectable(false); 

     return edge; 
    } 

    @Override 
    public void drawState(mxICanvas canvas, mxCellState state, boolean drawLabel) 
    { 
     Object cell = state.getCell(); 
     drawLabel = !(cell instanceof PtNodeVertex) && drawLabel; 

     super.drawState(canvas, state, drawLabel); 
    } 

    public void setLayout(mxCompactTreeLayout layout) 
    { 
     this.layout = layout; 
    } 
} 

Edge.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.model.mxCell; 
import com.mxgraph.model.mxGeometry; 
import org.jsc.core.DriveContext; 

class Edge extends mxCell 
{ 
    enum EdgeType 
    { 
     TYPE_1, 
     TYPE_2 
    } 

    static mxCell create(Object parent, 
          PtNodeVertex source, 
          PtNodeVertex target, 
          DriveContext context, 
          String style, 
          mxCompactTreeLayout layout) 
    { 
     int index = target.getIndex(); 
     Edge edge = source.getEdge(index); 
     edge.setValue(context); 
     edge.setEdge(true); 
     edge.setLayoutParamsForEdge(layout); 

     return edge; 
    } 

    protected void setLayoutParamsForEdge(mxCompactTreeLayout layout) 
    { 
    } 

    Edge(Object parent, PtNodeVertex source) 
    { 
     mxGeometry geo = new mxGeometry(); 
     setEdge(true); 
     setGeometry(geo); 
    } 
} 

class IfElseEdge extends Edge 
{ 
    EdgeType type; 
    Direction direction; 

    IfElseEdge(Object parent, IfElseNodeVertex source, String text, EdgeType type, Direction direction) 
    { 
     super(parent, source); 

     this.type = type; 
     this.direction = direction; 

     mxGeometry geo = new mxGeometry(0, 0, 0, 0); 
     //geo.setRelative(true); 
     setGeometry(geo); 

     setStyle("rhombusEdge"); 

     mxCell sourceLabel = new mxCell(text, new mxGeometry(-1, 0, 0, 0), 
       direction == Direction.RIGHT ? 
         "resizable=0;align=left;verticalAlign=top;" : 
         "resizable=0;align=right;verticalAlign=top;" 
     ); 
     sourceLabel.getGeometry().setRelative(true); 
     sourceLabel.setConnectable(false); 
     sourceLabel.setVertex(true); 

     insert(sourceLabel); 

    } 

    @Override 
    protected void setLayoutParamsForEdge(mxCompactTreeLayout layout) 
    { 
     layout.setOrthogonalEdge(this, true); 
     layout.setEdgeStyleEnabled(this, true); 
    } 
} 

ProcessTreeSVGView.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.model.mxCell; 
import com.mxgraph.swing.mxGraphComponent; 
import com.mxgraph.util.mxConstants; 
import com.mxgraph.view.mxGraph; 
import com.mxgraph.view.mxPerimeter; 
import com.mxgraph.view.mxStylesheet; 
import org.apache.batik.dom.svg.SVGDOMImplementation; 
import org.apache.batik.svggen.SVGGraphics2D; 
import org.apache.batik.svggen.SVGGraphics2DIOException; 
import org.jsc.core.ptree.ProcessTree; 
import org.jsc.core.ptree.PtEdge; 
import org.jsc.core.ptree.PtNode; 
import org.w3c.dom.DOMImplementation; 
import org.w3c.dom.Element; 
import org.w3c.dom.svg.SVGDocument; 

import java.awt.*; 
import java.io.*; 
import java.util.Hashtable; 
import java.util.Map; 

public class ProcessTreeSVGView 
{ 
    private static final String SVG_FILE_NAME = "C:\\users\\anthony\\g.svg"; 

    static SVGGraphics2D g; 

    private final mxGraph graph; 
    private final mxGraphComponent graphComponent; 
    private String style; 

    public final static PtNode dummyNode = new PtNode(); 
    public final static PtEdge dummyEdge = new PtEdge(); 

    /** 
    * Constructs a new frame that is initially invisible. 
    * <p> 
    * This constructor sets the component's locale property to the value 
    * returned by <code>JComponent.getDefaultLocale</code>. 
    * 
    * @exception java.awt.HeadlessException if GraphicsEnvironment.isHeadless() 
    * returns true. 
    * @see java.awt.GraphicsEnvironment#isHeadless 
    * @see java.awt.Component#setSize 
    * @see java.awt.Component#setVisible 
    * @see javax.swing.JComponent#getDefaultLocale 
    */ 
    public ProcessTreeSVGView(ProcessTree pTree) 
      throws HeadlessException, SVGGraphics2DIOException, FileNotFoundException, UnsupportedEncodingException 
    { 
     System.out.printf("\nSaving Process tree(s) in '%s' ... ", SVG_FILE_NAME); 
     // Create an SVG document. 
     DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); 
     String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; 
     SVGDocument doc = (SVGDocument) impl.createDocument(svgNS, "svg", null); 

     // Create a converter for this document. 
     g = new SVGGraphics2D(doc); 
     graph = new PtGraph(); 
     graphComponent = new mxGraphComponent(graph); 

     //First draw Graph to the SVGGraphics2D object using graph component objects draw method 
     drawTree(pTree); 

     // Do some drawing. 
     graphComponent.getGraphControl().drawGraph(g, true); 

     // Populate the document root with the generated SVG content. 
     Element root = doc.getDocumentElement(); 
     g.getRoot(root); 

     //Once every thing is drawn on graphics find root element and update this by adding additional values for the required fields. 
     // Element root = g.getRoot(); 
     Dimension size = graphComponent.getGraphControl().getPreferredSize(); 

     root.setAttributeNS(null, "width", size.width + ""); 
     root.setAttributeNS(null, "height", size.height + ""); 
     root.setAttributeNS(null, "viewBox", "0 0 " + size.width + " " + size.height); 


     OutputStream outStream = new FileOutputStream(SVG_FILE_NAME); 
     Writer out = new OutputStreamWriter(outStream, "UTF-8"); 
     g.stream(root, out); 

     System.out.println("done."); 

     runSVGViewer(SVG_FILE_NAME); 
    } 

    private void runSVGViewer(String svgFileName) 
    { 
     System.out.print("\nLoading SVG viewer ... "); 
     ProcessBuilder builder = new ProcessBuilder("C:\\Program Files (x86)\\Free Picture Solutions\\Free Svg Viewer\\SvgViewer.exe ", svgFileName); 
     try 
     { 
      builder.start(); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
      throw new Error(); 
     } 
     System.out.println("done."); 
    } 

    //================================================================================================================== 

    private void drawTree(ProcessTree pTree) 
    { 
     Object parent = graph.getDefaultParent(); 

     registerRhombusVertexStyle(graph); 

     mxCompactTreeLayout layout = setupLayout(graph); 

     graph.getModel().beginUpdate(); 
     mxCell v; 
     try 
     { 
      v = build(pTree.getRoot(), (mxCell) parent, 0); 
     } 
     finally 
     { 
      graph.getModel().endUpdate(); 
     } 

     layout.execute(parent, v); 

    } 

    private mxCompactTreeLayout setupLayout(mxGraph graph) 
    { 
     mxCompactTreeLayout layout = new mxCompactTreeLayout(graph, false); 

     layout.setEdgeRouting(true); 
     layout.setHorizontal(false); 
     layout.setLevelDistance(100); 
     layout.setNodeDistance(50); 

     layout.setUseBoundingBox(true); 

     ((PtGraph) graph).setLayout(layout); 

     return layout; 
    } 

    private PtNodeVertex build(PtNode node, mxCell parent, int index) 
    { 
     PtNodeVertex source = insertVertex(node, parent, index); 
     if (node.getChildrenCount() == 0) 
     { 
      HaltVertex target = (HaltVertex) insertHaltVertex(parent); 

      source.addSuccessor(target); 
      insertEdge(parent, dummyEdge, source, target); 

      return source; 
     } 

     for (int i = 0; i < node.getChildrenCount(); i++) 
     { 
      PtNode node1 = node.getChild(i); 

      PtNodeVertex target = build(node1, parent, i); 

      source.addSuccessor(target); 
      insertEdge(parent, node1.getIn(), source, target); 
     } 

     return source; 
    } 

    PtNodeVertex insertVertex(PtNode node, mxCell parent, int index) 
    { 
     PtNodeVertex v = (PtNodeVertex) graph.insertVertex(parent, null, node, 0, 0, 0, 0, style); 
     v.setIndex(index); 

     return v; 
    } 

    private mxCell insertHaltVertex(mxCell parent) 
    { 
     mxCell v = (mxCell) graph.insertVertex(parent, null, dummyNode, 0, 0, 0, 0, style); 

     return v; 
    } 

    private void insertEdge(Object parent, PtEdge ptEdge, mxCell source, mxCell target) 
    { 
     if (!(source instanceof HaltVertex)) 
     { 
      graph.insertEdge(parent, null, ptEdge, source, target); 
     } 
    } 

    private static void registerRhombusVertexStyle(mxGraph graph) 
    { 
     mxStylesheet ss = graph.getStylesheet(); 

     Map<String, Object> style = new Hashtable<String, Object>(); 

     style.put(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_RHOMBUS); 
     style.put(mxConstants.STYLE_PERIMETER, mxPerimeter.RhombusPerimeter); 
     style.put(mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE); 
     style.put(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER); 
     style.put(mxConstants.STYLE_FILLCOLOR, "#C3D9FF"); 
     style.put(mxConstants.STYLE_STROKECOLOR, "#6482B9"); 
     style.put(mxConstants.STYLE_FONTCOLOR, "#774400"); 

     ss.putCellStyle("vRhombus", style); 

     style = ss.getDefaultEdgeStyle(); 
     style.put(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_ELBOW); 
     style.put(mxConstants.STYLE_ROUTING_CENTER_Y, 0.0); 

     ss.putCellStyle("rhombusEdge", style); 

//////////////////////////////////////////////////////////////////////////////////// 
     Map<String, Map<String, Object>> styles = ss.getStyles(); 

     for (String key : styles.keySet()) 
     { 
      Map<String, Object> _style = styles.get(key); 
      System.out.printf("\n%s =\n", key); 
      System.out.println("---------------------"); 

      for (String key1 : _style.keySet()) 
      { 
       System.out.printf("\n%s = %s", key1, _style.get(key1)); 
      } 
      System.out.println(); 
     } 

    } 
} 
+0

发布您的代码。 – CaffeineToCode

回答

0

我已经找到了答案。

一般来说,如果您无法使用边缘样式或其他东西来实现结果,那么您应该编写自己的布局。

它可以是从头开始编写的布局,也可以是现有布局实现的布局扩展或组合功能。

关于我的问题,我扩展mxCompactTreeLayout覆盖setEdgePoints方法。

的源代码:

PtCompactTreeLayout.java

package org.jsc.core.visualization.jgraphx; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.model.mxGeometry; 
import com.mxgraph.util.mxPoint; 
import com.mxgraph.view.mxGraph; 

import java.util.Collections; 
import java.util.List; 

public class PtCompactTreeLayout extends mxCompactTreeLayout 
{ 
    public PtCompactTreeLayout(mxGraph graph) 
    { 
     super(graph, false); 
    } 

    @Override 
    public void setEdgePoints(Object edge, List<mxPoint> points) 
    { 
     if (!(edge instanceof IfElseEdge)) 
     { 
      super.setEdgePoints(edge, points); 

      return; 
     } 
     IfElseEdge ifElseEdge = (IfElseEdge) edge; 
     IfElseNodeVertex v = (IfElseNodeVertex) ifElseEdge.getSource(); 
     mxGeometry geo = v.getGeometry(); 
     mxGeometry vb = ifElseEdge.getGeometry(); 
     if (vb == null) 
     { 
      super.setEdgePoints(edge, points); 

      return; 
     } 

     double xc = geo.getCenterX(); 
     double yc = geo.getCenterY(); 
     double w = geo.getWidth(); 
     double h = geo.getHeight(); 
     double xt; 

     double yt; 
     int i = (ifElseEdge == v.getEdge(0) ? 0 : 1); 
     PtNodeVertex vs = v.getSuccessor(i); 

     mxGeometry sgeo0 = v.getSuccessor(0).getGeometry(); 
     mxGeometry sgeo1 = v.getSuccessor(1).getGeometry(); 

     double ws0 = sgeo0.getWidth(); 

     xt = (i == 0 ? sgeo0.getCenterX() : sgeo1.getCenterX()); 
     yt = (i == 0 ? sgeo0.getY() : sgeo1.getY()); 

     vb.setTargetPoint(new mxPoint(xt, yt)); 

     double xm = xt; 

     mxPoint mp = new mxPoint(xm, yc); 
     vb.setPoints(Collections.singletonList(mp)); 
     vb.setSourcePoint(calcSourcePoint(v, i)); 
    } 

    private mxPoint calcSourcePoint(PtNodeVertex v, int i) 
    { 
     mxGeometry geom = v.getGeometry(); 

     double w = geom.getWidth(); 
     double xs = (i == 0 ? geom.getX() : geom.getX() + geom.getWidth()); 
     double ys = geom.getCenterY(); 

     return new mxPoint(xs, ys); 
    } 
} 
相关问题