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

net.sf.gluebooster.java.booster.basic.math.graph.JungGraphLayouter Maven / Gradle / Ivy

package net.sf.gluebooster.java.booster.basic.math.graph;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyListener;
import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.collections4.TransformerUtils;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.UndirectedSparseGraph;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import net.sf.gluebooster.java.booster.basic.math.GeometryBoostUtils;
import net.sf.gluebooster.java.booster.basic.math.GeometryPositionConstraint;
import net.sf.gluebooster.java.booster.basic.transformation.CallableDelegate;
import net.sf.gluebooster.java.booster.essentials.eventsCommands.CallableByConstant;
import net.sf.gluebooster.java.booster.essentials.logging.LogBooster;

/**
 * Does a layout for jung graphs
 * 
 * @author CBauer
 *
 */
public class JungGraphLayouter /* extends BoostedObject */{

	/**
	 * Writes logging information.
	 */
	private LogBooster log = new LogBooster(getClass());

	/**
	 * The graph that is to be layouted.
	 */
	private Graph graph;

	/**
	 * The configuration of the layout.
	 */
	private GraphDisplayConfiguration configuration;

	/**
	 * The actual dimension of the layout
	 */
	private Dimension computedLayoutDimension;

	// private Transformer vertexFillPaintTransformer;
	// private boolean displayVertexLabel = false;
	// private Transformer vertexLabelTransformer;
	// private boolean displayVertexTooltip = false;
	// private Transformer vertexToolTipTransformer;
	// private GraphMouseListener graphMouseListener;
	// private List keyListeners = new ArrayList();
	// private Transformer vertexShapeTransformer;

	public JungGraphLayouter() {

	}

	/**
	 * Creata a layout of the graph.
	 * 
	 * @return the created layout
	 */
	private Layout createLayout() throws Exception {

		if (configuration.getLayoutDimension() == null) {
			log.info("no default layout dimension set");
			// displayConfiguration.setLayoutDimension(new Dimension(300, 300));
		}

		computedLayoutDimension = configuration.getLayoutDimension();
		// create a basic layout by using an existing layout

		FRLayout layout = new FRLayout(graph);
		// Layout layout = new CircleLayout(
		// graph);
		// TODO create the graph of the FRLayout and then modify the positions
		// (by using a staticLayout) so that no overlapping occurs
		layout.setSize(configuration.getLayoutDimension());
		// layout.setForceMultiplier()
		// layout.setRepulsionRange(300);
		// layout.setRepulsionMultiplier(50);
		// layout.setAttractionMultiplier(0.01);

		if (configuration.getVertexShapeTransformer() == null) {
			return layout;
			// hopefully the layout is good enough
			// nothing more needs be done yet
			// Optimization: use the modification of the else part always. Use
			// the default vertex shape transformer to compute the shapes of the
			// vertices.
		} else {

			// Optimize the layout by removing overlapping vertices and edges

			layout.initialize();
			// Compute the shapes of the vertices
			
			Graph graph1 = new UndirectedSparseGraph();
			
			HashMap shapes = new HashMap();
			for (Vertex vertex : graph.getVertices()) {
				Point2D center = layout.apply(vertex);
				Shape shape = (Shape) configuration.getVertexShapeTransformer()
						.call(vertex);
				Rectangle bounds = shape.getBounds();
				bounds.x = (int) center.getX();
				bounds.y = (int) center.getY();
				shapes.put(vertex, bounds);
				graph1.addVertex(bounds);
			}

			// compute the edges between the shapes
			for (Edge edge : graph.getEdges()) {
				edu.uci.ics.jung.graph.util.Pair endpoints = graph
						.getEndpoints(edge);
				graph1.addEdge(edge, shapes.get(endpoints.getFirst()),
						shapes.get(endpoints.getSecond()));
			}

			// reposition the shapes to avoid overlapping
			GeometryPositionConstraint constraints = new GeometryPositionConstraint();
			constraints.setMinimumDistance(30);
			// GeometryBoostUtils
			// .repositionWithoutOverlapping(graph1, constraints);
			GeometryBoostUtils.position(graph1, constraints);

			// transfer the shape positions to the vertices
			int maxX = 0;
			int maxY = 0;
			HashMap positions = new HashMap();
			for (Entry entry : shapes.entrySet()) {
				Rectangle position = entry.getValue();
				positions.put(entry.getKey(), position.getLocation());
				maxX = Math.max(maxX, position.x + position.width);
				maxY = Math.max(maxY, position.y + position.height);
			}

			GeometryBoostUtils.checkOverlappings(graph1, configuration.getOverlappingAllowed(),
					true, true, false, constraints);

			// add margin
			maxX = maxX + 10;
			maxY = maxY + 10;

			computedLayoutDimension = new Dimension(maxX, maxY);

			// Vertex locations can be placed in a Map and then supplied to this
			// layout as follows: Transformer vertexLocations =
			// TransformerUtils.mapTransformer(map);
			StaticLayout result = new StaticLayout(
					graph, new CallableDelegate(TransformerUtils.mapTransformer(positions)),
					computedLayoutDimension);

			return result;
		}
	}

