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

org.jungrapht.samples.GraphEditorDemoWithPaletteDefaultMouse Maven / Gradle / Ivy

The newest version!
package org.jungrapht.samples;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
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.Function;
import javax.imageio.ImageIO;
import javax.swing.*;
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultGraphType;
import org.jgrapht.graph.builder.GraphTypeBuilder;
import org.jgrapht.util.SupplierUtil;
import org.jungrapht.samples.util.ControlHelpers;
import org.jungrapht.samples.util.IconPalette;
import org.jungrapht.visualization.VisualizationScrollPane;
import org.jungrapht.visualization.VisualizationViewer;
import org.jungrapht.visualization.annotations.AnnotationControls;
import org.jungrapht.visualization.control.EditingDefaultGraphMouse;
import org.jungrapht.visualization.control.ModalGraphMouse;
import org.jungrapht.visualization.control.SelectionIconListener;
import org.jungrapht.visualization.control.dnd.VertexImageDropTargetListener;
import org.jungrapht.visualization.control.modal.ModeControls;
import org.jungrapht.visualization.decorators.EllipseShapeFunction;
import org.jungrapht.visualization.decorators.IconShapeFunction;
import org.jungrapht.visualization.decorators.PickableElementPaintFunction;
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.StaticLayoutAlgorithm;
import org.jungrapht.visualization.renderers.JLabelEdgeLabelRenderer;
import org.jungrapht.visualization.renderers.JLabelVertexLabelRenderer;
import org.jungrapht.visualization.selection.MutableSelectedState;
import org.jungrapht.visualization.spatial.Spatial;
import org.jungrapht.visualization.util.ParallelEdgeIndexFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This one uses the EditingDefaultGraphMouse with default, editing, and annotating modes. No rotate
 * or shear. Selection and transformation are both available in the default mode. 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 GraphEditorDemoWithPaletteDefaultMouse extends JPanel implements Printable {

  /** */
  private static final Logger log =
      LoggerFactory.getLogger(GraphEditorDemoWithPaletteDefaultMouse.class);
  /** 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<>();

  // Maps for the labels and icons
  Map map = new HashMap<>();
  Map iconMap = 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 GraphEditorDemoWithPaletteDefaultMouse() { setLayout(new BorderLayout()); // create a simple graph for the demo graph = GraphTypeBuilder.forGraphType(DefaultGraphType.directedPseudograph()) .vertexSupplier(SupplierUtil.createIntegerSupplier()) .edgeSupplier(SupplierUtil.createIntegerSupplier()) .buildGraph(); this.layoutAlgorithm = new StaticLayoutAlgorithm<>(); vv = VisualizationViewer.builder(graph) .layoutAlgorithm(layoutAlgorithm) .viewSize(new Dimension(600, 600)) .build(); vv.getRenderContext().setParallelEdgeIndexFunction(new ParallelEdgeIndexFunction<>()); Function vpf = new PickableElementPaintFunction<>(vv.getSelectedVertexState(), Color.white, Color.yellow); vv.getRenderContext().setVertexFillPaintFunction(vpf); vv.getRenderContext() .setEdgeDrawPaintFunction( new PickableElementPaintFunction<>(vv.getSelectedEdgeState(), Color.black, Color.cyan)); vv.getRenderContext().setVertexLabelFunction(map::get); vv.getRenderContext().setVertexLabelRenderer(new JLabelVertexLabelRenderer(Color.cyan)); vv.getRenderContext().setEdgeLabelRenderer(new JLabelEdgeLabelRenderer(Color.cyan)); final IconShapeFunction vertexImageShapeFunction = new IconShapeFunction<>(new EllipseShapeFunction<>()); final Function vertexIconFunction = iconMap::get; vertexImageShapeFunction.setIconFunction(iconMap::get); vv.getRenderContext().setVertexShapeFunction(vertexImageShapeFunction); vv.getRenderContext().setVertexIconFunction(vertexIconFunction); TransferHandler dnd = new TransferHandler() { @Override public boolean canImport(TransferSupport support) { if (!support.isDrop()) { return false; } //only Strings if (!support.isDataFlavorSupported(DataFlavor.imageFlavor)) { return false; } return true; } @Override public boolean importData(TransferSupport support) { if (!canImport(support)) { return false; } Transferable tansferable = support.getTransferable(); Icon ico; try { ico = (Icon) tansferable.getTransferData(DataFlavor.imageFlavor); } catch (Exception e) { e.printStackTrace(); return false; } vv.getComponent().add(new JLabel(ico)); return true; } }; vv.getComponent().setTransferHandler(dnd); // Get the pickedState and add a listener that will decorate the //Vertex images with a checkmark icon when they are selected MutableSelectedState ps = vv.getSelectedVertexState(); ps.addItemListener(new SelectionIconListener<>(vertexIconFunction)); 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); final EditingDefaultGraphMouse graphMouse = EditingDefaultGraphMouse.builder() .renderContextSupplier(vv::getRenderContext) .multiLayerTransformerSupplier(vv.getRenderContext()::getMultiLayerTransformer) .edgeFactory(graph.getEdgeSupplier()) .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.DEFAULT); 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.getEditingDefaultModeComboBox(graphMouse); controls.add(ControlHelpers.getCenteredContainer("Mouse Mode", modeBox)); controls.add(annotationControls.getAnnotationsToolBar()); controls.add(help); add(controls, BorderLayout.SOUTH); add( ControlHelpers.getCenteredContainer("Drag icons to create vertices", new IconPalette()), BorderLayout.EAST); new VertexImageDropTargetListener<>(vv, iconMap::put); } /** * 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(Graphics graphics, java.awt.print.PageFormat pageFormat, int pageIndex) { if (pageIndex > 0) { return (Printable.NO_SUCH_PAGE); } else { Graphics2D g2d = (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(Integer number) { if (vertexLabelMap.containsKey(number)) return vertexLabelMap.get(number); else return number.toString(); } public Map getVertexLabelMap() { return vertexLabelMap; } public Map getEdgeLabelMap() { return edgeLabelMap; } public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); final GraphEditorDemoWithPaletteDefaultMouse demo = new GraphEditorDemoWithPaletteDefaultMouse(); 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