org.jungrapht.samples.LensDemoWithDefaultGraphMouseProperyDriven Maven / Gradle / Ivy
Show all versions of jungrapht-visualization-samples Show documentation
/*
* Copyright (c) 2003, The JUNG Authors
* All rights reserved.
*
* This software is open-source under the BSD license; see either "license.txt"
* or https://github.com/tomnelson/jungrapht-visualization/blob/master/LICENSE for a description.
*
*/
package org.jungrapht.samples;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.event.ItemEvent;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import javax.swing.*;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultGraphType;
import org.jgrapht.graph.builder.GraphTypeBuilder;
import org.jungrapht.samples.util.ControlHelpers;
import org.jungrapht.samples.util.LensControlHelper;
import org.jungrapht.samples.util.TestGraphs;
import org.jungrapht.visualization.MultiLayerTransformer.Layer;
import org.jungrapht.visualization.VisualizationModel;
import org.jungrapht.visualization.VisualizationScrollPane;
import org.jungrapht.visualization.VisualizationViewer;
import org.jungrapht.visualization.control.DefaultGraphMouse;
import org.jungrapht.visualization.control.DefaultLensGraphMouse;
import org.jungrapht.visualization.decorators.PickableElementPaintFunction;
import org.jungrapht.visualization.layout.algorithms.FRLayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.StaticLayoutAlgorithm;
import org.jungrapht.visualization.layout.model.LayoutModel;
import org.jungrapht.visualization.layout.model.Point;
import org.jungrapht.visualization.layout.util.RandomLocationTransformer;
import org.jungrapht.visualization.selection.MutableSelectedState;
import org.jungrapht.visualization.transform.HyperbolicTransformer;
import org.jungrapht.visualization.transform.LayoutLensSupport;
import org.jungrapht.visualization.transform.Lens;
import org.jungrapht.visualization.transform.LensSupport;
import org.jungrapht.visualization.transform.MagnifyTransformer;
import org.jungrapht.visualization.transform.shape.HyperbolicShapeTransformer;
import org.jungrapht.visualization.transform.shape.MagnifyShapeTransformer;
import org.jungrapht.visualization.transform.shape.ViewLensSupport;
import org.jungrapht.visualization.util.LayoutAlgorithmTransition;
/**
* Demonstrates the use of HyperbolicTransform
and MagnifyTransform
* applied to either the model (graph layout) or the view (VisualizationViewer) The transforms are
* applied in an elliptical lens that affects that part of the visualization.
*
* This version of the LensDemo has customized (via properties) graph mouse settings so that
* MouseButtonOne click on a vertex or edge selects it (no additional modifier), click on vertex
* followed by a drag will move the selected vertices, while a click not on a vertex or an edge
* followed by a drag will translate the graph. MouseButtonOne+CTRL (Command on Mac) will initiate
* tracing a rectangle which can be dragged to enclose vertices. When the mouse button is released,
* the contained vertices will be selected.
*
* @author Tom Nelson
*/
public class LensDemoWithDefaultGraphMouseProperyDriven extends JPanel {
/** the graph */
Graph graph;
FRLayoutAlgorithm graphLayoutAlgorithm;
/** a grid shaped graph */
Graph grid;
LayoutAlgorithm gridLayoutAlgorithm;
/** the visual component and renderer for the graph */
VisualizationViewer vv;
/** provides a Hyperbolic lens for the view */
LensSupport hyperbolicViewSupport;
/** provides a magnification lens for the view */
LensSupport magnifyViewSupport;
/** provides a Hyperbolic lens for the model */
LensSupport hyperbolicLayoutSupport;
/** provides a magnification lens for the model */
LensSupport magnifyLayoutSupport;
/** create an instance of a simple graph with controls to demo the zoomand hyperbolic features. */
public LensDemoWithDefaultGraphMouseProperyDriven() {
setLayout(new BorderLayout());
// create a simple graph for the demo
graph = TestGraphs.getOneComponentGraph();
graphLayoutAlgorithm = new FRLayoutAlgorithm<>();
graphLayoutAlgorithm.setMaxIterations(1000);
Dimension preferredSize = new Dimension(600, 600);
Map map = new HashMap<>();
Function vlf = map::get;
grid = this.generateVertexGrid(map, preferredSize, 25);
gridLayoutAlgorithm = new StaticLayoutAlgorithm<>();
final VisualizationModel visualizationModel =
VisualizationModel.builder(graph)
.layoutAlgorithm(graphLayoutAlgorithm)
.layoutSize(preferredSize)
.build();
vv =
VisualizationViewer.builder(visualizationModel)
.graphMouse(new DefaultGraphMouse<>())
.viewSize(preferredSize)
.build();
MutableSelectedState ps = vv.getSelectedVertexState();
MutableSelectedState pes = vv.getSelectedEdgeState();
vv.getRenderContext()
.setVertexFillPaintFunction(
new PickableElementPaintFunction<>(ps, Color.red, Color.yellow));
vv.getRenderContext()
.setEdgeDrawPaintFunction(new PickableElementPaintFunction<>(pes, Color.black, Color.cyan));
vv.getRenderContext().setVertexLabelFunction(Object::toString);
final Function ovals = vv.getRenderContext().getVertexShapeFunction();
final Function squares = n -> new Rectangle2D.Float(-10, -10, 20, 20);
// add a listener for ToolTips
vv.setVertexToolTipFunction(n -> n); //Object::toString);
VisualizationScrollPane visualizationScrollPane = new VisualizationScrollPane(vv);
add(visualizationScrollPane);
// create a lens to share between the two hyperbolic transformers
LayoutModel layoutModel = vv.getVisualizationModel().getLayoutModel();
Dimension d = new Dimension(layoutModel.getWidth(), layoutModel.getHeight());
hyperbolicViewSupport =
ViewLensSupport.builder(vv)
.lensTransformer(
HyperbolicShapeTransformer.builder(
Lens.builder().lensShape(Lens.Shape.ELLIPSE).build())
.delegate(
vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW))
.build())
.lensGraphMouse(new DefaultLensGraphMouse<>())
.useGradient(true)
.build();
hyperbolicLayoutSupport =
LayoutLensSupport.builder(vv)
.lensTransformer(
HyperbolicTransformer.builder(Lens.builder().lensShape(Lens.Shape.ELLIPSE).build())
.delegate(
vv.getRenderContext()
.getMultiLayerTransformer()
.getTransformer(Layer.LAYOUT))
.build())
.lensGraphMouse(new DefaultLensGraphMouse<>())
.useGradient(true)
.build();
// the magnification lens uses a different magnification than the hyperbolic lens
magnifyViewSupport =
ViewLensSupport.builder(vv)
.lensTransformer(
MagnifyShapeTransformer.builder(
Lens.builder().lensShape(Lens.Shape.ELLIPSE).magnification(3.f).build())
.delegate(
vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW))
.build())
.lensGraphMouse(
DefaultLensGraphMouse.builder()
.magnificationFloor(1.0f)
.magnificationCeiling(4.0f)
.build())
.build();
magnifyLayoutSupport =
LayoutLensSupport.builder(vv)
.lensTransformer(
MagnifyTransformer.builder(
Lens.builder().lensShape(Lens.Shape.ELLIPSE).magnification(3.f).build())
.delegate(
vv.getRenderContext()
.getMultiLayerTransformer()
.getTransformer(Layer.LAYOUT))
.build())
.lensGraphMouse(
DefaultLensGraphMouse.builder()
.magnificationFloor(1.0f)
.magnificationCeiling(4.0f)
.build())
.build();
ButtonGroup graphRadio = new ButtonGroup();
JRadioButton graphButton = new JRadioButton("Graph");
graphButton.setSelected(true);
graphButton.addItemListener(
e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
layoutModel.setInitializer(
new RandomLocationTransformer<>(layoutModel.getWidth(), layoutModel.getHeight()));
visualizationModel.setGraph(graph, false);
LayoutAlgorithmTransition.apply(vv, graphLayoutAlgorithm);
vv.getRenderContext().setVertexShapeFunction(ovals);
vv.getRenderContext().setVertexLabelFunction(Object::toString);
vv.repaint();
}
});
JRadioButton gridButton = new JRadioButton("Grid");
gridButton.addItemListener(
e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
layoutModel.setInitializer(vlf);
// so it won't start running the old layout algorithm on the new graph
visualizationModel.setGraph(grid, false);
LayoutAlgorithmTransition.apply(vv, gridLayoutAlgorithm);
vv.getRenderContext().setVertexShapeFunction(squares);
vv.getRenderContext().setVertexLabelFunction(n -> null);
vv.repaint();
}
});
graphRadio.add(graphButton);
graphRadio.add(gridButton);
JPanel modePanel = new JPanel(new GridLayout(2, 1));
modePanel.setBorder(BorderFactory.createTitledBorder("Display"));
modePanel.add(graphButton);
modePanel.add(gridButton);
Box controls = Box.createHorizontalBox();
controls.add(ControlHelpers.getZoomControls("Zoom", vv));
Map lensSupportMap = new LinkedHashMap<>();
lensSupportMap.put("Hyperbolic View", hyperbolicViewSupport);
lensSupportMap.put("Hyperbolic Layout", hyperbolicLayoutSupport);
lensSupportMap.put("Magnified View", magnifyViewSupport);
lensSupportMap.put("Magnified Layout", magnifyLayoutSupport);
controls.add(
LensControlHelper.builder(lensSupportMap)
.containerSupplier(JPanel::new)
.containerLayoutManager(new GridLayout(0, 2))
.title("Lens Controls")
.build()
.container());
add(controls, BorderLayout.SOUTH);
}
private Graph generateVertexGrid(
Map vlf, Dimension d, int interval) {
int count = d.width / interval * d.height / interval;
Graph graph =
GraphTypeBuilder.forGraphType(DefaultGraphType.directedMultigraph())
.buildGraph();
for (int i = 0; i < count; i++) {
int x = interval * i;
int y = x / d.width * interval;
x %= d.width;
Point location = Point.of(x, y);
String vertex = "v" + i;
vlf.put(vertex, location);
graph.addVertex(vertex);
}
return graph;
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new LensDemoWithDefaultGraphMouseProperyDriven());
f.pack();
f.setVisible(true);
}
}