Initial opendaylight infrastructure commit!!
[controller.git] / third-party / net.sf.jung2 / src / main / java / edu / uci / ics / jung / algorithms / layout / AbstractLayout.java
1 /*
2  * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3  * California All rights reserved.
4  * 
5  * This software is open-source under the BSD license; see either "license.txt"
6  * or http://jung.sourceforge.net/license.txt for a description.
7  * 
8  * Created on Jul 7, 2003
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  * Abstract class for implementations of {@code Layout}.  It handles some of the
30  * basic functions: storing coordinates, maintaining the dimensions, initializing
31  * the locations, maintaining locked vertices.
32  * 
33  * @author Danyel Fisher, Scott White
34  * @author Tom Nelson - converted to jung2
35  * @param <V> the vertex type
36  * @param <E> the edge type
37  */
38 abstract public class AbstractLayout<V, E> implements Layout<V,E> {
39
40     /**
41      * a set of vertices that should not move in relation to the
42      * other vertices
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          * Creates an instance which does not initialize the vertex locations.
60          * 
61          * @param graph the graph for which the layout algorithm is to be created.
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          * When a visualization is resized, it presumably wants to fix the
103          * locations of the vertices and possibly to reinitialize its data. The
104          * current method calls <tt>initializeLocations</tt> followed by <tt>initialize_local</tt>.
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                 // now, move each vertex to be at the new screen center
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          * Returns the current size of the visualization space, accoring to the
154          * last call to resize().
155          * 
156          * @return the current size of the screen
157          */
158         public Dimension getSize() {
159                 return size;
160         }
161
162         /**
163          * Returns the Coordinates object that stores the vertex' x and y location.
164          * 
165          * @param v
166          *            A Vertex that is a part of the Graph being visualized.
167          * @return A Coordinates object with x and y locations.
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          * Returns the x coordinate of the vertex from the Coordinates object.
179          * in most cases you will be better off calling transform(v).
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          * Returns the y coordinate of the vertex from the Coordinates object.
188          * In most cases you will be better off calling transform(v).
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          * @param v
197          * @param xOffset
198          * @param yOffset
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          * Accessor for the graph that represets all vertices.
208          * 
209          * @return the graph that contains all vertices.
210          */
211         public Graph<V, E> getGraph() {
212             return graph;
213         }
214         
215         /**
216          * Forcibly moves a vertex to the (x,y) location by setting its x and y
217          * locations to the inputted location. Does not add the vertex to the
218          * "dontmove" list, and (in the default implementation) does not make any
219          * adjustments to the rest of the graph.
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          * Locks {@code v} in place if {@code state} is {@code true}, otherwise unlocks it.
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          * Locks all vertices in place if {@code lock} is {@code true}, otherwise unlocks all vertices.
243          */
244         public void lock(boolean lock) {
245                 for(V v : graph.getVertices()) {
246                         lock(v, lock);
247                 }
248         }
249 }