1
|
/*******************************************************************************
|
2
|
* Copyright (c) 2005, 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 java.util.Collection;
|
14
|
|
15
|
/**
|
16
|
* A group of nodes which are interlocked and cannot be separately placed.
|
17
|
*
|
18
|
* @since 3.1
|
19
|
*/
|
20
|
class NodeCluster extends NodeList {
|
21
|
|
22
|
int hashCode = new Object().hashCode();
|
23
|
|
24
|
boolean isSetMember;
|
25
|
boolean isDirty;
|
26
|
boolean leftDirty;
|
27
|
boolean rightDirty;
|
28
|
|
29
|
int leftFreedom;
|
30
|
int rightFreedom;
|
31
|
int leftNonzero;
|
32
|
int rightNonzero;
|
33
|
int leftCount = 0;
|
34
|
int rightCount = 0;
|
35
|
|
36
|
CollapsedEdges leftLinks[] = new CollapsedEdges[10];
|
37
|
CollapsedEdges rightLinks[] = new CollapsedEdges[10];
|
38
|
NodeCluster leftNeighbors[] = new NodeCluster[10];
|
39
|
NodeCluster rightNeighbors[] = new NodeCluster[10];
|
40
|
|
41
|
int effectivePull;
|
42
|
int weightedTotal;
|
43
|
int weightedDivisor;
|
44
|
int unweightedTotal;
|
45
|
int unweightedDivisor;
|
46
|
|
47
|
void addLeftNeighbor(NodeCluster neighbor, CollapsedEdges link) {
|
48
|
// Need to grow array in the following case
|
49
|
if (leftNeighbors.length == leftCount) {
|
50
|
int newSize = leftNeighbors.length * 2;
|
51
|
|
52
|
NodeCluster newNeighbors[] = new NodeCluster[newSize];
|
53
|
CollapsedEdges newLinks[] = new CollapsedEdges[newSize];
|
54
|
|
55
|
System.arraycopy(leftNeighbors, 0, newNeighbors, 0,
|
56
|
leftNeighbors.length);
|
57
|
System.arraycopy(leftLinks, 0, newLinks, 0, leftLinks.length);
|
58
|
|
59
|
leftNeighbors = newNeighbors;
|
60
|
leftLinks = newLinks;
|
61
|
}
|
62
|
leftNeighbors[leftCount] = neighbor;
|
63
|
leftLinks[leftCount++] = link;
|
64
|
}
|
65
|
|
66
|
void addRightNeighbor(NodeCluster neighbor, CollapsedEdges link) {
|
67
|
if (rightNeighbors.length == rightCount) {
|
68
|
int newSize = rightNeighbors.length * 2;
|
69
|
|
70
|
NodeCluster newNeighbors[] = new NodeCluster[newSize];
|
71
|
CollapsedEdges newLinks[] = new CollapsedEdges[newSize];
|
72
|
|
73
|
System.arraycopy(rightNeighbors, 0, newNeighbors, 0,
|
74
|
rightNeighbors.length);
|
75
|
System.arraycopy(rightLinks, 0, newLinks, 0, rightLinks.length);
|
76
|
|
77
|
rightNeighbors = newNeighbors;
|
78
|
rightLinks = newLinks;
|
79
|
}
|
80
|
rightNeighbors[rightCount] = neighbor;
|
81
|
rightLinks[rightCount++] = link;
|
82
|
}
|
83
|
|
84
|
public void adjustRank(int delta, Collection affected) {
|
85
|
adjustRank(delta);
|
86
|
NodeCluster neighbor;
|
87
|
CollapsedEdges edges;
|
88
|
for (int i = 0; i < leftCount; i++) {
|
89
|
neighbor = leftNeighbors[i];
|
90
|
if (neighbor.isSetMember)
|
91
|
continue;
|
92
|
edges = leftLinks[i];
|
93
|
|
94
|
neighbor.weightedTotal += delta * edges.collapsedWeight;
|
95
|
neighbor.unweightedTotal += delta * edges.collapsedCount;
|
96
|
|
97
|
weightedTotal -= delta * edges.collapsedWeight;
|
98
|
unweightedTotal -= delta * edges.collapsedCount;
|
99
|
|
100
|
neighbor.rightDirty = leftDirty = true;
|
101
|
if (!neighbor.isDirty) {
|
102
|
neighbor.isDirty = true;
|
103
|
affected.add(neighbor);
|
104
|
}
|
105
|
}
|
106
|
for (int i = 0; i < rightCount; i++) {
|
107
|
neighbor = rightNeighbors[i];
|
108
|
if (neighbor.isSetMember)
|
109
|
continue;
|
110
|
edges = rightLinks[i];
|
111
|
|
112
|
neighbor.weightedTotal += delta * edges.collapsedWeight;
|
113
|
neighbor.unweightedTotal += delta * edges.collapsedCount;
|
114
|
|
115
|
weightedTotal -= delta * edges.collapsedWeight;
|
116
|
unweightedTotal -= delta * edges.collapsedCount;
|
117
|
|
118
|
neighbor.leftDirty = rightDirty = true;
|
119
|
if (!neighbor.isDirty) {
|
120
|
neighbor.isDirty = true;
|
121
|
affected.add(neighbor);
|
122
|
}
|
123
|
}
|
124
|
isDirty = true;
|
125
|
affected.add(this);
|
126
|
}
|
127
|
|
128
|
public boolean equals(Object o) {
|
129
|
return o == this;
|
130
|
}
|
131
|
|
132
|
CollapsedEdges getLeftNeighbor(NodeCluster neighbor) {
|
133
|
for (int i = 0; i < leftCount; i++) {
|
134
|
if (leftNeighbors[i] == neighbor)
|
135
|
return leftLinks[i];
|
136
|
}
|
137
|
return null;
|
138
|
}
|
139
|
|
140
|
int getPull() {
|
141
|
return effectivePull;
|
142
|
}
|
143
|
|
144
|
CollapsedEdges getRightNeighbor(NodeCluster neighbor) {
|
145
|
for (int i = 0; i < rightCount; i++) {
|
146
|
if (rightNeighbors[i] == neighbor)
|
147
|
return rightLinks[i];
|
148
|
}
|
149
|
return null;
|
150
|
}
|
151
|
|
152
|
public int hashCode() {
|
153
|
return hashCode;
|
154
|
}
|
155
|
|
156
|
/**
|
157
|
* Initializes pull and freedom values.
|
158
|
*/
|
159
|
void initValues() {
|
160
|
weightedTotal = 0;
|
161
|
weightedDivisor = 0;
|
162
|
unweightedTotal = 0;
|
163
|
int slack;
|
164
|
|
165
|
leftNonzero = rightNonzero = leftFreedom = rightFreedom = Integer.MAX_VALUE;
|
166
|
for (int i = 0; i < leftCount; i++) {
|
167
|
CollapsedEdges edges = leftLinks[i];
|
168
|
weightedTotal -= edges.getWeightedPull();
|
169
|
unweightedTotal -= edges.tightestEdge.getSlack();
|
170
|
unweightedDivisor += edges.collapsedCount;
|
171
|
weightedDivisor += edges.collapsedWeight;
|
172
|
slack = edges.tightestEdge.getSlack();
|
173
|
leftFreedom = Math.min(slack, leftFreedom);
|
174
|
if (slack > 0)
|
175
|
leftNonzero = Math.min(slack, leftNonzero);
|
176
|
}
|
177
|
for (int i = 0; i < rightCount; i++) {
|
178
|
CollapsedEdges edges = rightLinks[i];
|
179
|
weightedTotal += edges.getWeightedPull();
|
180
|
unweightedDivisor += edges.collapsedCount;
|
181
|
unweightedTotal += edges.tightestEdge.getSlack();
|
182
|
weightedDivisor += edges.collapsedWeight;
|
183
|
slack = edges.tightestEdge.getSlack();
|
184
|
rightFreedom = Math.min(slack, rightFreedom);
|
185
|
if (slack > 0)
|
186
|
rightNonzero = Math.min(slack, rightNonzero);
|
187
|
}
|
188
|
updateEffectivePull();
|
189
|
}
|
190
|
|
191
|
/**
|
192
|
* Refreshes the left and right freedom.
|
193
|
*/
|
194
|
void refreshValues() {
|
195
|
int slack;
|
196
|
isDirty = false;
|
197
|
if (leftDirty) {
|
198
|
leftDirty = false;
|
199
|
leftNonzero = leftFreedom = Integer.MAX_VALUE;
|
200
|
for (int i = 0; i < leftCount; i++) {
|
201
|
CollapsedEdges edges = leftLinks[i];
|
202
|
slack = edges.tightestEdge.getSlack();
|
203
|
leftFreedom = Math.min(slack, leftFreedom);
|
204
|
if (slack > 0)
|
205
|
leftNonzero = Math.min(slack, leftNonzero);
|
206
|
}
|
207
|
}
|
208
|
if (rightDirty) {
|
209
|
rightDirty = false;
|
210
|
rightNonzero = rightFreedom = Integer.MAX_VALUE;
|
211
|
for (int i = 0; i < rightCount; i++) {
|
212
|
CollapsedEdges edges = rightLinks[i];
|
213
|
slack = edges.tightestEdge.getSlack();
|
214
|
rightFreedom = Math.min(slack, rightFreedom);
|
215
|
if (slack > 0)
|
216
|
rightNonzero = Math.min(slack, rightNonzero);
|
217
|
}
|
218
|
}
|
219
|
updateEffectivePull();
|
220
|
}
|
221
|
|
222
|
private void updateEffectivePull() {
|
223
|
if (weightedDivisor != 0)
|
224
|
effectivePull = weightedTotal / weightedDivisor;
|
225
|
else if (unweightedDivisor != 0)
|
226
|
effectivePull = unweightedTotal / unweightedDivisor;
|
227
|
else
|
228
|
effectivePull = 0;
|
229
|
}
|
230
|
|
231
|
}
|