	/**
	 * Creates a layout component of the graph.
	 * 
	 * @return the created layout
	 */
	public Component createLayoutComponent() throws Exception {

		// FRLayout layout = new FRLayout(graph);
		// layout.setSize(layoutDimension);
		Layout layout = createLayout();

		// The BasicVisualizationServer is parameterized by the edge types
		// BasicVisualizationServer vv = new
		// BasicVisualizationServer(
		// layout);
		JungVisualizationViewer vv = new JungVisualizationViewer(layout);
		vv.setExceptionListener(configuration.getExceptionListener());

		if (configuration.isDisplayVertexLabel()) {
			if (configuration.getVertexLabelTransformer() != null) {
				vv.getRenderContext().setVertexLabelTransformer(
						new CallableDelegate(configuration.getVertexLabelTransformer()));
			} else if (configuration.getVertexToolTipTransformer() != null) {
				vv.getRenderContext().setVertexLabelTransformer(
						new CallableDelegate(configuration.getVertexToolTipTransformer()));
			}
		}

		if (configuration.isDisplayVertexTooltip()) {
			if (configuration.getVertexToolTipTransformer() != null) {
				vv.setVertexToolTipTransformer(new CallableDelegate(configuration.getVertexToolTipTransformer()));
			} else if (configuration.getVertexLabelTransformer() != null) {
				vv.getRenderContext().setVertexLabelTransformer(
						new CallableDelegate(configuration.getVertexLabelTransformer()));
			}
		}

		vv.setPreferredSize(computedLayoutDimension);
		if (configuration.getVertexBackgroundTransformer() != null) {
			vv.getRenderContext().setVertexFillPaintTransformer(
					new CallableDelegate(configuration.getVertexBackgroundTransformer()));
		} else {
			vv.getRenderContext().setVertexFillPaintTransformer(
					new CallableDelegate(new CallableByConstant(null)));

		}

		if (configuration.getClickListener() != null) {
			vv.addGraphMouseListener(configuration.getClickListener());
		}

		List listeners = configuration.getKeyListeners();
		if (listeners != null) {
			for (KeyListener keylistener : listeners) {
				vv.addKeyListener(keylistener);
			}
		}

		if (configuration.getVertexShapeTransformer() != null) {
			vv.getRenderContext().setVertexShapeTransformer(
					new CallableDelegate(configuration.getVertexShapeTransformer()));
		}

		if (configuration.getVertexIconTransformer() != null) {
			vv.getRenderContext().setVertexIconTransformer(new CallableDelegate(configuration.getVertexIconTransformer()));
		}

		// vv.getRenderContext().setVertexLabelRenderer(vertexLabelRenderer);
		vv.getRenderer().getVertexLabelRenderer()
				.setPosition(Renderer.VertexLabel.Position.CNTR);

		return vv;
		// JViewport viewport = new JViewport();
		// viewport.setView(vv);
		// viewport.setAutoscrolls(true);
		// return viewport;
	}

	public Graph getGraph() {
		return graph;
	}

	public void setGraph(Graph graph) {
		this.graph = graph;
	}


	// public Transformer getVertexFillPaintTransformer() {
	// return vertexFillPaintTransformer;
	// }
	//
	// public void setVertexFillPaintTransformer(
	// Transformer vertexFillPaintTransformer) {
	// this.vertexFillPaintTransformer = vertexFillPaintTransformer;
	// }

	// public Transformer getVertexToolTipTransformer() {
	// return vertexToolTipTransformer;
	// }
	//
	// public void setVertexToolTipTransformer(
	// Transformer vertexToolTipTransformer) {
	// this.vertexToolTipTransformer = vertexToolTipTransformer;
	// }

	// public GraphMouseListener getGraphMouseListener() {
	// return graphMouseListener;
	// }
	//
	// public void setGraphMouseListener(
	// GraphMouseListener graphMouseListener) {
	// this.graphMouseListener = graphMouseListener;
	// }

	// public List getKeyListeners() {
	// return keyListeners;
	// }
	//
	// public void setKeyListeners(List keyListeners) {
	// this.keyListeners = keyListeners;
	// }
	//
	// public void addKeyListener(KeyListener listener) {
	// keyListeners.add(listener);
	// }

	// public Transformer getVertexShapeTransformer() {
	// return vertexShapeTransformer;
	// }
	//
	// public void setVertexShapeTransformer(
	// Transformer vertexShapeTransformer) {
	// this.vertexShapeTransformer = vertexShapeTransformer;
	// }
	//

	// public Transformer getVertexLabelTransformer() {
	// return vertexLabelTransformer;
	// }
	//
	// public void setVertexLabelTransformer(
	// Transformer vertexLabelTransformer) {
	// this.vertexLabelTransformer = vertexLabelTransformer;
	// }
	//
	// public boolean isDisplayVertexLabel() {
	// return displayVertexLabel;
	// }
	//
	// public void setDisplayVertexLabel(boolean displayVertexLabel) {
	// this.displayVertexLabel = displayVertexLabel;
	// }
	//
	// public boolean isDisplayVertexTooltip() {
	// return displayVertexTooltip;
	// }
	//
	// public void setDisplayVertexTooltip(boolean displayVertexTooltip) {
	// this.displayVertexTooltip = displayVertexTooltip;
	// }





	public GraphDisplayConfiguration getConfiguration() {
		return configuration;
	}

	public void setConfiguration(GraphDisplayConfiguration configuration) {
		this.configuration = configuration;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy