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

org.jungrapht.samples.tree.RandomDAGExampleWithSatellite Maven / Gradle / Ivy

The newest version!
package org.jungrapht.samples.tree;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import com.google.common.base.Strings;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ItemEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.TitledBorder;
import org.jgrapht.Graph;
import org.jungrapht.samples.util.ControlHelpers;
import org.jungrapht.samples.util.TestGraphs;
import org.jungrapht.samples.util.TreeLayoutSelector;
import org.jungrapht.visualization.SatelliteVisualizationViewer;
import org.jungrapht.visualization.VisualizationViewer;
import org.jungrapht.visualization.decorators.EdgeShape;
import org.jungrapht.visualization.decorators.EllipseShapeFunction;
import org.jungrapht.visualization.decorators.IconShapeFunction;
import org.jungrapht.visualization.layout.algorithms.util.InitialDimensionFunction;
import org.jungrapht.visualization.renderers.Renderer;
import org.jungrapht.visualization.util.AWT;
import org.jungrapht.visualization.util.IconCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** @author Tom Nelson */
public class RandomDAGExampleWithSatellite extends JPanel {

  private static final Logger log = LoggerFactory.getLogger(RandomDAGExampleWithSatellite.class);

  static Set prioritySet = Set.of(0, 2, 6, 8);

  static Predicate edgePredicate = e -> false;

  Graph graph;

  /** the visual component and renderer for the graph */
  VisualizationViewer vv;

