org.jgrapht.ext.JGraphXAdapter Maven / Gradle / Ivy
/*
* (C) Copyright 2013-2016, by JeanYves Tinevez and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package org.jgrapht.ext;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.event.*;
import com.mxgraph.model.*;
import com.mxgraph.view.*;
/**
*
* Adapter to draw a JGraphT graph with the JGraphX drawing library.
*
*
*
* This adapter will not convert JGraphX to JGraphT - this should be handled in another class
* entirely.
*
*
*
* Known Bugs: If this class is used with String-Edges, please note that there is a bug with the
* method JgraphT.addEdge(vertex1, vertex2); The edge will be created with an empty String "" as
* value and saved (in JGraphT as well as in this class), which results in the edge not saving
* correctly. So, if you're using Strings as Edgeclass please use the method addEdge(vertex1,
* vertex2, "Edgename"); with a unique edgename.
*
*
* @param the graph vertex type
* @param the graph edge type
*
* @author JeanYves Tinevez
* @since 09 July, 2013
*/
public class JGraphXAdapter
extends mxGraph
implements GraphListener
{
/**
* The graph to be drawn. Has vertices "V" and edges "E".
*/
private Graph graphT;
/**
* Maps the JGraphT-Vertices onto JGraphX-mxICells. {@link #cellToVertexMap} is for the opposite
* direction.
*/
private HashMap vertexToCellMap = new HashMap<>();
/**
* Maps the JGraphT-Edges onto JGraphX-mxICells. {@link #cellToEdgeMap} is for the opposite
* direction.
*/
private HashMap edgeToCellMap = new HashMap<>();
/**
* Maps the JGraphX-mxICells onto JGraphT-Edges. {@link #edgeToCellMap} is for the opposite
* direction.
*/
private HashMap cellToVertexMap = new HashMap<>();
/**
* Maps the JGraphX-mxICells onto JGraphT-Vertices. {@link #vertexToCellMap} is for the opposite
* direction.
*/
private HashMap cellToEdgeMap = new HashMap<>();
/**
* Constructs and draws a new ListenableGraph. If the graph changes through as ListenableGraph,
* the JGraphXAdapter will automatically add/remove the new edge/vertex as it implements the
* GraphListener interface. Throws a IllegalArgumentException if the graph is null.
*
* @param graph casted to graph
*/
public JGraphXAdapter(ListenableGraph graph)
{
// call normal constructor with graph class
this((Graph) graph);
graph.addGraphListener(this);
}
/**
* Constructs and draws a new mxGraph from a jGraphT graph. Changes on the jgraphT graph will
* not edit this mxGraph any further; use the constructor with the ListenableGraph parameter
* instead or use this graph as a normal mxGraph. Throws an IllegalArgumentException if the
* parameter is null.
*
* @param graph is a graph
*/
public JGraphXAdapter(Graph graph)
{
super();
// Don't accept null as jgrapht graph
if (graph == null) {
throw new IllegalArgumentException();
} else {
this.graphT = graph;
}
// generate the drawing
insertJGraphT(graph);
setAutoSizeCells(true);
}
/**
* Returns Hashmap which maps the vertices onto their visualization mxICells.
*
* @return {@link #vertexToCellMap}
*/
public HashMap getVertexToCellMap()
{
return vertexToCellMap;
}
/**
* Returns Hashmap which maps the edges onto their visualization mxICells.
*
* @return {@link #edgeToCellMap}
*/
public HashMap getEdgeToCellMap()
{
return edgeToCellMap;
}
/**
* Returns Hashmap which maps the visualization mxICells onto their edges.
*
* @return {@link #cellToEdgeMap}
*/
public HashMap getCellToEdgeMap()
{
return cellToEdgeMap;
}
/**
* Returns Hashmap which maps the visualization mxICells onto their vertices.
*
* @return {@link #cellToVertexMap}
*/
public HashMap getCellToVertexMap()
{
return cellToVertexMap;
}
@Override
public void vertexAdded(GraphVertexChangeEvent e)
{
addJGraphTVertex(e.getVertex());
}
@Override
public void vertexRemoved(GraphVertexChangeEvent e)
{
mxICell cell = vertexToCellMap.remove(e.getVertex());
removeCells(new Object[] { cell });
// remove vertex from hashmaps
cellToVertexMap.remove(cell);
vertexToCellMap.remove(e.getVertex());
// remove all edges that connected to the vertex
ArrayList removedEdges = new ArrayList<>();
// first, generate a list of all edges that have to be deleted
// so we don't change the cellToEdgeMap.values by deleting while
// iterating
// we have to iterate over this because the graphT has already
// deleted the vertex and edges so we can't query what the edges were
for (E edge : cellToEdgeMap.values()) {
if (!graphT.edgeSet().contains(edge)) {
removedEdges.add(edge);
}
}
// then delete all entries of the previously generated list
for (E edge : removedEdges) {
removeEdge(edge);
}
}
@Override
public void edgeAdded(GraphEdgeChangeEvent e)
{
addJGraphTEdge(e.getEdge());
}
@Override
public void edgeRemoved(GraphEdgeChangeEvent e)
{
removeEdge(e.getEdge());
}
/**
* Removes a jgrapht edge and its visual representation from this graph completely.
*
* @param edge The edge that will be removed
*/
private void removeEdge(E edge)
{
mxICell cell = edgeToCellMap.remove(edge);
removeCells(new Object[] { cell });
// remove edge from hashmaps
cellToEdgeMap.remove(cell);
edgeToCellMap.remove(edge);
}
/**
* Draws a new vertex into the graph.
*
* @param vertex vertex to be added to the graph
*/
private void addJGraphTVertex(V vertex)
{
getModel().beginUpdate();
try {
// create a new JGraphX vertex at position 0
mxICell cell = (mxICell) insertVertex(defaultParent, null, vertex, 0, 0, 0, 0);
// update cell size so cell isn't "above" graph
updateCellSize(cell);
// Save reference between vertex and cell
vertexToCellMap.put(vertex, cell);
cellToVertexMap.put(cell, vertex);
} finally {
getModel().endUpdate();
}
}
/**
* Draws a new egde into the graph.
*
* @param edge edge to be added to the graph. Source and target vertices are needed.
*/
private void addJGraphTEdge(E edge)
{
getModel().beginUpdate();
try {
// find vertices of edge
V sourceVertex = graphT.getEdgeSource(edge);
V targetVertex = graphT.getEdgeTarget(edge);
// if the one of the vertices is not drawn, don't draw the edge
if (!(vertexToCellMap.containsKey(sourceVertex)
&& vertexToCellMap.containsKey(targetVertex)))
{
return;
}
// get mxICells
Object sourceCell = vertexToCellMap.get(sourceVertex);
Object targetCell = vertexToCellMap.get(targetVertex);
// add edge between mxICells
mxICell cell = (mxICell) insertEdge(defaultParent, null, edge, sourceCell, targetCell);
// update cell size so cell isn't "above" graph
updateCellSize(cell);
// Save reference between vertex and cell
edgeToCellMap.put(edge, cell);
cellToEdgeMap.put(cell, edge);
} finally {
getModel().endUpdate();
}
}
/**
* Draws a given graph with all its vertices and edges.
*
* @param graph the graph to be added to the existing graph.
*/
private void insertJGraphT(Graph graph)
{
for (V vertex : graph.vertexSet()) {
addJGraphTVertex(vertex);
}
for (E edge : graph.edgeSet()) {
addJGraphTEdge(edge);
}
}
}
// End JGraphXAdapter.java
© 2015 - 2025 Weber Informatics LLC | Privacy Policy