1
2
3
4
5
6
7
8
9
10
11 package edu.uci.ics.jung.algorithms.layout;
12
13 import java.awt.Dimension;
14 import java.awt.geom.Point2D;
15 import java.util.ConcurrentModificationException;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.apache.commons.collections15.Transformer;
22 import org.apache.commons.collections15.functors.ChainedTransformer;
23 import org.apache.commons.collections15.functors.CloneTransformer;
24 import org.apache.commons.collections15.map.LazyMap;
25
26 import edu.uci.ics.jung.graph.Graph;
27
28
29
30
31
32
33
34
35
36
37
38 abstract public class AbstractLayout<V, E> implements Layout<V,E> {
39
40
41
42
43
44 private Set<V> dontmove = new HashSet<V>();
45
46 protected Dimension size;
47 protected Graph<V, E> graph;
48 protected boolean initialized;
49
50 protected Map<V, Point2D> locations =
51 LazyMap.decorate(new HashMap<V, Point2D>(),
52 new Transformer<V,Point2D>() {
53 public Point2D transform(V arg0) {
54 return new Point2D.Double();
55 }});
56
57
58
59
60
61
62
63 protected AbstractLayout(Graph<V, E> graph) {
64 if (graph == null)
65 {
66 throw new IllegalArgumentException("Graph must be non-null");
67 }
68 this.graph = graph;
69 }
70
71 @SuppressWarnings("unchecked")
72 protected AbstractLayout(Graph<V,E> graph, Transformer<V,Point2D> initializer) {
73 this.graph = graph;
74 Transformer<V, ? extends Object> chain =
75 ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance());
76 this.locations = LazyMap.decorate(new HashMap<V,Point2D>(), (Transformer<V,Point2D>)chain);
77 initialized = true;
78 }
79
80 protected AbstractLayout(Graph<V,E> graph, Dimension size) {
81 this.graph = graph;
82 this.size = size;
83 }
84
85 @SuppressWarnings("unchecked")
86 protected AbstractLayout(Graph<V,E> graph, Transformer<V,Point2D> initializer, Dimension size) {
87 this.graph = graph;
88 Transformer<V, ? extends Object> chain =
89 ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance());
90 this.locations = LazyMap.decorate(new HashMap<V,Point2D>(), (Transformer<V,Point2D>)chain);
91 this.size = size;
92 }
93
94 public void setGraph(Graph<V,E> graph) {
95 this.graph = graph;
96 if(size != null && graph != null) {
97 initialize();
98 }
99 }
100
101
102
103
104
105
106 public void setSize(Dimension size) {
107
108 if(size != null && graph != null) {
109
110 Dimension oldSize = this.size;
111 this.size = size;
112 initialize();
113
114 if(oldSize != null) {
115 adjustLocations(oldSize, size);
116 }
117 }
118 }
119
120 private void adjustLocations(Dimension oldSize, Dimension size) {
121
122 int xOffset = (size.width - oldSize.width) / 2;
123 int yOffset = (size.height - oldSize.height) / 2;
124
125
126 while(true) {
127 try {
128 for(V v : getGraph().getVertices()) {
129 offsetVertex(v, xOffset, yOffset);
130 }
131 break;
132 } catch(ConcurrentModificationException cme) {
133 }
134 }
135 }
136
137 public boolean isLocked(V v) {
138 return dontmove.contains(v);
139 }
140
141 @SuppressWarnings("unchecked")
142 public void setInitializer(Transformer<V,Point2D> initializer) {
143 if(this.equals(initializer)) {
144 throw new IllegalArgumentException("Layout cannot be initialized with itself");
145 }
146 Transformer<V, ? extends Object> chain =
147 ChainedTransformer.getInstance(initializer, CloneTransformer.getInstance());
148 this.locations = LazyMap.decorate(new HashMap<V,Point2D>(), (Transformer<V, Point2D>)chain);
149 initialized = true;
150 }
151
152
153
154
155
156
157
158 public Dimension getSize() {
159 return size;
160 }
161
162
163
164
165
166
167
168
169 private Point2D getCoordinates(V v) {
170 return locations.get(v);
171 }
172
173 public Point2D transform(V v) {
174 return getCoordinates(v);
175 }
176
177
178
179
180
181 public double getX(V v) {
182 assert getCoordinates(v) != null : "Cannot getX for an unmapped vertex "+v;
183 return getCoordinates(v).getX();
184 }
185
186
187
188
189
190 public double getY(V v) {
191 assert getCoordinates(v) != null : "Cannot getY for an unmapped vertex "+v;
192 return getCoordinates(v).getY();
193 }
194
195
196
197
198
199
200 protected void offsetVertex(V v, double xOffset, double yOffset) {
201 Point2D c = getCoordinates(v);
202 c.setLocation(c.getX()+xOffset, c.getY()+yOffset);
203 setLocation(v, c);
204 }
205
206
207
208
209
210
211 public Graph<V, E> getGraph() {
212 return graph;
213 }
214
215
216
217
218
219
220
221 public void setLocation(V picked, double x, double y) {
222 Point2D coord = getCoordinates(picked);
223 coord.setLocation(x, y);
224 }
225
226 public void setLocation(V picked, Point2D p) {
227 Point2D coord = getCoordinates(picked);
228 coord.setLocation(p);
229 }
230
231
232
233
234 public void lock(V v, boolean state) {
235 if(state == true)
236 dontmove.add(v);
237 else
238 dontmove.remove(v);
239 }
240
241
242
243
244 public void lock(boolean lock) {
245 for(V v : graph.getVertices()) {
246 lock(v, lock);
247 }
248 }
249 }