All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.algorithms.layout.AggregateLayout Maven / Gradle / Ivy

/*
 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 * 
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 * 
 * 
 * 
 */
package edu.uci.ics.jung.algorithms.layout;

import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.util.IterativeContext;
import edu.uci.ics.jung.graph.Graph;

/**
 * A {@code Layout} implementation that combines 
 * multiple other layouts so that they may be manipulated
 * as one layout. The relaxer thread will step each layout
 * in sequence.
 * 
 * @author Tom Nelson - [email protected]
 *
 * @param  the vertex type
 * @param  the edge type
 */
public class AggregateLayout implements Layout, IterativeContext {

	protected Layout delegate;
	protected Map,Point2D> layouts = new HashMap,Point2D>();

	/**
	 * Creates an instance backed by the specified {@code delegate}.
	 * @param delegate
	 */
	public AggregateLayout(Layout delegate) {
		this.delegate = delegate;
	}

	/**
	 * @return the delegate
	 */
	public Layout getDelegate() {
		return delegate;
	}

	/**
	 * @param delegate the delegate to set
	 */
	public void setDelegate(Layout delegate) {
		this.delegate = delegate;
	}

	/**
	 * adds the passed layout as a sublayout, also specifying
	 * the center of where this sublayout should appear
	 * @param layout
	 * @param center
	 */
	public void put(Layout layout, Point2D center) {
		layouts.put(layout,center);
	}
	
	/**
	 * Returns the center of the passed layout.
	 * @param layout
	 * @return the center of the passed layout
	 */
	public Point2D get(Layout layout) {
		return layouts.get(layout);
	}
	
	/**
	 * Removes {@code layout} from this instance.
	 */
	public void remove(Layout layout) {
		layouts.remove(layout);
	}
	
	/**
	 * Removes all layouts from this instance.
	 */
	public void removeAll() {
		layouts.clear();
	}
	
	/**
	 * Returns the graph for which this layout is defined.
	 * @return the graph for which this layout is defined
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#getGraph()
	 */
	public Graph getGraph() {
		return delegate.getGraph();
	}

	/**
	 * Returns the size of the underlying layout.
	 * @return the size of the underlying layout
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#getSize()
	 */
	public Dimension getSize() {
		return delegate.getSize();
	}

	/**
	 * 
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#initialize()
	 */
	public void initialize() {
		delegate.initialize();
		for(Layout layout : layouts.keySet()) {
			layout.initialize();
		}
	}

	/**
	 * Override to test if the passed vertex is locked in
	 * any of the layouts.
	 * @param v
	 * @return true if v is locked in any of the layouts, and false otherwise
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#isLocked(java.lang.Object)
	 */
	public boolean isLocked(V v) {
		boolean locked = false;
		for(Layout layout : layouts.keySet()) {
			locked |= layout.isLocked(v);
		}
		locked |= delegate.isLocked(v);
		return locked;
	}

	/**
	 * override to lock or unlock this vertex in any layout with
	 * a subgraph containing it
	 * @param v
	 * @param state
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#lock(java.lang.Object, boolean)
	 */
	public void lock(V v, boolean state) {
		for(Layout layout : layouts.keySet()) {
			if(layout.getGraph().getVertices().contains(v)) {
				layout.lock(v, state);
			}
		}
		delegate.lock(v, state);
	}

	/**
	 * 
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#reset()
	 */
	public void reset() {
		for(Layout layout : layouts.keySet()) {
			layout.reset();
		}
		delegate.reset();
	}

	/**
	 * @param graph
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#setGraph(edu.uci.ics.jung.graph.Graph)
	 */
	public void setGraph(Graph graph) {
		delegate.setGraph(graph);
	}

	/**
	 * @param initializer
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#setInitializer(org.apache.commons.collections15.Transformer)
	 */
	public void setInitializer(Transformer initializer) {
		delegate.setInitializer(initializer);
	}

	/**
	 * @param v
	 * @param location
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#setLocation(java.lang.Object, java.awt.geom.Point2D)
	 */
	public void setLocation(V v, Point2D location) {
		boolean wasInSublayout = false;
		for(Layout layout : layouts.keySet()) {
			if(layout.getGraph().getVertices().contains(v)) {
				Point2D center = layouts.get(layout);
				// transform by the layout itself, but offset to the
				// center of the sublayout
				Dimension d = layout.getSize();

				AffineTransform at = 
					AffineTransform.getTranslateInstance(-center.getX()+d.width/2,-center.getY()+d.height/2);
				Point2D localLocation = at.transform(location, null);
				layout.setLocation(v, localLocation);
				wasInSublayout = true;
			}
		}
		if(wasInSublayout == false && getGraph().getVertices().contains(v)) {
			delegate.setLocation(v, location);
		}
	}

	/**
	 * @param d
	 * @see edu.uci.ics.jung.algorithms.layout.Layout#setSize(java.awt.Dimension)
	 */
	public void setSize(Dimension d) {
		delegate.setSize(d);
	}
	
	/**
	 * Returns a map from each {@code Layout} instance to its center point.
	 */
	public Map,Point2D> getLayouts() {
		return layouts;
	}

	/**
	 * Returns the location of the vertex.  The location is specified first
	 * by the sublayouts, and then by the base layout if no sublayouts operate
	 * on this vertex.
	 * @return the location of the vertex
	 * @see org.apache.commons.collections15.Transformer#transform(java.lang.Object)
	 */
	public Point2D transform(V v) {
		boolean wasInSublayout = false;
		for(Layout layout : layouts.keySet()) {
			if(layout.getGraph().getVertices().contains(v)) {
				wasInSublayout = true;
				Point2D center = layouts.get(layout);
				// transform by the layout itself, but offset to the
				// center of the sublayout
				Dimension d = layout.getSize();
				AffineTransform at = 
					AffineTransform.getTranslateInstance(center.getX()-d.width/2,
							center.getY()-d.height/2);
				return at.transform(layout.transform(v),null);
			}
		}
		if(wasInSublayout == false) {
			return delegate.transform(v);
		}
		return null;
	
	}

	/**
	 * Check all sublayouts.keySet() and the delegate layout, returning
	 * done == true iff all are done.
	 */
	public boolean done() {
		boolean done = true;
		for(Layout layout : layouts.keySet()) {
			if(layout instanceof IterativeContext) {
				done &= ((IterativeContext)layout).done();
			}
		}
		if(delegate instanceof IterativeContext) {
			done &= ((IterativeContext)delegate).done();
		}
		return done;
	}

	/**
	 * call step on any sublayout that is also an IterativeContext
	 * and is not done
	 */
	public void step() {
		for(Layout layout : layouts.keySet()) {
			if(layout instanceof IterativeContext) {
				IterativeContext context = (IterativeContext)layout;
				if(context.done() == false) {
					context.step();
				}
			}
		}
		if(delegate instanceof IterativeContext) {
			IterativeContext context = (IterativeContext)delegate;
			if(context.done() == false) {
				context.step();
			}
		}
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy