blob: 094be2146713588a69015c5e87a8a20257bb204b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2010 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.draw2d.graph;
import org.eclipse.draw2d.geometry.Insets;
/**
* Encapsulates the conversion of a long edge to multiple short edges and back.
*
* @since 3.1
*/
class VirtualNodeCreation extends RevertableChange {
private final Edge edge;
private final DirectedGraph graph;
private Node nodes[];
private Edge[] edges;
private static final int INNER_EDGE_X = 2;
private static final int LONG_EDGE_X = 8;
/**
* Breaks a single edge into multiple edges containing virtual nodes.
*
* @since 3.1
* @param edge
* The edge to convert
* @param graph
* the graph containing the edge
*/
public VirtualNodeCreation(Edge edge, DirectedGraph graph) {
this.edge = edge;
this.graph = graph;
int size = edge.target.rank - edge.source.rank - 1;
int offset = edge.source.rank + 1;
Node prevNode = edge.source;
Node currentNode;
Edge currentEdge;
nodes = new Node[size];
edges = new Edge[size + 1];
Insets padding = new Insets(0, edge.padding, 0, edge.padding);
Subgraph s = GraphUtilities.getCommonAncestor(edge.source, edge.target);
for (int i = 0; i < size; i++) {
nodes[i] = currentNode = new VirtualNode(
"Virtual" + i + ':' + edge, s); //$NON-NLS-1$
currentNode.width = edge.width;
if (s != null) {
currentNode.nestingIndex = s.nestingIndex;
}
currentNode.height = 0;
currentNode.setPadding(padding);
currentNode.rank = offset + i;
graph.ranks.getRank(offset + i).add(currentNode);
currentEdge = new Edge(prevNode, currentNode, 1, edge.weight
* LONG_EDGE_X);
if (i == 0) {
currentEdge.weight = edge.weight * INNER_EDGE_X;
currentEdge.offsetSource = edge.offsetSource;
}
graph.edges.add(edges[i] = currentEdge);
graph.nodes.add(currentNode);
prevNode = currentNode;
}
currentEdge = new Edge(prevNode, edge.target, 1, edge.weight
* INNER_EDGE_X);
currentEdge.offsetTarget = edge.offsetTarget;
graph.edges.add(edges[edges.length - 1] = currentEdge);
graph.removeEdge(edge);
}
void revert() {
edge.start = edges[0].start;
edge.end = edges[edges.length - 1].end;
edge.vNodes = new NodeList();
for (int i = 0; i < edges.length; i++) {
graph.removeEdge(edges[i]);
}
for (int i = 0; i < nodes.length; i++) {
edge.vNodes.add(nodes[i]);
graph.removeNode(nodes[i]);
}
edge.source.outgoing.add(edge);
edge.target.incoming.add(edge);
graph.edges.add(edge);
}
}