如何在jgraphx的图形中创建所需形式的边缘

如何在jgraphx的图形中创建所需形式的边缘

本文介绍了如何在jgraphx的图形中创建所需形式的边缘?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的图形包含具有单个输出边缘的矩形顶点,以及具有两个输出边缘的菱形形状的顶点。

My graph contains rectangular vertices with single outgoing edge and the vertices of rhombus shape with two outgoing edges.

我使用 mxCompactTreeLayout ,并且大部分一切正常,除了第二种类型的顶点边缘看起来不对为了我。

I'm using mxCompactTreeLayout and mostly everything is ok except that edges of the vertices of the second type look wrong for me.

我想让他们看起来像在图片

I want them to look like in the picture

而是将边连接到菱形的底部。

Instead, edges connected to the bottom segments of the rhombus.

我做的是让边缘看起来像所希望的。

What should I do to get edges look as desired.

编辑:添加了源代码。

PtNodeVertex.java

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

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

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

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

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();
        }

    }
}


推荐答案

我找到了答案。

一般来说,如果使用边缘样式或其他方法未能达到结果,编写自己的布局。

In general, if you failed to achieve the result using edge styles or something else, then you should write your own layout.

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

It can be the layout written from scratch, or the layout extending or combining functionality of existing layout implementations.

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

Regarding my problem, I extend mxCompactTreeLayout overriding setEdgePoints method.

源代码:

PtCompactTreeLayout.java

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 );
    }
}

这篇关于如何在jgraphx的图形中创建所需形式的边缘?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 13:31