ontologyvisualizationviewer.java
来自「Semantic Web Ontology Editor」· Java 代码 · 共 1,510 行 · 第 1/3 页
JAVA
1,510 行
/*
* Created on Jul 27, 2005
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
/**
* @author Dave Wang
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.mindswap.swoop.utils.graph.hierarchy;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.mindswap.swoop.SwoopModel;
import edu.uci.ics.jung.exceptions.FatalException;
import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.impl.DirectedSparseGraph;
import edu.uci.ics.jung.graph.impl.DirectedSparseVertex;
import edu.uci.ics.jung.utils.PickEventListener;
import edu.uci.ics.jung.visualization.GraphMouseListener;
import edu.uci.ics.jung.visualization.Layout;
import edu.uci.ics.jung.visualization.MultiPickedState;
import edu.uci.ics.jung.visualization.PickSupport;
import edu.uci.ics.jung.visualization.PickedState;
import edu.uci.ics.jung.visualization.Renderer;
import edu.uci.ics.jung.visualization.StatusCallback;
import edu.uci.ics.jung.visualization.VisualizationViewer;
/**
* A class that maintains many of the details necessary for creating
* visualizations of graphs.
*
* @author Joshua O'Madadhain
* @author Tom Nelson
* @author Danyel Fisher
*/
public class OntologyVisualizationViewer extends VisualizationViewer
{
//protected StatusCallback statusCallback;
Thread relaxer;
boolean suspended;
boolean manualSuspend;
private SwoopModel myModel = null;
private OntologyWithClassHierarchyGraph myGraph = null;
protected Set previousSelectedNodes = null; // selected nodes (by
// mouse/selection list)
protected Set previousHighlightedNodes = null; // highlighted nodes (by
// search box)
protected SwoopOntologyVertex previousSelectedVertex = null; // selected
// vertex by
// mouse
protected ClassTreeNode listBrowsedNode = null; // viewed/browsed in the class list
protected ClassTreeNode rightSelectedNode = null; // right clicked node
protected ClassTreeNode currentSelectedNode = null; // the node that's selected by user
//protected Renderer renderer;
//protected Layout layout;
//protected ToolTipListener toolTipListener;
/**
* holds the values for zoom/pan of the display
*/
//protected AffineTransform transform;
/**
* the inverse of transform. Used to map window points to graph points.
* Lazily created in transform method and reset to null any time transform
* is changed.
*/
//protected AffineTransform inverse;
//protected Map renderingHints = new HashMap();
/**
* pluggable support for picking graph elements by finding them based on
* their coordinates. Typically used in mouse events.
*/
//protected PickSupport pickSupport;
/**
* pluggable support for handling the picked/not-picked state of graph
* elements.
*/
//protected PickedState pickedState;
/**
* an offscreen image to render the graph
*/
//protected BufferedImage offscreen;
/**
* graphics context for the offscreen image
*/
//protected Graphics2D offscreenG2d;
/**
* a collection of user-implementable functions to render under the topology
* (before the graph is rendered)
*/
//protected List preRenderers = new ArrayList();
/**
* a collection of user-implementable functions to render over the topology
* (after the graph is rendered)
*/
//protected List postRenderers = new ArrayList();
//protected long relaxerThreadSleepTime = 20L;
/**
* The <code>changeListener</code>.
*/
//protected ChangeListener changeListener;
/**
* Only one <code>ChangeEvent</code> is needed instance since the event's
* only state is the source property. The source of events generated is
* always "this".
*/
//protected transient ChangeEvent changeEvent;
//public Object pauseObject = new String("PAUSE OBJECT");
// keeps track of where the current view port is centered at
protected double currentX = 0;
protected double currentY = 0;
// debugging values
private boolean DEBUG = false;
private double DEBUGX = 0;
private double DEBUGY = 0;
private double DEBUGW = 0;
private double DEBUGH = 0;
private double DX = 0;
private double DY = 0;
/**
* The VisualizationViewer constructor creates a JPanel based a given Layout
* and Renderer. While GraphDraw places reasonable defaults on these, this
* gives more precise control.
*
* @param layout
* The Layout to apply, with its associated Graph
* @param renderer
* The Renderer to draw it with
*/
public OntologyVisualizationViewer(SwoopModel model,
OntologyWithClassHierarchyGraph graph, Layout layout, Renderer r) {
super(layout, r);
myModel = model;
myGraph = graph;
// adding postrenderer (overlaygraph)
//postRenderers.add(myGraph.getOverlayGraph());
// code copied from the constructor.
setDoubleBuffered( true );
this.transform = new AffineTransform();
this.addComponentListener(new VisualizationListener(this));
this.renderer = r;
pickedState = new MultiPickedState();
if (layout instanceof PickEventListener)
pickedState.addListener((PickEventListener) layout);
r.setPickedKey(pickedState);
this.layout = layout;
//setPreferredSize(new Dimension(640, 600));
//setSize(640, 600);
Dimension d = getPreferredSize();
Dimension ld = layout.getCurrentSize();
// if the layout has NOT been intialized yet, initialize it
// now to be the same size as the VisualizationViewer window
if (ld == null) {
System.out.println("Ont VV constructor: layout not init" );
layout.initialize(d);
}
ld = layout.getCurrentSize();
if (DEBUG)
{
System.out.println( " vv preferred size: w=" + d.width + " h=" + d.height);
System.out.println( " layout current: w=" + ld.width + " lh=" + d.height);
System.out.println( " after init" );
System.out.println( " layout current: w=" + ld.width + " lh=" + d.height);
}
// set my scale to show the entire layout
setScale((float) d.width / ld.width, (float) d.height / ld.height,
new Point2D.Float());
this.suspended = true;
this.manualSuspend = false;
renderingHints.put(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
init();
initMouseClicker();
}
private Rectangle getViewRectangle()
{
DirectedSparseGraph graph = myGraph.getVisualGraph();
Set vertices = graph.getVertices();
double xmin = Integer.MAX_VALUE;
double xmax = Integer.MIN_VALUE;
double ymin = Integer.MAX_VALUE;
double ymax = Integer.MIN_VALUE;
for (Iterator it = vertices.iterator(); it.hasNext();) {
Vertex v = (Vertex) it.next();
//System.out.println("v x,y= " + layout.getX(v) + " " + layout.getY(v));
OntologyGraphNode ontNode = ((OntologyGraphNode) v.getUserDatum(OntologyWithClassHierarchyGraph.DATA));
int r = ontNode.getRadius();
//System.out.println( "radius = " + r);
double x = layout.getX(v);
double y = layout.getY(v);
if ((x - r) < xmin)
xmin = x - r;
if ((x + r) > xmax)
xmax = x + r;
if ((y - r) < ymin)
ymin = y - r;
if ((y + r) > ymax)
ymax = y + r;
}
Rectangle rect = new Rectangle( (int)xmin, (int)ymin, (int)(xmax - xmin), (int)(ymax - ymin));
return rect;
}
/*
* Called by OntologyWithClassHierarchyGraph at init time to zoom in / center at the
* graph so every vertex on the graph is in the view port.
*
*/
public void autoPanZoom()
{
Rectangle rect = getViewRectangle();
int xfocus = (int) ( (rect.width/2 + rect.x) );
int yfocus = (int) ( (rect.height/2 + rect.y) );
// getting the size of the screen space
int screenWidth = this.getWidth();
int screenHeight = this.getHeight();
double hw = screenWidth / 2;
double hh = screenHeight / 2;
Point2D point = transform( new Point2D.Double( screenWidth/2, screenHeight/2) );
Point2D focus = this.transformGraph2Screen( new Point2D.Double( xfocus, yfocus));
if (DEBUG)
{
System.out.println( " screenWidth = " + screenWidth + " screenHeight = "+ screenHeight );
System.out.println( " xmin = " + rect.x + " ymin = " + rect.y + " xmax " + ( rect.width + rect.x ) + " ymax " + (rect.height + rect.y ));
System.out.println( " xfocus = " + xfocus + " yfocus = " + yfocus );
System.out.println( " center of screen: x=" + (screenWidth/2) + " y=" + (screenHeight/2) );
System.out.println( " graphspace of centerscreen: " + point.getX() + " " + point.getY() );
System.out.println( " screensapce: xfocus = " + focus.getX() + " yfocus " + focus.getY() );
System.out.println( " scaling = " + this.getScaleX());
}
DX = focus.getX();
DY = focus.getY();
DEBUGX = rect.x;
DEBUGY = rect.y;
DEBUGW = rect.width ;
DEBUGH = rect.height;
// compute for the necessary translation offsets to center
double translateOffsetX = (point.getX() - xfocus);
double translateOffsetY = (point.getY() - yfocus);
//double translateOffsetX = 0;
//double translateOffsetY = 0;
// compute for the appropriate scaling factor for zoom in
double min = Math.min(screenHeight, screenWidth);
double graphMaxLength = Math.max(( rect.width), (rect.height));
double scaleX = min / (graphMaxLength) / this.getScaleX();
if (scaleX > 1)
scaleX = 1;
double scaleY = scaleX;
// apply translation and zooming
this.translate(translateOffsetX, translateOffsetY);
this.scale(scaleX, scaleY);
// set initial position of where the viewer is viewing
this.currentX = xfocus;
this.currentY = yfocus;
}
public void autoPanZoomTest()
{
Rectangle rect = getViewRectangle();
int xfocus = (int) ( (rect.width/2 + rect.x) );
int yfocus = (int) ( (rect.height/2 + rect.y) );
int screenWidth = this.getWidth();
int screenHeight = this.getHeight();
double hw = screenWidth / 2;
double hh = screenHeight / 2;
double translateOffsetX = (currentX - xfocus);
double translateOffsetY = (currentY - yfocus);
double min = Math.min(screenHeight, screenWidth);
double graphMaxLength = Math.max(( rect.width ), ( rect.height ));
double scaleX = min / (graphMaxLength) / this.getScaleX();
if (scaleX > 1)
scaleX = 1;
double scaleY = scaleX;
this.translate(translateOffsetX, translateOffsetY);
this.scale(scaleX, scaleY);
}
/**
* Returns the time between iterations of the Relaxer thread. The Relaxer
* thread sleeps for a moment before calling the Layout to update again.
* This tells how long the current delay is. The default, 20 milliseconds,
* essentially causes the system to run the next iteration with virtually no
* pause.
*
* @return Returns the relaxerThreadSleepTime.
*/
public long getRelaxerThreadSleepTime() {
return relaxerThreadSleepTime;
}
/**
* Sets the relaxerThreadSleepTime.
*
* @see #getRelaxerThreadSleepTime()
* @param relaxerThreadSleepTime
* The relaxerThreadSleepTime to set.
*/
public void setRelaxerThreadSleepTime(long relaxerThreadSleepTime) {
this.relaxerThreadSleepTime = relaxerThreadSleepTime;
}
/**
* Creates a default mouseClicker behavior: a default
*
* @link{GraphMouseImpl}
* @deprecated replaced by setGraphMouse()
*/
protected void initMouseClicker() {
// GraphMouseImpl will give original behavior
setGraphMouse(new GraphMouseImpl(this));
}
/**
* a setter for the GraphMouse. This will remove any previous GraphMouse
* (including the one that is added in the initMouseClicker method.
*
* @param graphMouse
* new value
*/
public void setGraphMouse(GraphMouse graphMouse) {
MouseListener[] ml = getMouseListeners();
for (int i = 0; i < ml.length; i++) {
if (ml[i] instanceof GraphMouse) {
removeMouseListener(ml[i]);
}
}
MouseMotionListener[] mml = getMouseMotionListeners();
for (int i = 0; i < mml.length; i++) {
if (mml[i] instanceof GraphMouse) {
removeMouseMotionListener(mml[i]);
}
}
MouseWheelListener[] mwl = getMouseWheelListeners();
for (int i = 0; i < mwl.length; i++) {
if (mwl[i] instanceof GraphMouse) {
removeMouseWheelListener(mwl[i]);
}
}
addMouseListener(graphMouse);
addMouseMotionListener(graphMouse);
addMouseWheelListener(graphMouse);
}
/**
* Sets the showing Renderer to be the input Renderer. Also tells the
* Renderer to refer to this visualizationviewer as a PickedKey. (Because
* Renderers maintain a small amount of state, such as the PickedKey, it is
* important to create a separate instance for each VV instance.)
*
* @param v
*/
public void setRenderer(Renderer r) {
this.renderer = r;
r.setPickedKey(pickedState);
repaint();
}
/**
* Returns the renderer used by this instance.
*
* @return
*/
public Renderer getRenderer() {
return renderer;
}
/**
* Removes the current graph layout, and adds a new one.
*/
public void setGraphLayout(Layout layout) {
if (this.layout instanceof PickEventListener)
pickedState.removeListener((PickEventListener) this.layout);
suspend();
Dimension d = getPreferredSize();
Dimension ld = layout.getCurrentSize();
// if the layout has NOT been initialized yet, initialize it
// now to the size of the VisualizationViewer window
if (ld == null) {
layout.initialize(d);
}
ld = layout.getCurrentSize();
// set scale to show the entire graph layout
setScale((float) d.width / ld.width, (float) d.height / ld.height,
new Point2D.Float());
this.layout = layout;
layout.restart();
prerelax();
unsuspend();
if (layout instanceof PickEventListener)
pickedState.addListener((PickEventListener) layout);
this.pickSupport.setLayout(layout);
}
public void setGraph(OntologyWithClassHierarchyGraph graph) {
myGraph = graph;
}
public OntologyWithClassHierarchyGraph getGraph() {
return myGraph;
}
/**
* Returns the current graph layout.
*/
public Layout getGraphLayout() {
return layout;
}
/**
* This is the interface for adding a mouse listener. The GEL will be called
* back with mouse clicks on vertices.
*
* @param gel
*/
public void addGraphMouseListener(GraphMouseListener gel) {
addMouseListener(new SwoopMouseListenerTranslator(gel, this));
}
/**
* starts a visRunner thread without prerelaxing
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?