  public RandomDAGExampleWithSatellite() {

    setLayout(new BorderLayout());
    // create a simple graph for the demo
    graph = TestGraphs.createDirectedAcyclicGraph(9, 3, .2, 5L);

    vv = VisualizationViewer.builder(graph).viewSize(new Dimension(900, 600)).build();
    vv.getRenderContext().setEdgeShapeFunction(EdgeShape.line());
    // need to update the edge spatial structure
    // add a listener for ToolTips
    vv.setVertexToolTipFunction(Object::toString);
    vv.getRenderContext().setArrowFillPaintFunction(n -> Color.lightGray);

    vv.getRenderContext().setVertexLabelPosition(Renderer.VertexLabel.Position.CNTR);
    vv.getRenderContext().setVertexLabelDrawPaintFunction(c -> Color.white);

    Dimension preferredSatelliteSize = new Dimension(250, 250);

    final SatelliteVisualizationViewer satelliteVisualizationViewer =
        SatelliteVisualizationViewer.builder(vv).viewSize(preferredSatelliteSize).build();

    this.add(vv.getComponent());

    vv.getComponent().setLayout(null);
    vv.add(satelliteVisualizationViewer.getComponent());
    Dimension sd = satelliteVisualizationViewer.getSize();
    vv.getComponent()
        .addComponentListener(
            new ComponentAdapter() {
              @Override
              public void componentResized(ComponentEvent e) {
                super.componentResized(e);
                Component vv = e.getComponent();
                Dimension vvd = vv.getSize();
                Point p = new Point(vvd.width - sd.width, vvd.height - sd.height);
                satelliteVisualizationViewer
                    .getComponent()
                    .setBounds(p.x, p.y, sd.width, sd.height);
              }
            });

    IconCache iconCache =
        IconCache.builder(Object::toString)
            .vertexShapeFunction(vv.getRenderContext().getVertexShapeFunction())
            .colorFunction(
                n -> {
                  if (graph.degreeOf(n) > 9) return Color.red;
                  if (graph.degreeOf(n) < 7) return Color.green;
                  return Color.lightGray;
                })
            .stylist(
                (label, vertex, colorFunction) -> {
                  label.setFont(new Font("Serif", Font.BOLD, 20));
                  label.setForeground(Color.black);
                  label.setBackground(Color.white);
                  Border lineBorder = BorderFactory.createEtchedBorder();
                  Border marginBorder = BorderFactory.createEmptyBorder(4, 4, 4, 4);
                  label.setBorder(new CompoundBorder(lineBorder, marginBorder));
                })
            .preDecorator(
                (graphics, vertex, labelBounds, vertexShapeFunction, colorFunction) -> {
                  Color color = (Color) colorFunction.apply(vertex);
                  color =
                      new Color(
                          color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha() / 4);
                  // save off the old color
                  Color oldColor = graphics.getColor();
                  // fill the image background with white
                  graphics.setPaint(Color.white);
                  graphics.fill(labelBounds);

                  Shape shape = vertexShapeFunction.apply(vertex);
                  Rectangle2D bounds = shape.getBounds2D();

                  AffineTransform scale =
                      AffineTransform.getScaleInstance(
                          labelBounds.width / bounds.getWidth(),
                          labelBounds.height / bounds.getHeight());
                  AffineTransform translate =
                      AffineTransform.getTranslateInstance(
                          labelBounds.width / 2, labelBounds.height / 2);
                  translate.concatenate(scale);
                  shape = translate.createTransformedShape(shape);
                  graphics.setColor(color);
                  graphics.fill(shape);
                  graphics.setColor(oldColor);
                })
            .build();

    final IconShapeFunction vertexImageShapeFunction =
        new IconShapeFunction<>(new EllipseShapeFunction<>());
    vertexImageShapeFunction.setIconFunction(iconCache);

    vv.getRenderContext().setVertexShapeFunction(vertexImageShapeFunction);
    vv.getRenderContext().setVertexIconFunction(iconCache);
    vv.setInitialDimensionFunction(
        InitialDimensionFunction.builder()
            .vertexShapeFunction(
                vertexImageShapeFunction.andThen(s -> AWT.convert(s.getBounds2D())))
            .build());

    vv.getRenderContext()
        .getSelectedVertexState()
        .select(
            Stream.concat(
                    vv.getVisualizationModel()
                        .getGraph()
                        .edgeSet()
                        .stream()
                        .filter(edgePredicate)
                        .map(e -> graph.getEdgeTarget(e)),
                    vv.getVisualizationModel()
                        .getGraph()
                        .edgeSet()
                        .stream()
                        .filter(edgePredicate)
                        .map(e -> graph.getEdgeSource(e)))
                .collect(Collectors.toList()));

    TreeLayoutSelector treeLayoutSelector =
        TreeLayoutSelector.builder(vv)
            .edgePredicate(edgePredicate)
            .initialSelection(2)
            .vertexShapeFunction(vv.getRenderContext().getVertexShapeFunction())
            .alignFavoredEdges(false)
            .build();

    JRadioButton showSpatialEffects = new JRadioButton("Show Structure");
    showSpatialEffects.addItemListener(
        e -> {
          if (e.getStateChange() == ItemEvent.SELECTED) {
            System.err.println("TURNED ON LOGGING");
            // turn on the logging
            // programmatically set the log level so that the spatial grid is drawn for this demo and the SpatialGrid logging is output
            ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) log;
            LoggerContext ctx = (LoggerContext) LoggerFactory.getILoggerFactory();
            ctx.getLogger("org.jungrapht.visualization.layout.spatial").setLevel(Level.DEBUG);
            ctx.getLogger("org.jungrapht.visualization.DefaultVisualizationServer")
                .setLevel(Level.TRACE);
            ctx.getLogger("org.jungrapht.visualization.picking").setLevel(Level.TRACE);
            repaint();

          } else if (e.getStateChange() == ItemEvent.DESELECTED) {
            System.err.println("TURNED OFF LOGGING");
            // turn off the logging
            // programmatically set the log level so that the spatial grid is drawn for this demo and the SpatialGrid logging is output
            ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) log;
            LoggerContext ctx = (LoggerContext) LoggerFactory.getILoggerFactory();
            ctx.getLogger("org.jungrapht.visualization.layout.spatial").setLevel(Level.INFO);
            ctx.getLogger("org.jungrapht.visualization.DefaultVisualizationServer")
                .setLevel(Level.INFO);
            ctx.getLogger("org.jungrapht.visualization.picking").setLevel(Level.INFO);
            repaint();
          }
        });

    JTextField layersText = new JTextField("10", 15);
    layersText.setBorder(new TitledBorder("Graph Layers"));
    JTextField maxVerticesPerLayerText = new JTextField("4", 15);
    maxVerticesPerLayerText.setBorder(new TitledBorder("Max V per Layer"));
    JTextField linkProbabilityText = new JTextField("0.2", 15);
    linkProbabilityText.setBorder(new TitledBorder("Link Probabilty"));
    JTextField randomSeedText = new JTextField("7", 15);
    randomSeedText.setBorder(new TitledBorder("Random Seed"));

    JTextField maxLevelCrossText = new JTextField("23", 15);
    maxLevelCrossText.setBorder(new TitledBorder("Max Level Cross"));

    JPanel graphPropertyPanel = new JPanel(new GridLayout(2, 2));
    graphPropertyPanel.add(layersText);
    graphPropertyPanel.add(maxVerticesPerLayerText);
    graphPropertyPanel.add(linkProbabilityText);
    graphPropertyPanel.add(randomSeedText);
    JPanel floater = new JPanel();
    floater.setBorder(new TitledBorder("Graph Generator"));
    floater.add(graphPropertyPanel);
    ActionListener action =
        e -> {
          int layers = 9;
          if (!Strings.isNullOrEmpty(layersText.getText())) {
            try {
              layers = Integer.parseInt(layersText.getText());
            } catch (Exception ex) {
            }
          }
          int maxVerticesPerLayer = 3;
          if (!Strings.isNullOrEmpty(layersText.getText())) {
            try {
              maxVerticesPerLayer = Integer.parseInt(maxVerticesPerLayerText.getText());
            } catch (Exception ex) {
            }
          }
          double linkProbability = 0.2;
          if (!Strings.isNullOrEmpty(linkProbabilityText.getText())) {
            try {
              linkProbability = Double.parseDouble(linkProbabilityText.getText());
            } catch (Exception ex) {
            }
          }
          long randomSeed = System.currentTimeMillis();
          if (!Strings.isNullOrEmpty(randomSeedText.getText())) {
            try {
              randomSeed = Long.parseLong(randomSeedText.getText());
            } catch (Exception ex) {
            }
          }
          resetGraph(layers, maxVerticesPerLayer, linkProbability, randomSeed);
        };
    layersText.addActionListener(action);
    maxVerticesPerLayerText.addActionListener(action);
    linkProbabilityText.addActionListener(action);
    randomSeedText.addActionListener(action);

    Box controls = Box.createHorizontalBox();
    controls.add(ControlHelpers.getCenteredContainer("Layout Controls", treeLayoutSelector));
    Box rightControls = Box.createVerticalBox();
    rightControls.add(floater);
    JPanel spatialPanel = new JPanel();
    spatialPanel.setBorder(new TitledBorder("Spatial Structure"));
    spatialPanel.add(showSpatialEffects);
    rightControls.add(spatialPanel);
    controls.add(rightControls);
    add(controls, BorderLayout.SOUTH);
  }

  private void resetGraph(
      int layers, int maxVerticesPerLayer, double linkProbability, long randomSeed) {
    this.graph =
        TestGraphs.createDirectedAcyclicGraph(
            layers, maxVerticesPerLayer, linkProbability, randomSeed);
    vv.getVisualizationModel().getLayoutModel().setSize(600, 600); // put back original size
    vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
    vv.getVisualizationModel().setGraph(this.graph, true);
  }

  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new RandomDAGExampleWithSatellite());
    f.pack();
    f.setVisible(true);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy