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

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

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.ItemEvent;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
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.samples.util.VerticalLabelUI;
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.DefaultModalGraphMouse;
import org.jungrapht.visualization.control.ModalLensGraphMouse;
import org.jungrapht.visualization.control.modal.Modal;
import org.jungrapht.visualization.control.modal.ModeMenu;
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.*;
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 a rectangular lens that affects that part of the visualization.
 *
 * @author Tom Nelson
 */
public class RectangularLensDemo 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 RectangularLensDemo() {

    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<>();

    // the regular graph mouse for the normal view
    final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse<>();

    final VisualizationModel visualizationModel =
        VisualizationModel.builder(graph)
            .layoutAlgorithm(graphLayoutAlgorithm)
            .layoutSize(preferredSize)
            .build();
    vv =
        VisualizationViewer.builder(visualizationModel)
            .graphMouse(graphMouse)
            .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.RECTANGLE).build())
                    .delegate(
                        vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW))
                    .build())
            .lensGraphMouse(
                ModalLensGraphMouse.builder()
                    .magnificationFloor(0.4f)
                    .magnificationCeiling(1.0f)
                    .magnificationDelta(0.05f)
                    .build())
            .build();

    hyperbolicLayoutSupport =
        LayoutLensSupport.builder(vv)
            .lensTransformer(
                HyperbolicTransformer.builder(
                        Lens.builder().lensShape(Lens.Shape.RECTANGLE).build())
                    .delegate(
                        vv.getRenderContext()
                            .getMultiLayerTransformer()
                            .getTransformer(Layer.LAYOUT))
                    .build())
            .lensGraphMouse(new ModalLensGraphMouse())
            .build();

    // the magnification lens uses a different magnification than the hyperbolic lens
    magnifyViewSupport =
        ViewLensSupport.builder(vv)
            .lensTransformer(
                MagnifyShapeTransformer.builder(
                        Lens.builder().lensShape(Lens.Shape.RECTANGLE).magnification(3.f).build())
                    .delegate(
                        vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW))
                    .build())
            .lensGraphMouse(
                ModalLensGraphMouse.builder()
                    .magnificationFloor(0.4f)
                    .magnificationCeiling(1.0f)
                    .magnificationDelta(0.05f)
                    .build())
            .build();

    magnifyLayoutSupport =
        LayoutLensSupport.builder(vv)
            .lensTransformer(
                MagnifyTransformer.builder(
                        Lens.builder().lensShape(Lens.Shape.RECTANGLE).magnification(3.f).build())
                    .delegate(
                        vv.getRenderContext()
                            .getMultiLayerTransformer()
                            .getTransformer(Layer.LAYOUT))
                    .build())
            .lensGraphMouse(new ModalLensGraphMouse())
            .build();

    JLabel modeLabel = new JLabel("     Mode Menu >>");
    modeLabel.setUI(new VerticalLabelUI(false));

    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(3, 1));
    modePanel.setBorder(BorderFactory.createTitledBorder("Display"));
    modePanel.add(graphButton);
    modePanel.add(gridButton);

    JMenuBar menubar = new JMenuBar();
    menubar.add(
        ModeMenu.builder()
            .modes(Modal.Mode.TRANSFORMING, Modal.Mode.PICKING)
            .modals(
                graphMouse,
                hyperbolicLayoutSupport.getGraphMouse(),
                hyperbolicViewSupport.getGraphMouse(),
                magnifyLayoutSupport.getGraphMouse(),
                magnifyViewSupport.getGraphMouse())
            .build()
            .buildUI());

    visualizationScrollPane.setCorner(menubar);

    Box controls = Box.createHorizontalBox();
    controls.add(ControlHelpers.getZoomControls("Zoom", vv));
    controls.add(
        LensControlHelper.builder(
                Map.of(
                    "Hyperbolic View",
                    hyperbolicViewSupport,
                    "Hyperbolic Layout",
                    hyperbolicLayoutSupport,
                    "Magnified View",
                    magnifyViewSupport,
                    "Magnified Layout",
                    magnifyLayoutSupport))
            .containerSupplier(JPanel::new)
            .containerLayoutManager(new GridLayout(0, 2))
            .title("Lens Controls")
            .build()
            .container());

    controls.add(modePanel);
    controls.add(modeLabel);
    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 RectangularLensDemo());
    f.pack();
    f.setVisible(true);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy