org.jungrapht.samples.GraphEditorDemo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jungrapht-visualization-samples Show documentation
Show all versions of jungrapht-visualization-samples Show documentation
Sample programs using Graph Visualization.
The newest version!
/*
* 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.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.print.Printable;
import java.awt.print.PrinterJob;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import javax.imageio.ImageIO;
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.visualization.VisualizationScrollPane;
import org.jungrapht.visualization.VisualizationViewer;
import org.jungrapht.visualization.annotations.AnnotationControls;
import org.jungrapht.visualization.control.EditingModalGraphMouse;
import org.jungrapht.visualization.control.ModalGraphMouse;
import org.jungrapht.visualization.control.modal.ModeControls;
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.StaticLayoutAlgorithm;
import org.jungrapht.visualization.spatial.Spatial;
import org.jungrapht.visualization.util.ParallelEdgeIndexFunction;
/**
* Shows how to create a graph editor. Mouse modes and actions are explained in the help text.
* GraphEditorDemo provides a File menu with an option to save the visible graph as a jpeg file.
*
* @author Tom Nelson
*/
public class GraphEditorDemo extends JPanel implements Printable {
/** */
private static final long serialVersionUID = -2023243689258876709L;
/** the graph */
Graph graph;
LayoutAlgorithm layoutAlgorithm;
/** the visual component and renderer for the graph */
VisualizationViewer vv;
/** Used in the vertexLabelFunction. Values may be inserted by the EditingGraphMouse */
Map vertexLabelMap = new HashMap<>();
/** Used in the edgeLabelFunction Values may be inserted by the EditingGraphMouse */
Map edgeLabelMap = new HashMap<>();
String instructions =
""
+ "All Modes:
"
+ ""
+ "- Right-click an empty area for Create vertex popup"
+ "
- Right-click on a vertex for Delete vertex popup"
+ "
- Right-click on a vertex for Add Edge menus
(if there are selected Vertices)"
+ " - Right-click on an Edge for Delete Edge popup"
+ "
- Mousewheel scales with a crossover value of 1.0.
"
+ " - scales the graph layout when the combined scale is greater than 1
"
+ " - scales the graph view when the combined scale is less than 1"
+ "
"
+ "Editing Mode:
"
+ ""
+ "- Left-click an empty area to create a new vertex"
+ "
- Left-click on a vertex and drag to another vertex to create an Undirected Edge"
+ "
- Shift+Left-click on a vertex and drag to another vertex to create a Directed Edge"
+ "
"
+ "Picking Mode:
"
+ ""
+ "- Mouse1 on a vertex selects the vertex"
+ "
- Mouse1 elsewhere unselects all Vertices"
+ "
- Mouse1+Shift on a vertex adds/removes vertex selection"
+ "
- Mouse1+drag on a vertex moves all selected Vertices"
+ "
- Mouse1+drag elsewhere selects Vertices in a region"
+ "
- Mouse1+Shift+drag adds selection of Vertices in a new region"
+ "
- Mouse1+CTRL on a vertex selects the vertex and centers the display on it"
+ "
- Mouse1 double-click on a vertex or edge allows you to edit the label"
+ "
"
+ "Transforming Mode:
"
+ ""
+ "- Mouse1+drag pans the graph"
+ "
- Mouse1+Shift+drag rotates the graph"
+ "
- Mouse1+CTRL(or Command)+drag shears the graph"
+ "
- Mouse1 double-click on a vertex or edge allows you to edit the label"
+ "
"
+ "Annotation Mode:
"
+ ""
+ "- Mouse1 begins drawing of a Rectangle"
+ "
- Mouse1+drag defines the Rectangle shape"
+ "
- Mouse1 release adds the Rectangle as an annotation"
+ "
- Mouse1+Shift begins drawing of an Ellipse"
+ "
- Mouse1+Shift+drag defines the Ellipse shape"
+ "
- Mouse1+Shift release adds the Ellipse as an annotation"
+ "
- Mouse3 shows a popup to input text, which will become"
+ "
- a text annotation on the graph at the mouse location"
+ "
"
+ "";
/** create an instance of a simple graph with popup controls to create a graph. */
public GraphEditorDemo() {
setLayout(new BorderLayout());
// create a simple graph for the demo
graph =
GraphTypeBuilder.forGraphType(DefaultGraphType.directedPseudograph())
.buildGraph();
this.layoutAlgorithm = new StaticLayoutAlgorithm<>();
vv =
VisualizationViewer.builder(graph)
.layoutAlgorithm(layoutAlgorithm)
.viewSize(new Dimension(600, 600))
.build();
vv.getRenderContext().setParallelEdgeIndexFunction(new ParallelEdgeIndexFunction<>());
vv.getRenderContext()
.setVertexLabelFunction(
v -> vertexLabelMap.containsKey(v) ? vertexLabelMap.get(v) : v.toString());
vv.getRenderContext()
.setEdgeLabelFunction(
e -> edgeLabelMap.containsKey(e) ? edgeLabelMap.get(e) : e.toString());
vv.setVertexSpatial(new Spatial.NoOp.Vertex(vv.getVisualizationModel().getLayoutModel()));
vv.setEdgeSpatial(new Spatial.NoOp.Edge(vv.getVisualizationModel()));
vv.setVertexToolTipFunction(vv.getRenderContext().getVertexLabelFunction());
final VisualizationScrollPane panel = new VisualizationScrollPane(vv);
add(panel);
Supplier vertexFactory = new VertexFactory();
Supplier edgeFactory = new EdgeFactory();
final EditingModalGraphMouse graphMouse =
EditingModalGraphMouse.builder()
.renderContextSupplier(vv::getRenderContext)
.multiLayerTransformerSupplier(vv.getRenderContext()::getMultiLayerTransformer)
.vertexFactory(vertexFactory)
.edgeFactory(edgeFactory)
.vertexLabelMapSupplier(this::getVertexLabelMap)
.edgeLabelMapSupplier(this::getEdgeLabelMap)
.build();
// the EditingGraphMouse will pass mouse event coordinates to the
// vertexLocations function to set the locations of the vertices as
// they are created
vv.setGraphMouse(graphMouse);
vv.addKeyListener(graphMouse.getModeKeyListener());
graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
JButton help = new JButton("Help");
help.addActionListener(e -> JOptionPane.showMessageDialog(vv.getComponent(), instructions));
AnnotationControls annotationControls =
new AnnotationControls<>(graphMouse.getAnnotatingPlugin());
JPanel controls = new JPanel();
controls.add(ControlHelpers.getZoomControls("Zoom", vv));
JComboBox modeBox = ModeControls.getEditingModeComboBox(graphMouse);
controls.add(ControlHelpers.getCenteredContainer("Mouse Mode", modeBox));
controls.add(annotationControls.getAnnotationsToolBar());
controls.add(help);
add(controls, BorderLayout.SOUTH);
}
/**
* copy the visible part of the graph to a file as a jpeg image
*
* @param file the file in which to save the graph image
*/
public void writeJPEGImage(File file) {
int width = vv.getWidth();
int height = vv.getHeight();
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = bi.createGraphics();
vv.getComponent().paint(graphics);
graphics.dispose();
try {
ImageIO.write(bi, "jpeg", file);
} catch (Exception e) {
e.printStackTrace();
}
}
public int print(
java.awt.Graphics graphics, java.awt.print.PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return (Printable.NO_SUCH_PAGE);
} else {
java.awt.Graphics2D g2d = (java.awt.Graphics2D) graphics;
vv.setDoubleBuffered(false);
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
vv.getComponent().paint(g2d);
vv.setDoubleBuffered(true);
return (Printable.PAGE_EXISTS);
}
}
private String apply(Number number) {
if (vertexLabelMap.containsKey(number)) return vertexLabelMap.get(number);
else return number.toString();
}
static class VertexFactory implements Supplier {
int i = 0;
public Number get() {
return i++;
}
}
static class EdgeFactory implements Supplier {
int i = 0;
public Number get() {
return i++;
}
}
public Map getVertexLabelMap() {
return vertexLabelMap;
}
public Map getEdgeLabelMap() {
return edgeLabelMap;
}
@SuppressWarnings("serial")
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final GraphEditorDemo demo = new GraphEditorDemo();
JMenu menu = new JMenu("File");
menu.add(
new AbstractAction("Make Image") {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
int option = chooser.showSaveDialog(demo);
if (option == JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
demo.writeJPEGImage(file);
}
}
});
menu.add(
new AbstractAction("Print") {
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(demo);
if (printJob.printDialog()) {
try {
printJob.print();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.getContentPane().add(demo);
frame.pack();
frame.setVisible(true);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy