blob: ebdb6eefd4f34c9e1ae0048b632b1b4f1ac374fe [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.draw2d.ui.graph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.graph.DirectedGraph;
import org.eclipse.draw2d.graph.Node;
/**
* Performs the pre-routing work such as to route edges from border nodes located on left or right sides of a parent node.
* Those edges are assigned <code>startingRoutedPoints</code> and/or <endingRoutedPoints</code> to route edges to the top or
* bottom of the parent node rank.
* This class can be used to do some pre-routing work for orthogonal edges in the future.
*
* @author aboyko
* @since 2.1
*/
class PreRouteEdges {
private DirectedGraph g;
public PreRouteEdges(DirectedGraph g) {
this.g = g;
}
void preRouteEdges() {
for (int i = 0; i < g.nodes.size(); i++) {
Node n = g.nodes.getNode(i);
if (n instanceof ConstantSizeNode) {
preRouteEdgesFromNode((ConstantSizeNode)n);
}
}
}
private void preRouteEdgesFromNode(ConstantSizeNode n) {
List<BorderNode> leftBorderNodes = new ArrayList<BorderNode>();
List<BorderNode> rightBorderNodes = new ArrayList<BorderNode>();
for (Iterator<BorderNode> itr = n.borderNodes.iterator(); itr.hasNext();) {
BorderNode bn = itr.next();
if (bn.position == PositionConstants.EAST) {
rightBorderNodes.add(bn);
} else if (bn.position == PositionConstants.WEST) {
leftBorderNodes.add(bn);
}
}
createRoutingPointsForSideBorderNodes(leftBorderNodes, n, PositionConstants.WEST);
createRoutingPointsForSideBorderNodes(rightBorderNodes, n, PositionConstants.EAST);
}
private void createRoutingPointsForSideBorderNodes(List<BorderNode> nodes, ConstantSizeNode parentNode, int position) {
List<ConstrainedEdge> incomingEdges = new ArrayList<ConstrainedEdge>();
List<ConstrainedEdge> outgoingEdges = new ArrayList<ConstrainedEdge>();
int maxBorderItemOutsideWidth = initBorderNodeEdgesLists(nodes, incomingEdges, outgoingEdges, position);
int nodePadding = position == PositionConstants.WEST ? g.getPadding(parentNode).left : g.getPadding(parentNode).right;
if (nodePadding <= maxBorderItemOutsideWidth) {
throw new RuntimeException("Node padding must be greater than the the width of the widest border node"); //$NON-NLS-1$
}
if (incomingEdges.isEmpty() || outgoingEdges.isEmpty()) {
/*
* Border nodes sitting on the side should either have both the incoming
* and outgoing edges or no edges at all
*/
return;
}
int incomingPadding = (nodePadding - maxBorderItemOutsideWidth) / (incomingEdges.size() + 1);
int outgoingPadding = (nodePadding - maxBorderItemOutsideWidth) / (outgoingEdges.size() + 1);
// if (incomingEdges.size() >= outgoingEdges.size()) {
// incomingPadding = (nodePadding - maxBorderItemOutsideWidth) / (incomingEdges.size() + 1);
// outgoingPadding = incomingEdges.size() % outgoingEdges.size() == 0 ? (nodePadding - maxBorderItemOutsideWidth) / (outgoingEdges.size() + 2)
// : (nodePadding - maxBorderItemOutsideWidth) / (outgoingEdges.size() + 1);
// } else {
// outgoingPadding = (nodePadding - maxBorderItemOutsideWidth) / (outgoingEdges.size() + 1);
// incomingPadding = outgoingEdges.size() % incomingEdges.size() == 0 ? (nodePadding - maxBorderItemOutsideWidth) / (incomingEdges.size() + 2)
// : (nodePadding - maxBorderItemOutsideWidth) / (incomingEdges.size() + 1);
// }
Collections.sort(incomingEdges, new Comparator<ConstrainedEdge>() {
public int compare(ConstrainedEdge e1, ConstrainedEdge e2) {
int diff = GraphUtilities.getIncomingEdgeBendpointX(e2, g) - GraphUtilities.getIncomingEdgeBendpointX(e1, g);
if (e1.targetConstraint.position == PositionConstants.WEST) {
return diff;
} else {
return -diff;
}
}
});
Collections.sort(outgoingEdges, new Comparator<ConstrainedEdge>() {
public int compare(ConstrainedEdge e1, ConstrainedEdge e2) {
int diff = GraphUtilities.getOutogingEdgeBendpointX(e2, g) - GraphUtilities.getOutogingEdgeBendpointX(e1, g);
if (e1.sourceConstraint.position == PositionConstants.WEST) {
return diff;
} else {
return -diff;
}
}
});
int rankHeight = GraphUtilities.getRankHeightFromNode(parentNode, g);
Point incomingStartPt = position == PositionConstants.WEST ? new Point(parentNode.x - maxBorderItemOutsideWidth, parentNode.y)
: new Point(parentNode.x + parentNode.width + maxBorderItemOutsideWidth, parentNode.y);
Point outgoingStartPt = position == PositionConstants.WEST ? new Point(parentNode.x - maxBorderItemOutsideWidth, parentNode.y + rankHeight)
: new Point(parentNode.x + parentNode.width + maxBorderItemOutsideWidth, parentNode.y + parentNode.height);
Dimension incomingOffset = position == PositionConstants.WEST ? new Dimension(-incomingPadding, 0)
: new Dimension(incomingPadding, 0);
Dimension outgoingOffset = position == PositionConstants.WEST ? new Dimension(-outgoingPadding, 0)
: new Dimension(outgoingPadding, 0);
padBendpointsForEdges(incomingEdges, incomingStartPt, incomingOffset, true);
padBendpointsForEdges(outgoingEdges, outgoingStartPt, outgoingOffset, false);
}
private void padBendpointsForEdges(List<ConstrainedEdge> edges, Point startPoint, Dimension offset, boolean incoming) {
Point current = startPoint.getCopy().translate(offset);
for (Iterator<ConstrainedEdge> itr = edges.iterator(); itr.hasNext(); current.translate(offset)) {
ConstrainedEdge e = itr.next();
if (incoming) {
e.endingRoutedPoints.addPoint(current);
if (e.targetConstraint.minIncomingPadding > 0 || e.targetConstraint.minOutgoingPadding > 0) {
e.endingRoutedPoints.addPoint(current.x, e.end.y);
}
e.endingRoutedPoints.addPoint(e.end);
} else {
e.startingRoutedPoints.addPoint(e.start);
if (e.sourceConstraint.minIncomingPadding > 0 || e.sourceConstraint.minOutgoingPadding > 0) {
e.startingRoutedPoints.addPoint(current.x, e.start.y);
}
e.startingRoutedPoints.addPoint(current);
}
}
}
private int initBorderNodeEdgesLists(List<BorderNode> nodes, List<ConstrainedEdge> incomingEdges, List<ConstrainedEdge> outgoingEdges, int position) {
int maxBorderNodeOutsideWidth = 0;
for (Iterator<BorderNode> itr = nodes.iterator(); itr.hasNext();) {
BorderNode bn = itr.next();
if (bn.position == position) {
incomingEdges.addAll(bn.incomingJointEdges.edges);
outgoingEdges.addAll(bn.outgoingJointEdges.edges);
maxBorderNodeOutsideWidth = Math.max(maxBorderNodeOutsideWidth, (int)(bn.width * bn.getOutsideRatio()));
}
}
return maxBorderNodeOutsideWidth;
}
}