package graph; import java.awt.Point; import java.util.ArrayList; import org.eclipse.elk.graph.ElkEdge; import bk.ExtremalLayoutCalc.LayoutType; import view.NodeView; /** * Die Implementation einer Kante aus einem Layered Graphen. * Implementiert {@link LayeredGraphEdge}. * * @author kolja * */ public class LayeredEdge implements LayeredGraphEdge { private ElkEdge original; private ArrayList< LayeredGraphNode > sources; private ArrayList< LayeredGraphNode > targets; private LayeredGraphNode graph; private boolean reversed; private boolean dummy; private ArrayList< Point >[] bindPoints; private boolean[] conflicted; @SuppressWarnings("unchecked") public LayeredEdge( ElkEdge original, ArrayList< LayeredGraphNode > sources, ArrayList< LayeredGraphNode > targets, LayeredGraphNode graph ) { this.original = original; this.sources = sources; this.targets = targets; this.graph = graph; reversed = false; dummy = false; bindPoints = new ArrayList[ 5 ]; conflicted = new boolean[ 5 ]; for( int i = 0; i < 5; i++ ) { conflicted[ i ] = false; bindPoints[ i ] = new ArrayList<>(); } for( ArrayList bps : bindPoints ) { bps.add( null ); bps.add( null ); } } @Override public boolean isConflicted( LayoutType layout ) { if( layout == LayoutType.TOP_BOTTOM_LEFT ) return conflicted[ 0 ]; if( layout == LayoutType.TOP_BOTTOM_RIGHT ) return conflicted[ 1 ]; if( layout == LayoutType.BOTTOM_TOP_LEFT ) return conflicted[ 2 ]; if( layout == LayoutType.BOTTOM_TOP_RIGHT ) return conflicted[ 3 ]; if( layout == LayoutType.COMBINED ) return conflicted[ 4 ]; return false; } @Override public ArrayList calcEdgeCrossings() { ArrayList list = new ArrayList<>(); ArrayList l = graph.getContainedLayers().get( sources.get( 0 ).getLayer() ); ArrayList l2 = graph.getContainedLayers().get( targets.get( 0 ).getLayer() ); int startIndex = l.indexOf( sources.get( 0 ) ); int endIndex = l2.indexOf( targets.get( 0 ) ); for( int i = 0; i < l.size(); i++ ) { if( i == startIndex ) continue; for( LayeredGraphEdge e : l.get( i ).getOutgoingEdges() ) { int i2 = l2.indexOf( e.getTargets().get( 0 ) ); if( i2 == endIndex ) continue; if( i < startIndex && i2 > endIndex || i > startIndex && i2 < endIndex ) { if( !list.contains( e ) ) list.add( e ); } } } return list; }; @Override public void setConflicted( boolean conflicted, LayoutType layout ) { if( layout == null ) { this.conflicted[ 0 ] = conflicted; this.conflicted[ 1 ] = conflicted; this.conflicted[ 2 ] = conflicted; this.conflicted[ 3 ] = conflicted; this.conflicted[ 4 ] = conflicted; } if( layout == LayoutType.TOP_BOTTOM_LEFT ) this.conflicted[ 0 ] = conflicted; if( layout == LayoutType.TOP_BOTTOM_RIGHT ) this.conflicted[ 1 ] = conflicted; if( layout == LayoutType.BOTTOM_TOP_LEFT ) this.conflicted[ 2 ] = conflicted; if( layout == LayoutType.BOTTOM_TOP_RIGHT ) this.conflicted[ 3 ] = conflicted; if( layout == LayoutType.COMBINED ) this.conflicted[ 4 ] = conflicted; } @Override public void setStartPoint( int x, int y, LayoutType layout ) { if( layout == null ) { bindPoints[ 0 ].set( 0, new Point( x, y ) ); bindPoints[ 1 ].set( 0, new Point( x, y ) ); bindPoints[ 2 ].set( 0, new Point( x, y ) ); bindPoints[ 3 ].set( 0, new Point( x, y ) ); bindPoints[ 4 ].set( 0, new Point( x, y ) ); } if( layout == LayoutType.TOP_BOTTOM_LEFT ) bindPoints[ 0 ].set( 0, new Point( x, y ) ); if( layout == LayoutType.TOP_BOTTOM_RIGHT ) bindPoints[ 1 ].set( 0, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_LEFT ) bindPoints[ 2 ].set( 0, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_RIGHT ) bindPoints[ 3 ].set( 0, new Point( x, y ) ); if( layout == LayoutType.COMBINED ) bindPoints[ 4 ].set( 0, new Point( x, y ) ); } @Override public void addBindPoint( int x, int y, LayoutType layout ) { if( layout == null ) { bindPoints[ 0 ].add( bindPoints[ 0 ].size() - 1, new Point( x, y ) ); bindPoints[ 1 ].add( bindPoints[ 1 ].size() - 1, new Point( x, y ) ); bindPoints[ 2 ].add( bindPoints[ 2 ].size() - 1, new Point( x, y ) ); bindPoints[ 3 ].add( bindPoints[ 3 ].size() - 1, new Point( x, y ) ); bindPoints[ 4 ].add( bindPoints[ 4 ].size() - 1, new Point( x, y ) ); } if( layout == LayoutType.TOP_BOTTOM_LEFT ) bindPoints[ 0 ].add( bindPoints[ 0 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.TOP_BOTTOM_RIGHT ) bindPoints[ 1 ].add( bindPoints[ 1 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_LEFT ) bindPoints[ 2 ].add( bindPoints[ 2 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_RIGHT ) bindPoints[ 3 ].add( bindPoints[ 3 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.COMBINED ) bindPoints[ 4 ].add( bindPoints[ 4 ].size() - 1, new Point( x, y ) ); } @Override public void setEndPoint( int x, int y, LayoutType layout ) { if( layout == null ) { bindPoints[ 0 ].set( bindPoints[ 0 ].size() - 1, new Point( x, y ) ); bindPoints[ 1 ].set( bindPoints[ 1 ].size() - 1, new Point( x, y ) ); bindPoints[ 2 ].set( bindPoints[ 2 ].size() - 1, new Point( x, y ) ); bindPoints[ 3 ].set( bindPoints[ 3 ].size() - 1, new Point( x, y ) ); bindPoints[ 4 ].set( bindPoints[ 4 ].size() - 1, new Point( x, y ) ); } if( layout == LayoutType.TOP_BOTTOM_LEFT ) bindPoints[ 0 ].set( bindPoints[ 0 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.TOP_BOTTOM_RIGHT ) bindPoints[ 1 ].set( bindPoints[ 1 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_LEFT ) bindPoints[ 2 ].set( bindPoints[ 2 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.BOTTOM_TOP_RIGHT ) bindPoints[ 3 ].set( bindPoints[ 3 ].size() - 1, new Point( x, y ) ); if( layout == LayoutType.COMBINED ) bindPoints[ 4 ].set( bindPoints[ 4 ].size() - 1, new Point( x, y ) ); } @Override public ArrayList getLinePoints( LayoutType layout ) { NodeView sourceView = ((LayeredNode)sources.get( 0 )).getView( layout ); NodeView targetView = ((LayeredNode)targets.get( 0 )).getView( layout ); //if( bindPoints.get( 0 ) == null && sources.size() > 0 ) //{ setStartPoint( (int)sources.get( 0 ).getX( layout ) + sourceView.getScaledX( (int)sources.get( 0 ).getWidth( layout ) / 2 ), (int)sources.get( 0 ).getY( layout ) + sourceView.getPreferredSize().height - sourceView.getScaledY( 0 ), layout ); //} //if( bindPoints.get( bindPoints.size() - 1 ) == null && targets.size() > 0 ) //{ setEndPoint( (int)targets.get( 0 ).getX( layout ) + targetView.getScaledX( (int)targets.get( 0 ).getWidth( layout ) / 2 ) , (int)targets.get( 0 ).getY( layout ) + targetView.getScaledY( 0 ), layout ); //} if( layout == LayoutType.TOP_BOTTOM_LEFT ) return bindPoints[ 0 ]; if( layout == LayoutType.TOP_BOTTOM_RIGHT ) return bindPoints[ 1 ]; if( layout == LayoutType.BOTTOM_TOP_LEFT ) return bindPoints[ 2 ]; if( layout == LayoutType.BOTTOM_TOP_RIGHT ) return bindPoints[ 3 ]; if( layout == LayoutType.COMBINED ) return bindPoints[ 4 ]; return null; } @Override public ElkEdge getOriginalEdge() { return original; } @Override public void remove() { graph.removeEdge( this ); } @Override public ArrayList getSources() { return sources; } @Override public ArrayList getTargets() { return targets; } @Override public boolean isCrossLayerEdge() { int sl = sources.get( 0 ).getLayer(); for( LayeredGraphNode s : sources ) { if( sl != s.getLayer() ) return true; } int tl = targets.get( 0 ).getLayer(); if( Math.abs( tl - sl ) != 1 ) return true; for( LayeredGraphNode t : targets ) { if( tl != t.getLayer() ) return true; } return false; } @Override public void replaceByDummyNodes() { if( isCrossLayerEdge() ) { remove(); if( sources.size() == 1 && targets.size() == 1 ) { LayeredGraphNode last = sources.get( 0 ); int sl = last.getLayer(); int tl = targets.get( 0 ).getLayer(); for( int i = sl + 1; i < tl; i++ ) { LayeredGraphNode n = graph.createNode( null ); n.setLayer( i ); LayeredGraphEdge e = graph.createSimpleEdge( original, last, n ); e.setDummyEdge(); if( reversed ) e.setReversedEdge(); last = n; } LayeredGraphEdge e = graph.createSimpleEdge( original, last, targets.get( 0 ) ); e.setDummyEdge(); if( reversed ) e.setReversedEdge(); } } } @Override public void reverse() { reversed = !reversed; ArrayList< LayeredGraphNode > tmp = sources; sources = targets; targets = tmp; } @Override public boolean isDummyEdge() { return dummy; } @Override public void removeDummyNodes() { if( isDummyEdge() ) { remove(); ArrayList< LayeredGraphNode > sours = sources; for( int i = 0; i < sours.size(); i++ ) { LayeredGraphNode n = sours.get( i ); if( n.getOriginalNode() == null ) { sours.remove( n ); for( LayeredGraphEdge e : n.getIncomingEdges() ) { if( e.isDummyEdge() && e.getOriginalEdge() == original ) sours.addAll( e.getSources() ); } } } ArrayList< LayeredGraphNode > targs = targets; for( int i = 0; i < targs.size(); i++ ) { LayeredGraphNode n = targs.get( i ); if( n.getOriginalNode() == null ) { targs.remove( n ); for( LayeredGraphEdge e : n.getOutgoingEdges() ) { if( e.isDummyEdge() && e.getOriginalEdge() == original ) targs.addAll( e.getTargets() ); } } } LayeredGraphEdge e = graph.createEdge( original, sours, targs ); if( reversed ) e.setReversedEdge(); } } @Override public void setDummyEdge() { dummy = true; } @Override public void setReversedEdge() { reversed = true; } @Override public void setGraph(LayeredGraphNode graph) { this.graph = graph; } @Override public boolean isReversedEdge() { return reversed; } @Override public String toString() { return "(" + sources.get( 0 ).toString() + "," + targets.get( 0 ).toString() + ")"; } }