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

org.jungrapht.samples.VertexCollapseDemo 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.BorderLayout;
import java.awt.Dimension;
import java.awt.Shape;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import org.jgrapht.Graph;
import org.jungrapht.samples.util.ControlHelpers;
import org.jungrapht.samples.util.TestGraphs;
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.modal.Modal.Mode;
import org.jungrapht.visualization.control.modal.ModeControls;
import org.jungrapht.visualization.decorators.EllipseShapeFunction;
import org.jungrapht.visualization.layout.algorithms.FRLayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
import org.jungrapht.visualization.sublayout.Collapser;
import org.jungrapht.visualization.util.PredicatedParallelEdgeIndexFunction;

/**
 * A demo that shows how collections of vertices can be collapsed into a single vertex. In this
 * demo, the vertices that are collapsed are those mouse-selected by the user.
 *
 * @author Tom Nelson
 */
public class VertexCollapseDemo extends JPanel {

  String instructions =
      "Use the mouse to select multiple vertices"
          + "

either by dragging a region, or by shift-clicking" + "

on multiple vertices." + "

After you select vertices, use the Collapse button" + "

to combine them into a single vertex." + "

Select a 'collapsed' vertex and use the Expand button" + "

to restore the collapsed vertices." + "

The Restore button will restore the original graph." + "

If you select 2 (and only 2) vertices, then press" + "

the Compress Edges button, parallel edges between" + "

those two vertices will no longer be expanded." + "

If you select 2 (and only 2) vertices, then press" + "

the Expand Edges button, parallel edges between" + "

those two vertices will be expanded." + "

You can drag the vertices with the mouse." + "

Use the 'Picking'/'Transforming' combo-box to switch" + "

between picking and transforming mode."; /** the graph */ Graph graph; /** the visual component and renderer for the graph */ VisualizationViewer vv; LayoutAlgorithm layoutAlgorithm; Collapser collapser; public VertexCollapseDemo() { setLayout(new BorderLayout()); // the graph has to allow self loops and parallel edges in order to // be collapsed and expanded without losing edges this.graph = TestGraphs.getOneComponentGraph(MyVertex::new); layoutAlgorithm = new FRLayoutAlgorithm<>(); Dimension preferredSize = new Dimension(400, 400); final VisualizationModel visualizationModel = VisualizationModel.builder(graph) .layoutAlgorithm(layoutAlgorithm) .layoutSize(preferredSize) .build(); // the regular graph mouse for the normal view final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse<>(); vv = VisualizationViewer.builder(visualizationModel) .graphMouse(graphMouse) .viewSize(preferredSize) .build(); collapser = Collapser.forVisualization(vv); vv.getRenderContext() .setVertexShapeFunction(new ClusterShapeFunction<>(collapser.collapsedGraphFunction())); final Set exclusions = new HashSet<>(); final PredicatedParallelEdgeIndexFunction eif = new PredicatedParallelEdgeIndexFunction<>(exclusions::contains); vv.getRenderContext().setParallelEdgeIndexFunction(eif); // add a listener for ToolTips vv.setVertexToolTipFunction(Object::toString); vv.setEdgeToolTipFunction(Object::toString); VisualizationScrollPane visualizationScrollPane = new VisualizationScrollPane(vv); add(visualizationScrollPane); JComboBox modeBox = ModeControls.getStandardModeComboBox(Mode.PICKING, graphMouse); JButton collapse = new JButton("Collapse"); collapse.addActionListener( e -> SwingUtilities.invokeLater( () -> collapser.collapse(vv.getSelectedVertices(), s -> new MyVertex()))); JButton expand = new JButton("Expand"); expand.addActionListener( e -> SwingUtilities.invokeLater(() -> collapser.expand(vv.getSelectedVertices()))); JButton compressEdges = new JButton("Compress Edges"); compressEdges.addActionListener( e -> { Set picked = vv.getSelectedVertices(); if (picked.size() == 2) { Iterator pickedIter = picked.iterator(); MyVertex vertexU = pickedIter.next(); MyVertex vertexV = pickedIter.next(); Graph graph = vv.getVisualizationModel().getGraph(); Collection edges = new HashSet<>(graph.edgesOf(vertexU)); edges.retainAll(graph.edgesOf(vertexV)); exclusions.addAll(edges); vv.repaint(); } }); JButton expandEdges = new JButton("Expand Edges"); expandEdges.addActionListener( e -> { Set picked = vv.getSelectedVertices(); if (picked.size() == 2) { Iterator pickedIter = picked.iterator(); MyVertex vertexU = pickedIter.next(); MyVertex vertexV = pickedIter.next(); Graph graph = vv.getVisualizationModel().getGraph(); Collection edges = new HashSet<>(graph.edgesOf(vertexU)); edges.retainAll(graph.edgesOf(vertexV)); exclusions.removeAll(edges); vv.repaint(); } }); JButton reset = new JButton("Reset"); reset.addActionListener( e -> { this.graph = TestGraphs.getOneComponentGraph(MyVertex::new); vv.getRenderContext().getParallelEdgeIndexFunction().reset(); vv.getVisualizationModel().setGraph(graph); exclusions.clear(); vv.repaint(); }); JButton help = new JButton("Help"); help.addActionListener( e -> JOptionPane.showMessageDialog( (JComponent) e.getSource(), instructions, "Help", JOptionPane.PLAIN_MESSAGE)); Box controls = Box.createHorizontalBox(); controls.add(ControlHelpers.getZoomControls("Zoom", vv)); controls.add( ControlHelpers.getCenteredContainer( "Picked", Box.createVerticalBox(), collapse, expand, compressEdges, expandEdges, reset)); controls.add(ControlHelpers.getCenteredContainer("Mouse Mode", modeBox)); controls.add(help); add(controls, BorderLayout.SOUTH); } /** * a demo class that will create a vertex shape that is either a polygon or star. The number of * sides corresponds to the number of vertices that were collapsed into the vertex represented by * this shape. */ static class ClusterShapeFunction extends EllipseShapeFunction { Function> function; ClusterShapeFunction(Function> function) { this.function = function; setSizeFunction(new ClusterSizeFunction<>(function, 20)); } @Override public Shape apply(V v) { Graph graph = function.apply(v); if (graph != null) { int size = graph.vertexSet().size(); if (size < 8) { int sides = Math.max(size, 3); return factory.getRegularPolygon(v, sides); } else { return factory.getRegularStar(v, size); } } return super.apply(v); } } /** * A demo class that will make vertices larger if they represent a collapsed collection of * original vertices */ static class ClusterSizeFunction implements Function { int size; Function> function; public ClusterSizeFunction(Function> function, Integer size) { this.function = function; this.size = size; } public Integer apply(V v) { if (function.apply(v) != null) { return 30; } return size; } } /** * simple vertex class for demo Any type will work as long as there is a Supplier to provide a new * instance. The noarg constructor is used in this demo {@code }MyVertex::new} */ static class MyVertex { static int count; int id; MyVertex() { this.id = count++; } @Override public String toString() { return "MyVertex{" + "id=" + id + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyVertex myVertex = (MyVertex) o; return id == myVertex.id; } @Override public int hashCode() { return Objects.hash(id); } } public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new VertexCollapseDemo()); f.pack(); f.setVisible(true); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy