Project

General

Profile

Download (4.92 KB) Statistics
| Branch: | Tag: | Revision:
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2010 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.draw2d.graph;
12

    
13
import org.eclipse.draw2d.geometry.Insets;
14

    
15
/**
16
 * Converts a compound directed graph into a simple directed graph.
17
 * 
18
 * @author Randy Hudson
19
 * @since 2.1.2
20
 */
21
class ConvertCompoundGraph extends GraphVisitor {
22

    
23
	private void addContainmentEdges(CompoundDirectedGraph graph) {
24
		// For all nested nodes, connect to head and/or tail of containing
25
		// subgraph if present
26
		for (int i = 0; i < graph.nodes.size(); i++) {
27
			Node node = graph.nodes.getNode(i);
28
			Subgraph parent = node.getParent();
29
			if (parent == null)
30
				continue;
31
			if (node instanceof Subgraph) {
32
				Subgraph sub = (Subgraph) node;
33
				connectHead(graph, sub.head, parent);
34
				connectTail(graph, sub.tail, parent);
35
			} else {
36
				connectHead(graph, node, parent);
37
				connectTail(graph, node, parent);
38
			}
39
		}
40
	}
41

    
42
	int buildNestingTreeIndices(NodeList nodes, int base) {
43
		for (int i = 0; i < nodes.size(); i++) {
44
			Node node = (Node) nodes.get(i);
45
			if (node instanceof Subgraph) {
46
				Subgraph s = (Subgraph) node;
47
				s.nestingTreeMin = base;
48
				base = buildNestingTreeIndices(s.members, base);
49
			}
50
			node.nestingIndex = base++;
51
		}
52
		return base++;
53
	}
54

    
55
	private void connectHead(CompoundDirectedGraph graph, Node node,
56
			Subgraph parent) {
57
		boolean connectHead = true;
58
		for (int j = 0; connectHead && j < node.incoming.size(); j++) {
59
			Node ancestor = node.incoming.getEdge(j).source;
60
			if (parent.isNested(ancestor))
61
				connectHead = false;
62
		}
63
		if (connectHead) {
64
			Edge e = new Edge(parent.head, node);
65
			e.weight = 0;
66
			graph.edges.add(e);
67
			graph.containment.add(e);
68
		}
69
	}
70

    
71
	private void connectTail(CompoundDirectedGraph graph, Node node,
72
			Subgraph parent) {
73
		boolean connectTail = true;
74
		for (int j = 0; connectTail && j < node.outgoing.size(); j++) {
75
			Node ancestor = node.outgoing.getEdge(j).target;
76
			if (parent.isNested(ancestor))
77
				connectTail = false;
78
		}
79
		if (connectTail) {
80
			Edge e = new Edge(node, parent.tail);
81
			e.weight = 0;
82
			graph.edges.add(e);
83
			graph.containment.add(e);
84
		}
85
	}
86

    
87
	private void convertSubgraphEndpoints(CompoundDirectedGraph graph) {
88
		for (int i = 0; i < graph.edges.size(); i++) {
89
			Edge edge = (Edge) graph.edges.get(i);
90
			if (edge.source instanceof Subgraph) {
91
				Subgraph s = (Subgraph) edge.source;
92
				Node newSource;
93
				if (s.isNested(edge.target))
94
					newSource = s.head;
95
				else
96
					newSource = s.tail;
97
				// s.outgoing.remove(edge);
98
				edge.source = newSource;
99
				newSource.outgoing.add(edge);
100
			}
101
			if (edge.target instanceof Subgraph) {
102
				Subgraph s = (Subgraph) edge.target;
103
				Node newTarget;
104
				if (s.isNested(edge.source))
105
					newTarget = s.tail;
106
				else
107
					newTarget = s.head;
108

    
109
				// s.incoming.remove(edge);
110
				edge.target = newTarget;
111
				newTarget.incoming.add(edge);
112
			}
113
		}
114
	}
115

    
116
	private void replaceSubgraphsWithBoundaries(CompoundDirectedGraph graph) {
117
		for (int i = 0; i < graph.subgraphs.size(); i++) {
118
			Subgraph s = (Subgraph) graph.subgraphs.get(i);
119
			graph.nodes.add(s.head);
120
			graph.nodes.add(s.tail);
121
			graph.nodes.remove(s);
122
		}
123
	}
124

    
125
	void revisit(DirectedGraph g) {
126
		for (int i = 0; i < g.edges.size(); i++) {
127
			Edge e = g.edges.getEdge(i);
128
			if (e.source instanceof SubgraphBoundary) {
129
				e.source.outgoing.remove(e);
130
				e.source = e.source.getParent();
131
			}
132
			if (e.target instanceof SubgraphBoundary) {
133
				e.target.incoming.remove(e);
134
				e.target = e.target.getParent();
135
			}
136
		}
137
	}
138

    
139
	/**
140
	 * @see GraphVisitor#visit(org.eclipse.draw2d.graph.DirectedGraph)
141
	 */
142
	public void visit(DirectedGraph dg) {
143
		CompoundDirectedGraph graph = (CompoundDirectedGraph) dg;
144

    
145
		NodeList roots = new NodeList();
146
		// Find all subgraphs and root subgraphs
147
		for (int i = 0; i < graph.nodes.size(); i++) {
148
			Object node = graph.nodes.get(i);
149
			if (node instanceof Subgraph) {
150
				Subgraph s = (Subgraph) node;
151
				Insets padding = dg.getPadding(s);
152
				s.head = new SubgraphBoundary(s, padding, 0);
153
				s.tail = new SubgraphBoundary(s, padding, 2);
154
				Edge headToTail = new Edge(s.head, s.tail);
155
				headToTail.weight = 10;
156
				graph.edges.add(headToTail);
157
				graph.containment.add(headToTail);
158

    
159
				graph.subgraphs.add(s);
160
				if (s.getParent() == null)
161
					roots.add(s);
162
				if (s.members.size() == 2) // The 2 being the head and tail only
163
					graph.edges.add(new Edge(s.head, s.tail));
164
			}
165
		}
166

    
167
		buildNestingTreeIndices(roots, 0);
168
		convertSubgraphEndpoints(graph);
169
		addContainmentEdges(graph);
170
		replaceSubgraphsWithBoundaries(graph);
171
	}
172

    
173
}
(11-11/49)