2 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3 * California All rights reserved.
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.
8 * Created on Jul 7, 2003
11 package edu.uci.ics.jung.algorithms.layout;
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;
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;
26 import edu.uci.ics.jung.graph.Graph;
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.
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
38 abstract public class AbstractLayout<V, E> implements Layout<V,E> {
41 * a set of vertices that should not move in relation to the
44 private Set<V> dontmove = new HashSet<V>();
46 protected Dimension size;
47 protected Graph<V, E> graph;
48 protected boolean initialized;
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();
59 * Creates an instance which does not initialize the vertex locations.
61 * @param graph the graph for which the layout algorithm is to be created.
63 protected AbstractLayout(Graph<V, E> graph) {
66 throw new IllegalArgumentException("Graph must be non-null");
71 @SuppressWarnings("unchecked")
72 protected AbstractLayout(Graph<V,E> graph, Transformer<V,Point2D> initializer) {
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);
80 protected AbstractLayout(Graph<V,E> graph, Dimension size) {
85 @SuppressWarnings("unchecked")
86 protected AbstractLayout(Graph<V,E> graph, Transformer<V,Point2D> initializer, Dimension size) {
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);
94 public void setGraph(Graph<V,E> graph) {
96 if(size != null && graph != null) {
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>.
106 public void setSize(Dimension size) {
108 if(size != null && graph != null) {
110 Dimension oldSize = this.size;
114 if(oldSize != null) {
115 adjustLocations(oldSize, size);
120 private void adjustLocations(Dimension oldSize, Dimension size) {
122 int xOffset = (size.width - oldSize.width) / 2;
123 int yOffset = (size.height - oldSize.height) / 2;
125 // now, move each vertex to be at the new screen center
128 for(V v : getGraph().getVertices()) {
129 offsetVertex(v, xOffset, yOffset);
132 } catch(ConcurrentModificationException cme) {
137 public boolean isLocked(V v) {
138 return dontmove.contains(v);
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");
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);
153 * Returns the current size of the visualization space, accoring to the
154 * last call to resize().
156 * @return the current size of the screen
158 public Dimension getSize() {
163 * Returns the Coordinates object that stores the vertex' x and y location.
166 * A Vertex that is a part of the Graph being visualized.
167 * @return A Coordinates object with x and y locations.
169 private Point2D getCoordinates(V v) {
170 return locations.get(v);
173 public Point2D transform(V v) {
174 return getCoordinates(v);
178 * Returns the x coordinate of the vertex from the Coordinates object.
179 * in most cases you will be better off calling transform(v).
181 public double getX(V v) {
182 assert getCoordinates(v) != null : "Cannot getX for an unmapped vertex "+v;
183 return getCoordinates(v).getX();
187 * Returns the y coordinate of the vertex from the Coordinates object.
188 * In most cases you will be better off calling transform(v).
190 public double getY(V v) {
191 assert getCoordinates(v) != null : "Cannot getY for an unmapped vertex "+v;
192 return getCoordinates(v).getY();
200 protected void offsetVertex(V v, double xOffset, double yOffset) {
201 Point2D c = getCoordinates(v);
202 c.setLocation(c.getX()+xOffset, c.getY()+yOffset);
207 * Accessor for the graph that represets all vertices.
209 * @return the graph that contains all vertices.
211 public Graph<V, E> getGraph() {
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.
221 public void setLocation(V picked, double x, double y) {
222 Point2D coord = getCoordinates(picked);
223 coord.setLocation(x, y);
226 public void setLocation(V picked, Point2D p) {
227 Point2D coord = getCoordinates(picked);
228 coord.setLocation(p);
232 * Locks {@code v} in place if {@code state} is {@code true}, otherwise unlocks it.
234 public void lock(V v, boolean state) {
242 * Locks all vertices in place if {@code lock} is {@code true}, otherwise unlocks all vertices.
244 public void lock(boolean lock) {
245 for(V v : graph.getVertices()) {