//// GraphViewMySqlPhp.java
// D. Thiebaut
// _ _ _ _ _
// / \ _ __ _ __ | (_) ___ __ _| |_(_) ___ _ __
// / _ \ | '_ \| '_ \| | |/ __/ _` | __| |/ _ \| '_ \
// / ___ \| |_) | |_) | | | (_| (_| | |_| | (_) | | | |
///_/ \_\ .__/| .__/|_|_|\___\__,_|\__|_|\___/|_| |_|
// |_| |_|
//
// Adapted from code by <a href="http://jheer.org">jeffrey heer</a>
// VERSIONS
// Version 17: with tooltips
// Version 16: Remove the automatic freeze after 5 sec and remove the extra
// forces that were created (wrongly)
// Version 15: Makes animation restart with force field sliders are moved
// Version 14: stops animation after 5 sec, and zoom to fit afterward
// Version 13: Added delay and SlowInSlowOutPacer
// Version 12: uses applet context to open URL in browser window
// Version 11: 3/29/09
// Supports "url" field in mySql database. Works with getdata3.php
//
// Version 10: 3/28/09
// Added many features: save image, freeze/animate button
// class to control freeze/animate
// fixed bug about hover when item is searched and screen is cleared
// fixed bug about distance not respected when cruising through graph
// Version 9: 3/27/09 added feature where database can be specified
// to php tunnel
// Version 8: 3/26/09 (later) use sqrt( # of links) for node size
// Version 7: 3/26/09 working popup: updates force field!
// Version 6: working popup, no action on slider yet
// Version 5: Starting attaching Java Popup
// Version 4: starts showing information in right pane
// Version 3: 3 panes: two text, one information
// Version 2: 3/22/09: works (crashes at times) with two panes, one at the bottom
// Version 1: 3/17/09: the application version of the applet of the same name.
package DT;
import java.awt.BorderLayout;
import java.applet.AppletContext;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.*;
import prefuse.Constants;
import prefuse.Display;
import prefuse.Visualization;
import prefuse.action.ActionList;
import prefuse.action.GroupAction;
import prefuse.action.ItemAction;
import prefuse.action.RepaintAction;
import prefuse.action.assignment.ColorAction;
import prefuse.action.assignment.DataColorAction;
import prefuse.action.assignment.DataSizeAction;
import prefuse.action.assignment.SizeAction;
import prefuse.action.filter.GraphDistanceFilter;
import prefuse.action.layout.graph.ForceDirectedLayout;
import prefuse.activity.Activity;
import prefuse.activity.SlowInSlowOutPacer;
import prefuse.controls.Control;
import prefuse.controls.ControlAdapter;
import prefuse.controls.DragControl;
import prefuse.controls.FocusControl;
import prefuse.controls.NeighborHighlightControl;
import prefuse.controls.PanControl;
import prefuse.controls.WheelZoomControl;
import prefuse.controls.ZoomControl;
import prefuse.controls.ZoomToFitControl;
import prefuse.data.Graph;
import prefuse.data.Edge;
import prefuse.data.Node;
import prefuse.data.Table;
import prefuse.data.Tuple;
import prefuse.data.event.TupleSetListener;
import prefuse.data.tuple.TupleSet;
import prefuse.render.DefaultRendererFactory;
import prefuse.render.EdgeRenderer;
import prefuse.render.LabelRenderer;
import prefuse.util.ColorLib;
import prefuse.util.FontLib;
import prefuse.util.GraphicsLib;
import prefuse.util.PrefuseLib;
import prefuse.util.collections.IntIterator;
import prefuse.util.display.DisplayLib;
import prefuse.util.force.DragForce;
import prefuse.util.force.Force;
import prefuse.util.force.ForceSimulator;
import prefuse.util.force.NBodyForce;
import prefuse.util.force.SpringForce;
import prefuse.util.ui.JPrefuseApplet;
import prefuse.util.ui.JValueSlider;
import prefuse.util.ui.UILib;
import prefuse.visual.NodeItem;
import prefuse.visual.VisualGraph;
import prefuse.visual.VisualItem;
import prefuse.visual.expression.InGroupPredicate;
/** ================================================================================
* ____ _ __ ___ __ __ ____ _
* / ___|_ __ __ _ _ __ | |_\ \ / (_) _____ _| \/ |_ _/ ___| __ _| |
* | | _| '__/ _` | '_ \| '_ \ \ / /| |/ _ \ \ /\ / / |\/| | | | \___ \ / _` | |
* | |_| | | | (_| | |_) | | | \ V / | | __/\ V V /| | | | |_| |___) | (_| | |
* \____|_| \__,_| .__/|_| |_|\_/ |_|\___| \_/\_/ |_| |_|\__, |____/ \__, |_|
* |_| |___/ |_|
* ================================================================================
*/
public class GraphViewMySqlPhp extends Display {
private static final long serialVersionUID = 1L;
private static final String encyclopedia= "encyclopedia";
private static final String graph = "graph";
private static final String nodes = "graph.nodes";
private static final String edges = "graph.edges";
private static final String nodeSize = "nodeSize";
private static final String links = "links";
private static final String IdStr = "Id";
private static final String name = "name";
private static final String info = "info";
private static final String url = "url";
private static final String visited = "visited";
private static final String directed = "directed";
private static final int Kakhi0 = ColorLib.rgb( 0xad, 0xa9, 0x6e);
private static final int Kakhi3 = ColorLib.rgb( 0xc9, 0xbe, 0x62);
private static final int DarkGold = ColorLib.rgb( 0xfb, 0xb1, 0x17);
private static final int DefaultBlue = ColorLib.rgb(200,200,255);
private static Graph theGraph;
private static Visualization theVis;
private static VisualGraph vg;
private static DefaultRendererFactory defaultRenderFact;
private static GraphDistanceFilter filter;
private static AccessMySqlThroughPhp2 mySqlTunnel;
private static boolean busyUpdatingGraph = false;
// true if program has issued a query
// and we are waiting for the result
private static int frameWidth = 1000;
private static int frameHeight = 800;
private static EncyclopediaForm2 theForm;
private static ForceSimulator fsim;
private static String databaseUsed = "encyclopedia76d";
private static boolean isDirected = true;
private static boolean normalGraph = true;
private static boolean reverseGraph = false;
private static AnimationControl animationControl;
//private static NeighborHighlightControl2 neighborHighlightControl;
private static String lastRootNodeName;
private JPrefuseApplet parentApplet = null;
private static AppletContext appletContext=null;
/* -------------------------------------------------------------------------
* main
* -------------------------------------------------------------------------
*/
public static void main(String argv[]) {
UILib.setPlatformLookAndFeel();
databaseUsed = (String)JOptionPane.showInputDialog(
null,
"Enter database name\n"
+"(e.g. encyclopedia76)",
"Select Database",
JOptionPane.QUESTION_MESSAGE );
DataFileGraphView df = new DataFileGraphView();
if ( !df.isValidDatabase(databaseUsed))
return;
isDirected = df.getBooleanParam( databaseUsed, directed );
demo( databaseUsed /* as title of jpanel */ );
}
/*
* Call this when we run as an application
*/
public static JFrame demo( String title ) {
//--- create the UI ---
GraphViewMySqlPhp graphDisplay = new GraphViewMySqlPhp();
theForm = new EncyclopediaForm2( graphDisplay, filter );
graphDisplay.setBackground(Color.white);
JFrame frame = new JFrame( title );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(1000,800));
frame.setContentPane( theForm );
frame.pack();
frame.setVisible(true);
//--- center the graph in the form
centerGraphInDisplay( 0 ); // 0 --> first node in internal table
return frame;
}
/*
* Call this when we run as an applet
*/
public static JComponent demoComponent( AppletContext ac ) { // JPrefuseApplet parent ) {
appletContext = ac;
databaseUsed = (String)JOptionPane.showInputDialog(
null,
"Enter database name\n"
+"(e.g. epfl)",
"Select Database",
JOptionPane.QUESTION_MESSAGE );
DataFileGraphView df = new DataFileGraphView();
if ( !df.isValidDatabase(databaseUsed))
return null;
isDirected = df.getBooleanParam( databaseUsed, directed );
//--- create the UI ---
GraphViewMySqlPhp graphDisplay = new GraphViewMySqlPhp();
//graphDisplay.setParentApplet( parent );
theForm = new EncyclopediaForm2( graphDisplay, filter );
graphDisplay.setBackground(Color.white);
//centerGraphInDisplay( 0 ); // 0 --> first node in internal table
return theForm;
}
/*
* displayInfoForces: display the information about forces
*/
void displayInfoForces( ForceSimulator fsim ) {
Force[] forces = fsim.getForces();
for ( int i=0; i<forces.length; i++ ) {
Force f = forces[i];
String fname = f.getClass().getName();
fname = fname.substring( fname.lastIndexOf( ".")+1);
for ( int j=0; j<f.getParameterCount(); j++ ) {
String pname = f.getParameterName( j );
System.out.println( "Force["+String.valueOf( i )+"] ="+fname +","+pname+" --> "+String.valueOf(f.getParameter(j)));
if ( fname.equals("NBodyForce" ) && pname.equals("Distance") )
System.out.println( "--Force["+String.valueOf( i )+"] = "+fname +","+pname+" --> "+String.valueOf(f.getParameter(j)));
}
}
}
private void displayGraph() {
System.out.println("--------------------------------------------------------");
System.out.println( "isDirected =" + String.valueOf( isDirected ));
System.out.println( "reverseGraph =" + String.valueOf( reverseGraph ));
System.out.println( "normalGraph =" + String.valueOf( normalGraph ));
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
int noCol = node.getColumnCount();
System.out.println(
"name:" + node.getString( name ) +
" visited:" + node.getInt( visited ) +
" IdStr:" + node.getInt( IdStr ) +
" links:" + node.getString( links ) +
" nodeSize:" + node.getInt( nodeSize ) +
" info:" + node.getString( info ) +
" url:" + node.getString( url ) );
}
System.out.println("--------------------------------------------------------");
}
/* -------------------------------------------------------------------------
* GraphViewMySqlPhp
* -------------------------------------------------------------------------
*/
public GraphViewMySqlPhp() {
super(new Visualization());
//theGraph = new Graph( true /* is directed graph */);
theGraph = createNewGraph( isDirected );
createGraphColumns();
mySqlTunnel = new AccessMySqlThroughPhp2( databaseUsed );
mySqlTunnel.setDatabase( databaseUsed );
//int resCode = addNodeToGraph( 55 ); // pick the node with Index 1 in database
//Random generator = new Random();
//while ( resCode==-1 ) {
// resCode = addNodeToGraph( generator.nextInt( 1000 ) );
//}
// create a new, empty visualization for our data
theVis = m_vis; //new Visualization();
// set the animation control. Will need to be told of the button in
// the form that controls the animation
animationControl = new AnimationControl();
animationControl.setVisualization( theVis, "layout");
// VisualGraph
vg = theVis.addGraph(graph, theGraph );
theVis.setValue( edges, null, VisualItem.INTERACTIVE, Boolean.FALSE );
// focus group
TupleSet focusGroup = theVis.getGroup(Visualization.FOCUS_ITEMS);
focusGroup.addTupleSetListener(new TupleSetListener() {
public void tupleSetChanged(TupleSet ts, Tuple[] add, Tuple[] rem)
{
theVis.cancel( "draw" );
for ( int i=0; i<rem.length; ++i )
((VisualItem)rem[i]).setFixed(false);
for ( int i=0; i<add.length; ++i ) {
((VisualItem)add[i]).setFixed(false);
((VisualItem)add[i]).setFixed(true);
}
theVis.run( "draw" );
}
});
// renderers
LabelRenderer tr = new LabelRenderer( name );
tr.setRoundedCorner(8, 8);
defaultRenderFact = new DefaultRendererFactory( tr );
EdgeRenderer edgeRenderer = new EdgeRenderer( Constants.EDGE_TYPE_LINE, Constants.EDGE_ARROW_FORWARD );
edgeRenderer.setArrowHeadSize( 6, 10 );
defaultRenderFact.add( new InGroupPredicate( edges ), edgeRenderer);
theVis.setRendererFactory( defaultRenderFact );
// -- set up the actions ----------------------------------------------
int hops = 5;
filter = new GraphDistanceFilter(graph, hops);
ActionList draw = new ActionList();
draw.add(filter);
// create a datacoloraction for the nodes that are visited
int[] palette = new int[] { DefaultBlue, DarkGold };
DataColorAction fillVisited = new DataColorAction( nodes, visited,
Constants.NUMERICAL, VisualItem.FILLCOLOR, palette );
fillVisited.add("_fixed", ColorLib.rgb(225, 170, 95) );
fillVisited.add("_highlight", ColorLib.rgb(255,200,125));
ItemAction edgeColor = new ColorAction( edges,
VisualItem.STROKECOLOR, ColorLib.gray(200) );
( (ColorAction) edgeColor ).add( "_highlight", ColorLib.rgb(255,200,125) );
// EdgeSize is an idea to make highlighted edges bigger, but arrow heads are lost
// in the process...
SizeAction edgeSize = new SizeAction( edges ); // DFT add
edgeSize.add( "_highlight", 2 ); // DFT add
// add node data size action
DataSizeAction nodeDataSizeAction = new DataSizeAction( nodes, nodeSize );
nodeDataSizeAction.setScale( Constants.LINEAR_SCALE );
//draw.add(new ColorAction(nodes, VisualItem.FILLCOLOR, ColorLib.rgb(200,200,255)));
draw.add(new ColorAction(nodes, VisualItem.STROKECOLOR, 0));
draw.add(new ColorAction(nodes, VisualItem.TEXTCOLOR, ColorLib.rgb(0,0,0)));
draw.add( edgeColor );
draw.add(new ColorAction(edges, VisualItem.FILLCOLOR, ColorLib.gray(200)));
draw.add( edgeSize ); // DFT add
// set force-simulation system
//Force[0] =NBodyForce,GravitationalConstant --> -1.0
//Force[0] =NBodyForce,Distance --> -1.0
//--Force[0] = NBodyForce,Distance --> -1.0
//Force[0] =NBodyForce,BarnesHutTheta --> 0.9
//Force[1] =DragForce,DragCoefficient --> 0.01
//Force[2] =NBodyForce,GravitationalConstant --> -32.0
//Force[2] =NBodyForce,Distance --> 400.0
//--Force[2] = NBodyForce,Distance --> 400.0
//Force[2] =NBodyForce,BarnesHutTheta --> 0.9
//Force[3] =DragForce,DragCoefficient --> 0.02
//Force[4] =SpringForce,SpringCoefficient --> 1.2940001E-4
//Force[4] =SpringForce,DefaultSpringLength --> 0.0
//Force[5] =SpringForce,SpringCoefficient --> 1.09500004E-4
//Force[5] =SpringForce,DefaultSpringLength --> 400.0
ForceDirectedLayout fdl = new ForceDirectedLayout(graph);
fsim = fdl.getForceSimulator();
Force[] forces = fsim.getForces();
forces[0].setParameter(0 , -1); // gravitational constant
forces[0].setParameter(1 , -1); // Distance
forces[0].setParameter(2, (float) 0.9 ); // Barnes Hut theta
forces[1].setParameter(0, (float) 0.01 );
forces[2].setParameter(0, (float) 1.0E-5 );
forces[2].setParameter(1, (float) 216.0 );
// Add "zoom to fit" as action
ZoomToFitAction zoomToFit = new ZoomToFitAction( graph, this );
zoomToFit.setStepTime( 100000 );
//theVis.putAction( "zoomToFit", zoomToFit );
//theVis.putAction( "zoomToFit", new ZoomToFitAction( graph, this ));
ActionList animate = new ActionList(Activity.INFINITY); // DFT add
//ActionList animate = new ActionList(5000); // DFT remove
//animate.setPacingFunction(new SlowInSlowOutPacer()); // DFT remove
animate.add(fdl);
animate.add(fillVisited);
animate.add( edgeColor );
animate.add( edgeSize ); // DFT add
animate.add(new RepaintAction());
animate.add( nodeDataSizeAction );
//animate.add( zoomToFit ); // DFT add
// finally, we register our ActionList with the Visualization.
// we can later execute our Actions by invoking a method on our
// Visualization, using the name we've chosen below.
theVis.putAction("draw", draw);
theVis.putAction("layout", animate);
// DFT remove
theVis.runAfter( "draw", "layout");
//theVis.alwaysRunAfter( "layout", "zoomToFit"); // DFT remove
// set the display, of which we are an extension
setSize(1000,800);
setForeground(Color.GRAY);
setBackground(Color.WHITE);
// main display controls
addControlListener(new FocusControl(1));
addControlListener(new DragControl());
addControlListener(new PanControl());
addControlListener(new ZoomControl());
addControlListener(new WheelZoomControl());
addControlListener(new ZoomToFitControl());
addControlListener(new NeighborHighlightControl());
// added separate highlight controller so that we can force the node that is
// clicked on become the new center of the highlight
//neighborHighlightControl = new NeighborHighlightControl2();
//addControlListener( neighborHighlightControl );
addControlListener(new HoverTooltip());
addControlListener(new NodeClickControl2( this ) );
setForeground(Color.GRAY);
setBackground(Color.WHITE);
} // end constructor GraphViewMySql()
/* -------------------------------------------------------------------------
* I N S P E C T O R S
* -------------------------------------------------------------------------
*/
public AnimationControl getAnimationControl() {
return animationControl;
}
public GraphDistanceFilter getFilter() {
return filter;
}
public AppletContext getAppletContext() {
return appletContext;
}
public String getLastRootNode() {
return lastRootNodeName;
}
public void setLastRootNode( String name ) {
lastRootNodeName = name;
}
public void setParentApplet( JPrefuseApplet parent ) {
parentApplet = parent;
}
public JPrefuseApplet getParentApplet( ) {
return parentApplet;
}
/* -------------------------------------------------------------------------
* Graph and Id-related methods
* -------------------------------------------------------------------------
*/
protected int getDbId( int rowId ) {
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
if ( node.getRow()==rowId )
return node.getInt( "Id" );
}
return -1;
}
protected int getRowId( int dbId ) {
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
if ( node.getInt( "Id" )== dbId )
return node.getRow();
}
return -1;
}
public String getDataBaseName(){
return databaseUsed;
}
public Graph createNewGraph( boolean dir ) {
isDirected = dir;
Graph graph = new Graph( isDirected /* whether the graph is directed or not */);
return graph;
}
/* -------------------------------------------------------------------------
* graphContainsDbId: returns true if graph contains given Id
* -------------------------------------------------------------------------
*/
protected boolean graphContainsDbId( int dbId ) {
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
if ( node.getInt( "Id" )== dbId )
return true;
}
return false;
}
protected Node getNodeWithDBId( int dbId ) {
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
if ( node.getInt( "Id" )== dbId )
return node;
}
return null;
}
public Graph getGraph() {
return theGraph;
}
public ForceSimulator getForceSimulator() {
return fsim;
}
public static boolean isValidDatabase( String db ) {
DataFileGraphView df = new DataFileGraphView();
return df.isValidDatabase( db );
}
public boolean setDatabase( String db ){
DataFileGraphView df = new DataFileGraphView();
if ( !df.isValidDatabase( db ) )
return false;
databaseUsed = db;
isDirected = df.getBooleanParam( databaseUsed, directed );
mySqlTunnel.setDatabase( db );
theForm.setTitle( db );
updateStatus( "database set to "+db);
return true;
}
/* -------------------------------------------------------------------------
* isBusy: returns true if we are in the middle of issuing a query
* so that we won't instantiate one too soon.
* -------------------------------------------------------------------------
*/
public boolean isBusy() {
return busyUpdatingGraph;
}
public void setBusy( boolean b ) {
busyUpdatingGraph = b;
}
/* -------------------------------------------------------------------------
* noLinks: returns the number of links
* -------------------------------------------------------------------------
*/
protected int numberOfLinks( String links ) {
return links.split( "," ).length;
}
/* -------------------------------------------------------------------------
* ANIMATION CONTROLS
* -------------------------------------------------------------------------
*/
public void animate() {
animationControl.animate();
}
public void freeze() {
animationControl.freeze();
}
/* -------------------------------------------------------------------------
* centerGraphInDisplay
* -------------------------------------------------------------------------
*/
public static void centerGraphInDisplay( int centerNodeId ) {
TupleSet focusGroup = theVis.getGroup( Visualization.FOCUS_ITEMS );
NodeItem focus = (NodeItem)vg.getNode( centerNodeId );
PrefuseLib.setX( focus, null, frameWidth/2 );
PrefuseLib.setY( focus, null, frameHeight/2 );
focusGroup.setTuple( focus);
}
/* -------------------------------------------------------------------------
* removeNodeFromGraph: removes the node from the graph
* This shouldn't really be used, as we don't have a good way to deal with
* the removal of a node that would break the graph into two graphs.
* -------------------------------------------------------------------------
*/
/*
public void removeNodeFromGraph( String centerId ) {
removeNodeFromGraph( Integer.valueOf( centerId.trim() ));
}
*/
public void removeNode(int node) {
removeNodePrivate(node);
theVis.run("repaint");
}
private void removeNodePrivate(int node) {
theGraph.removeNode(node);
}
/* -------------------------------------------------------------------------
* clearGraph: resets the graph
* (Currently not used)
* -------------------------------------------------------------------------
*/
public void clearGraph( ) {
TupleSet focusGroup = theVis.getGroup(Visualization.FOCUS_ITEMS);
theVis.cancel( "draw" );
theVis.cancel( "layout" );
focusGroup.clear();
theGraph.clear();
/*
for ( Iterator<Node> nodeItem = theGraph.nodes(); nodeItem.hasNext(); ) {
Node node = nodeItem.next();
theGraph.removeNode( node );
}
for ( Iterator<Edge> edgeItem = theGraph.edges(); edgeItem.hasNext(); ) {
Edge edge = edgeItem.next();
theGraph.removeEdge( edge );
}
*/
theVis.run( "draw" );
theVis.run( "layout" );
}
/* -------------------------------------------------------------------------
* removeNodeFromGraph: remove node from graph
* Don't use: buggy...
* -------------------------------------------------------------------------
*/
/*
public void removeNodeFromGraph( int dbId ) {
int row = getRowId( dbId );
theVis.cancel( "draw" );
for ( Iterator<Edge> edgeItem = theGraph.edges(); edgeItem.hasNext(); ) {
Edge e = edgeItem.next();
Node sourceNode = e.getSourceNode();
if ( sourceNode.getRow() == row ) {
theGraph.removeEdge( e );
}
else {
Node targetNode = e.getTargetNode();
if ( targetNode.getRow() == row ) {
theGraph.removeEdge( e );
}
}
}
//System.out.println( "removing Node Id" + String.valueOf( dbId ) + " "+ node.getString( "name") );
theGraph.removeNode( row );
theVis.run( "draw" );
}
*/
/*
private static void displayTable( Table myTable, String caption ) {
System.out.println( "-------------------------------------------");
System.out.println( "--" + caption );
System.out.println( "-------------------------------------------");
for ( int i=0; i< myTable.getRowCount(); i++ ) {
int Id = myTable.getInt( i, 0 );
String name = myTable.getString( i, 1 );
String links = myTable.getString( i, 2 );
String info = myTable.getString( i, 3 );
System.out.println( "Table["+String.valueOf(i)+"] "
+name + "("+String.valueOf(Id)+ ") - "+ links +": "+info);
try {
System.out.println( " " + myTable.getString( i, 4 ) );
}
catch (IndexOutOfBoundsException e) {
// do nothing
}
}
System.out.println( "-------------------------------------------");
}
*/
protected void displayTable2( Table myTable ) {
for ( int i=0; i< myTable.getRowCount(); i++ ) {
int Id = myTable.getInt( i, 0 );
String name = myTable.getString( i, 1 );
String links = myTable.getString( i, 2 );
String info = myTable.getString( i, 3 );
System.out.println( "Table["+String.valueOf(i)+"] "
+name + "("+String.valueOf(Id)+ ") - "+ links);
}
}
/* -------------------------------------------------------------------------
* addNodeToGraph: adds a node to the graph. If the graph is empty
* a node is added to it.
* -------------------------------------------------------------------------
*/
public int addNodeToGraph( String centerId ) {
return addNodeToGraphUsingQuery( Integer.valueOf( centerId ), "", true );
}
public int addNodeToGraph( int centerId ) {
return addNodeToGraphUsingQuery( centerId, "", true );
}
public int addNodeToGraphByName( String searchName ) {
return addNodeToGraphUsingQuery( 0, searchName, false );
}
public int addNodeToGraphUsingQuery( int centerId, String centerName, boolean searchById ) {
Table dataTable = null;
int newNodeRow=0;
// returns table
// Id Name Links Info
// 3 toto 2,3,4 some info about node <-- the root of the graph
// 2 tata 3,5
//
try {
if ( searchById ) {
dataTable = mySqlTunnel.getData( centerId );
//System.out.println( "calling getData("+ String.valueOf( centerId )+")");
}
else {
//System.out.println( "calling getDataByName("+ centerName +")");
dataTable = mySqlTunnel.getDataByName( centerName );
}
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
if ( dataTable.getRowCount()==0 ) {
updateStatus( "No new titles found");
return -1;
}
//displayTable( dataTable, "table" );
// Add the nodes first
// First create a table assigning the database Id to the graph row
for (int i = 0; i < dataTable.getRowCount(); i++){
int Id = dataTable.getInt( i, 0 );
if ( i==0 ) {
setLastRootNode( dataTable.getString( 0, 1) );
}
if ( graphContainsDbId( Id ) ) {
////System.out.println( "Id already in IdMap" );
if (i==0) {
Node clickedNode = getNodeWithDBId( Id );
clickedNode.set( visited, 1 );
}
continue;
}
Node n = theGraph.addNode();
n.set( name, dataTable.get( i, 1 ) );
n.set( links, dataTable.get( i, 2 ) );
n.set( IdStr, Id );
int noLinks = numberOfLinks( dataTable.getString( i, 2 ) );
////System.out.println( "adding noLinks = " + String.valueOf( noLinks ) );
n.set( nodeSize, Math.round( 1+ Math.sqrt( noLinks ) ) );
n.set( info, dataTable.getString( i, 3 ));
n.set( url, dataTable.getString( i, 4 ));
if ( i==0 )
n.set( visited, 1); //first node in the table is visited
else
n.set( visited, 0); // other nodes aren't
int row = n.getRow();
if ( i==0 ) {
newNodeRow = row;
}
}
// add the edges next
for (int i = 0; i< dataTable.getRowCount(); i++ ) {
int sourceId = dataTable.getInt( i, 0 );
int sourceRow = getRowId( sourceId );
String IdList = dataTable.get( i, 2 ).toString();
String[] individualIds = IdList.split( "," );
for(int j = 0; j < individualIds.length; j++) {
int destId = Integer.parseInt( individualIds[j].trim() );
if ( graphContainsDbId( destId ) ) {
int destRow = getRowId( destId );
if ( normalGraph & theGraph.getEdge( sourceRow, destRow ) == -1 ) {
theGraph.addEdge( sourceRow, destRow );
}
if ( reverseGraph & theGraph.getEdge( destRow, sourceRow ) == -1 ) {
theGraph.addEdge( destRow, sourceRow );
}
}
}
}
// close up the graph so all edges incident to the new node are added
closeUpGraph();
//displayGraph();
return newNodeRow;
}
/* -------------------------------------------------------------------------
* closeUpGraph: once a node is added to the graph, we pass over all the nodes
* again and add edges that were not added before because some nodes were not
* on the graph yet.
* -------------------------------------------------------------------------
*/
public void closeUpGraph( ) {
// look at all the nodes of the current graph
for ( int i=0; i < theGraph.getNodeCount(); i++) {
// get Node i
Node n = theGraph.getNode( i );
int sourceId = n.getInt( IdStr );
int sourceRow = getRowId( sourceId );
// get its list of nodes to which it is linked
String IdList = n.getString( links );
String[] individualIds = IdList.split( "," );
// go through each linked node, and if an edge does not exist to that node
// add it.
for ( int j=0; j<individualIds.length; j++ ) {
int destId = Integer.parseInt( individualIds[j].trim() );
if ( graphContainsDbId( destId ) ) {
int destRow = getRowId( destId );
//if ( theGraph.getEdge( sourceRow, destRow ) == -1 ) {
// theGraph.addEdge( sourceRow, destRow );
//}
if ( normalGraph & theGraph.getEdge( sourceRow, destRow ) == -1 ) {
theGraph.addEdge( sourceRow, destRow );
}
if ( reverseGraph & theGraph.getEdge( destRow, sourceRow ) == -1 ) {
theGraph.addEdge( destRow, sourceRow );
}
}
}
}
}
/*
* redoLastSearch: used when we're switching databases.
*/
public void redoLastSearch() {
setBusy( true );
getVisualization().cancel( "draw" );
getAnimationControl().cancel( "layout" );
addNodeToGraph( lastRootNodeName );
getFilter().run();
getVisualization().run( "draw" );
getAnimationControl().run( "layout" );
setBusy( false );
}
/* -------------------------------------------------------------------------
* initUI
* -------------------------------------------------------------------------
*/
private static void initUI() {
}
/* -------------------------------------------------------------------------
* createGraphColumns
* -------------------------------------------------------------------------
*/
private void createGraphColumns() {
theGraph.addColumn( name, String.class );
theGraph.addColumn( links, String.class );
theGraph.addColumn( IdStr, int.class );
theGraph.addColumn( info, String.class );
theGraph.addColumn( url, String.class );
theGraph.addColumn( nodeSize, int.class );
theGraph.addColumn( visited, int.class );
}
/* -------------------------------------------------------------------------
* clearDisplayAddNewNodeByName
* -------------------------------------------------------------------------
*/
public void clearDisplayAddNewNodeByName( String title ) {
setBusy( true );
TupleSet focusGroup = theVis.getGroup(Visualization.FOCUS_ITEMS);
focusGroup.clear();
//theVis.cancel( "layout");
theVis.cancel( "draw" );
theGraph.clear();
createGraphColumns();
updateStatus( "Adding title " + title );
int nodeId = addNodeToGraphByName( title );
if ( nodeId == -1 ) {
setBusy( false );
animationControl.cancel("layout"); //theVis.cancel( "layout" );
updateStatus( "WARNING: Page title starting with \"" + title + "\" could not be found." );
}
else {
updateStatus( "New graph created around Page " + title );
centerGraphInDisplay( nodeId );
animationControl.run( "layout"); // theVis.run( "layout" );
theVis.run( "draw" );
}
//theVis.run( "draw" );
setBusy( false );
}
/* -------------------------------------------------------------------------
* clearDisplayAddNewNodeByName
* -------------------------------------------------------------------------
*/
public void updateStatus( String msg ) {
try {
theForm.updateStatus( msg );
}
catch ( Exception e) {
return;
}
}
void updateProperties( String msg ) {
theForm.updateProperties( msg );
}
/**
* Private "zoom to fit" action's implementation
* Note: copy-pasted from Prefuse demos
*/
private class ZoomToFitAction extends GroupAction {
private Display display;
//GroupAction(Visualization vis, long duration, long stepTime)
public ZoomToFitAction(String graphGroup, Display display) {
super(graphGroup);
this.display = display;
}
public void run(double frac) {
Visualization vis = display.getVisualization();
Rectangle2D bounds = vis.getBounds(Visualization.ALL_ITEMS);
GraphicsLib.expand(bounds, 50 + (int)(1/display.getScale()));
DisplayLib.fitViewToBounds(display, bounds, 500);
}
}
// end of GraphViewMySqlPhp Class
}
/** ================================================================================
* AnimationControl
* _ _ _ _ ___ _ _
* /_\ _ _ (_)_ __ __ _| |_(_)___ _ _ / __|___ _ _| |_ _ _ ___| |
* / _ \| ' \| | ' \/ _` | _| / _ \ ' \ (__/ _ \ ' \ _| '_/ _ \ |
* /_/ \_\_||_|_|_|_|_\__,_|\__|_\___/_||_\___\___/_||_\__|_| \___/_|
* =================================================================================
*/
class AnimationControl {
private JButton button = null;
private Visualization theVis = null;
boolean animationSuspended = true;
String actionString = "";
AnimationControl() {
}
AnimationControl( JButton button, Visualization theVis, String actionString ) {
this.button = button;
this.theVis = theVis;
this.actionString = actionString;
}
public void setButton( JButton button ) {
this.button = button;
}
public void setVisualization( Visualization theVis, String action ) {
this.theVis = theVis;
actionString = action;
}
public void run( String action ) {
animate();
}
public void cancel( String action ) {
freeze();
}
public void animate() {
if ( button!=null) button.setText("Freeze");
if (theVis !=null ) theVis.run( actionString );
animationSuspended = false;
}
public void freeze() {
if ( button != null ) button.setText("Animate");
if ( theVis != null ) theVis.cancel( actionString );
animationSuspended = true;
}
public void toggle() {
if ( animationSuspended )
animate();
else
freeze();
}
public boolean animationIsOn() {
return !animationSuspended;
}
public boolean animationIsOff() {
return !animationIsOn();
}
}
/* ===========================================================================
* EncyclopediaForm1: The main form
* ____ _ _ ___ _____
* / ___| | | |_ _| | ___|__ _ __ _ __ ___
* | | _| | | || | | |_ / _ \| '__| '_ ` _ \
* | |_| | |_| || | | _| (_) | | | | | | | |
* \____|\___/|___| |_| \___/|_| |_| |_| |_|
* ===========================================================================
*/
class EncyclopediaForm2 extends JPanel {
private static final long serialVersionUID = 1L;
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
// Generated using JFormDesigner non-commercial license
private JLabel label1;
private JTextField textField1;
private JPanel hSpacer1;
private JButton button1;
private JButton button2;
private JButton button3;
private JSpinner spinner1;
private JLabel label2;
private JPanel panel2;
private JPanel hSpacer2;
private JPopupMenu popupMenu1;
private JPanel menuItem1;
//--- visualization specific variables
Display display;
GraphDistanceFilter filter;
private GraphViewMySqlPhp graphView;
private Visualization theVis;
private ForceSimulator fsim;
/* -------------------------------------------------------------------------
* Constructor
* -------------------------------------------------------------------------
*/
public EncyclopediaForm2(GraphViewMySqlPhp graphDisplay, GraphDistanceFilter fltr ) {
filter = fltr;
graphView = graphDisplay;
theVis = graphView.getVisualization();
fsim = graphView.getForceSimulator();
//setBorder(BorderFactory.createTitledBorder( "Encyclopedia 1976 (Application)"));
setTitle( graphView.getDataBaseName() );
initComponents( display, filter );
}
/* -------------------------------------------------------------------------
* udpateStatus: prints a message in the bottom window
* -------------------------------------------------------------------------
*/
public void setTitle( String msg ){
setBorder(BorderFactory.createTitledBorder( msg + " (Application)"));
}
/* -------------------------------------------------------------------------
* udpateStatus: prints a message in the bottom window
* -------------------------------------------------------------------------
*/
public void updateStatus( String msg ) {
//textArea2.append( msg + "\n" );
System.out.println( msg );
}
/* -------------------------------------------------------------------------
* updateProperties: prints a message in the right hand-side window
* -------------------------------------------------------------------------
*/
public void updateProperties( String msg ) {
//textArea1.setText( msg );
System.out.println( msg );
}
/* -------------------------------------------------------------------------
* button1MouseClicked
* -------------------------------------------------------------------------
*/
private void button1MouseClicked(MouseEvent e) {
String query = textField1.getText().trim();
graphView.clearDisplayAddNewNodeByName(query);
}
/* -------------------------------------------------------------------------
* button2MouseClicked
* -------------------------------------------------------------------------
*/
private void button2MouseClicked(MouseEvent e) {
// TODO add your code here
}
/* -------------------------------------------------------------------------
* button2MouseClicked
* -------------------------------------------------------------------------
*/
private void button3MouseClicked(MouseEvent e) {
AnimationControl animationControl = graphView.getAnimationControl();
boolean frozen = animationControl.animationIsOff();
if ( frozen )
animationControl.animate();
else
animationControl.freeze();
}
/* -------------------------------------------------------------------------
* spinner1StateChanged
* -------------------------------------------------------------------------
*/
private void spinner1StateChanged(ChangeEvent e) {
filter.setDistance( (Integer) spinner1.getValue() );
theVis.run("draw");
}
/* -------------------------------------------------------------------------
* textField1KeyTyped
* -------------------------------------------------------------------------
*/
private void textField1KeyTyped(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
String query = textField1.getText().trim();
System.out.println("ENTER typed: " + query );
graphView.clearDisplayAddNewNodeByName(query);
}
}
private void textField1KeyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
String query = textField1.getText().trim();
System.out.println("ENTER pressed: " + query );
graphView.clearDisplayAddNewNodeByName(query);
}
}
/* -------------------------------------------------------------------------
* initComponents
* -------------------------------------------------------------------------
*/
private void initComponents( Display display, GraphDistanceFilter filter ) {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
// Generated using JFormDesigner non-commercial license
label1 = new JLabel();
textField1 = new JTextField();
button1 = new JButton();
hSpacer1 = new JPanel(null);
spinner1 = new JSpinner();
label2 = new JLabel();
panel2 = new JPanel();
hSpacer2 = new JPanel(null);
button2 = new JButton();
button3 = new JButton();
popupMenu1 = new JPopupMenu();
menuItem1 = new JPanel();
CellConstraints cc = new CellConstraints();
//======== this ========
setLayout(new FormLayout(
"default, $lcgap, [70dlu,min], 2*($lcgap, default), $lcgap, [36dlu,default], $lcgap, default:grow, 3*($lcgap, default)",
"default, $lgap, fill:default:grow"));
//---- label1 ----
label1.setText("Page Title");
add(label1, cc.xy(1, 1));
add(textField1, cc.xy(3, 1));
//---- textField1 ----
//textField1.setText( "" );
textField1.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
textField1KeyTyped(e);
}
@Override
public void keyPressed(KeyEvent e) {
textField1KeyPressed(e);
}
});
//---- button1 ----
button1.setText("Search");
button1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
button1MouseClicked(e);
}
});
button1.addFocusListener( new FocusListener() {
public void focusGained(FocusEvent e) {
button1.doClick();
}
public void focusLost(FocusEvent e) {
}
});
add(button1, cc.xy(5, 1));
add(hSpacer1, cc.xy(7, 1));
//---- spinner1 ----
spinner1.setModel(new SpinnerNumberModel(6, 1, null, 1));
spinner1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
spinner1StateChanged(e);
}
});
add(spinner1, cc.xy(9, 1));
//---- label2 ----
label2.setText("Link Length");
add(label2, cc.xy(11, 1));
add(hSpacer2, cc.xy(13, 1));
//---- button2 ----
button2.setText("Settings");
button2.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
popupMenu1.show(e.getComponent(),
e.getX(), e.getY());
//button2MouseClicked(e);
}
});
button2.addFocusListener( new FocusListener() {
public void focusGained(FocusEvent e) {
button2.doClick();
}
public void focusLost(FocusEvent e) {
}
});
button2.setComponentPopupMenu(popupMenu1);
add(button2, cc.xy(17, 1));
//---- button3 ----
button3.setText("Freeze");
button3.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
button3MouseClicked(e);
}
});
button1.addFocusListener( new FocusListener() {
public void focusGained(FocusEvent e) {
button1.doClick();
}
public void focusLost(FocusEvent e) {
}
});
graphView.getAnimationControl().setButton( button3 );
add(button3, cc.xy(15, 1));
//======== panel2 ========
panel2.setLayout(new FlowLayout());
//======== popupMenu1 ========
menuItem1.setLayout(new BoxLayout(menuItem1, BoxLayout.Y_AXIS));
menuItem1.add( new JForcePanel2( popupMenu1, fsim, graphView ) );
popupMenu1.add(menuItem1);
//======== panel2 ========
panel2.add( graphView );
panel2.setBackground(new Color(255, 153, 0));
panel2.setLayout(new BoxLayout(panel2, BoxLayout.PAGE_AXIS));
panel2.setSize( 600, 600);
add(panel2, cc.xywh(1, 3, 17, 1));
//==========SET SIZE========
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - End of variables declaration //GEN-END:variables
}
/** ================================================================================
* _ _ _ _ _ ____ _ _ ____
* | \ | | __ _(_) |__ | |__ ___ _ __ / ___|___ _ __ | |_ _ __ ___ | |___ \
* | \| |/ _` | | '_ \| '_ \ / _ \| '__| | / _ \| '_ \| __| '__/ _ \| | __) |
* | |\ | (_| | | |_) | | | | (_) | | | |__| (_) | | | | |_| | | (_) | |/ __/
* |_| \_|\__, |_|_.__/|_| |_|\___/|_| \____\___/|_| |_|\__|_| \___/|_|_____|
* |___/
* ================================================================================
*/
class NeighborHighlightControl2 extends NeighborHighlightControl {
public void makeItemNewCenter( VisualItem item ) {
if ( item instanceof NodeItem )
setNeighborHighlight( (NodeItem) item, true );
}
}
/** ================================================================================
* _ _ _ ____ _ _ _ ____ _ _
* | \ | | ___ __| | ___ / ___| (_) ___| | __/ ___|___ _ __ | |_ _ __ ___ | |
* | \| |/ _ \ / _` |/ _ \ | | | |/ __| |/ / | / _ \| '_ \| __| '__/ _ \| |
* | |\ | (_) | (_| | __/ |___| | | (__| <| |__| (_) | | | | |_| | | (_) | |
* |_| \_|\___/ \__,_|\___|\____|_|_|\___|_|\_\\____\___/|_| |_|\__|_| \___/|_|
*
* Interactive control that creates a new graph when a node
* is clicked
* ================================================================================
*/
class NodeClickControl2 extends ControlAdapter {
//private VisualItem activeItem;
protected Point2D down = new Point2D.Double();
protected Point2D temp = new Point2D.Double();
//private DebugClass log;
private GraphViewMySqlPhp graphView;
/* -------------------------------------------------------------------------
* Constructor
* -------------------------------------------------------------------------
*/
public NodeClickControl2() {
}
/* -------------------------------------------------------------------------
* Constructor: NodeClickControl
* -------------------------------------------------------------------------
*/
public NodeClickControl2( GraphViewMySqlPhp gView ) {
graphView = gView;
//log = gView.getLog();
}
/* -------------------------------------------------------------------------
* itemEntered
*/
public void itemEntered(VisualItem item, MouseEvent e) {
}
/* -------------------------------------------------------------------------
* if node is clicked, build a new graph
* -------------------------------------------------------------------------
*/
public void itemClicked( VisualItem item, MouseEvent e ) {
// don't do anything if we're busy querying...
if ( graphView.isBusy() )
return;
if ( SwingUtilities.isLeftMouseButton(e) ) {
graphView.setBusy( true );
graphView.getVisualization().cancel( "draw" );
graphView.getAnimationControl().cancel( "layout" );
graphView.addNodeToGraph( item.getString( "Id" ) );
graphView.getFilter().run();
graphView.getVisualization().run( "draw" );
graphView.getAnimationControl().run( "layout" );
//graphView.getHighlightController().makeItemNewCenter( item );
graphView.setBusy( false );
}
else if (SwingUtilities.isRightMouseButton( e ) ) {
// otherwise add node to graph
Graph g = graphView.getGraph();
String nodeId = item.getString( "Id" ).trim();
String toDisplay = "Node " + nodeId + "\n";
int rowId = graphView.getRowId( Integer.parseInt( nodeId ) );
//System.out.println( "accesing Node " + nodeId
// + " -- " + String.valueOf( rowId ));
Node n = g.getNode( rowId );
toDisplay = toDisplay + n.get( "info" );
toDisplay = toDisplay.replace( ", ", "\n" );
toDisplay = toDisplay + "\n" + n.get( "url" );
graphView.updateProperties( toDisplay );
if ( graphView.getAppletContext()==null )
return;
// open url in new browser window
URL theUrl;
try {
theUrl = new URL( (String) n.get( "url" ) );
} catch (MalformedURLException e1) {
e1.printStackTrace();
graphView.updateStatus( "malformed URL expression when opening not doc");
return;
}
try {
graphView.getAppletContext().showDocument( theUrl, "geoframe" );
graphView.updateStatus( "Opened document " + theUrl.toString() + " in geoframe");
} catch (Exception e1) {
graphView.updateStatus( "could not open url in geoframe");
}
/*
if ( graphView.getParentApplet() != null ) {
//graphView.getParentApplet().fireUrlInBrowser( n.get( "url" ) );
graphView.getParentApplet().getAppletContext().showDocument( theUrl, "docframe" );
graphView.updateStatus( "opening url in docframe page");
}
else
graphView.updateStatus( "parent is null: cannot open browser");
*/
}
}
} // end of NodeClickControl2
/** ================================================================================
* _ _____ ____ _ ____
* | | ___|__ _ __ ___ ___| _ \ __ _ _ __ ___| |___ \
* _ | | |_ / _ \| '__/ __/ _ \ |_) / _` | '_ \ / _ \ | __) |
* | |_| | _| (_) | | | (_| __/ __/ (_| | | | | __/ |/ __/
* \___/|_| \___/|_| \___\___|_| \__,_|_| |_|\___|_|_____|
* =================================================================================
*/
class JForcePanel2 extends JPanel {
/**
*
*/
private static final long serialVersionUID = -6486631015288069409L;
private ForcePanelChangeListener lstnr = new ForcePanelChangeListener();
private ForceSimulator fsim;
private static GraphViewMySqlPhp graphView;
private JPopupMenu parent;
/**
* Create a new JForcePanel
* @param fsim the ForceSimulator to configure
*/
public JForcePanel2( JPopupMenu parent, ForceSimulator fsim, GraphViewMySqlPhp graphDisplay ) {
this.parent = parent;
this.fsim = fsim;
this.graphView = graphDisplay;
this.setBackground(Color.WHITE);
initUI();
}
/*
* textField1KeyPressed: triggered when user has entered a new database in the
* text area of the settings
*/
private void textField1KeyPressed(KeyEvent e) {
int key = e.getKeyCode();
JTextField textField1 = (JTextField) e.getComponent();
if (key == KeyEvent.VK_ENTER) {
String database = textField1.getText().trim();
//System.out.println("ENTER pressed: " + database );
if ( graphView.setDatabase(database) ) {
graphView.clearGraph();
graphView.getAnimationControl().freeze();
}
else
textField1.setText( "invalid database" );
parent.setVisible( false );
}
}
private void b1MouseClicked( MouseEvent e ){
System.out.println( "Saving image to file");
SaveDisplayDialog fileDialog = new SaveDisplayDialog();
String imageFileName = fileDialog.saveFile(new Frame(), "Save graph...", ".\\", "*.png");
System.out.println( "image file =" + imageFileName );
if ( imageFileName.equals( "" ))
return;
try {
graphView.saveImage( new FileOutputStream( imageFileName ), "png", 1.0 );
} catch (FileNotFoundException e1) {
e1.printStackTrace();
System.out.println( "Could not save to file" );
}
}
/**
* Initialize the UI.
*/
private void initUI() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Force[] forces = fsim.getForces();
for ( int i=0; i<forces.length; i++ ) {
Force f = forces[i];
String name = f.getClass().getName();
name = name.substring(name.lastIndexOf(".")+1);
if ( !name.startsWith("SpringForce") ) continue;
Box v = new Box(BoxLayout.Y_AXIS);
for ( int j=0; j<f.getParameterCount(); j++ ) {
JValueSlider field = createField(f,j);
field.addChangeListener(lstnr);
v.add(field);
}
v.setBorder(BorderFactory.createTitledBorder(name));
this.add(v);
}
// set up last box of the series for the database name
{
Box v = new Box( BoxLayout.X_AXIS);
JLabel label1 = new JLabel();
JTextField textField1 = new JTextField();
label1.setText("Database");
v.add(label1);
textField1.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
textField1KeyPressed(e);
}
});
textField1.setText( graphView.getDataBaseName() );
v.add(textField1);
this.add( v );
}
// set up button to take picture of display
{
Box v = new Box( BoxLayout.X_AXIS);
JLabel label1 = new JLabel();
label1.setText( "Save image (.PNG)");
v.add( label1 );
final JButton b1 = new JButton();
b1.setText( "Save" );
v.add(b1);
b1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
b1MouseClicked(e);
}
});
b1.addFocusListener( new FocusListener() {
public void focusGained(FocusEvent e) {
b1.doClick();
}
public void focusLost(FocusEvent e) {
}
});
JPanel hspacer = new JPanel( null );
v.add( hspacer );
this.add(v);
}
}
/**
* Create an entry for configuring a single parameter.
*/
private static JValueSlider createField(Force f, int param) {
double value = f.getParameter(param);
double min = f.getMinValue(param);
double max = f.getMaxValue(param)*2;
String name = f.getParameterName(param);
JValueSlider s = new JValueSlider(name,min,max,value);
s.setBackground(Color.WHITE);
s.putClientProperty("force", f);
s.putClientProperty("param", new Integer(param));
s.setPreferredSize(new Dimension(300,30));
s.setMaximumSize(new Dimension(300,30));
return s;
}
/**
* Change listener that updates paramters in response to interaction.
*/
private class ForcePanelChangeListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JValueSlider s = (JValueSlider)e.getSource();
float val = s.getValue().floatValue();
Force f = (Force)s.getClientProperty("force");
Integer p = (Integer)s.getClientProperty("param");
f.setParameter(p.intValue(), val);
graphView.animate(); // latest change DFT
graphView.getVisualization().run( "draw" );
//graphView.displayInfoForces( fsim );
}
} // end of inner class ForcePanelChangeListener
/**
* Create and displays a new window showing a configuration panel
* for the given ForceSimulator.
* @param fsim the force simulator
* @return a JFrame instance containing a configuration interface
* for the force simulator
*/
} // end of class JForcePanel
/*
* _____ _ _ ____ _ _
*| ___(_) | ___| _ \(_) __ _| | ___ __ _
*| |_ | | |/ _ \ | | | |/ _` | |/ _ \ / _` |
*| _| | | | __/ |_| | | (_| | | (_) | (_| |
*|_| |_|_|\___|____/|_|\__,_|_|\___/ \__, |
* |___/
*/
class SaveDisplayDialog {
@SuppressWarnings("deprecation")
public String saveFile
(Frame f, String title, String defDir, String fileType) {
FileDialog fd = new FileDialog(f, title, FileDialog.SAVE);
fd.setFile(fileType);
fd.setDirectory(defDir);
fd.setLocation(50, 50);
fd.show();
// return fd.getFile();
return fd.getDirectory() + System.getProperty("file.separator") + fd.getFile();
}
} // end of class SaveDisplayDialog
/*
*
* _____ _ _____ _
* |_ _|__ ___ | |_ _(_)_ __
* | |/ _ \ / _ \| | | | | | '_ \
* | | (_) | (_) | | | | | | |_) |
* |_|\___/ \___/|_| |_| |_| .__/
* |_|
* from http://goosebumps4all.net/34all/bb/search.php?
* action=results&sid=25c9ef85cd43f7c268cefc09da2eac10
*/
abstract class PrefuseTooltip {
protected javax.swing.JPanel popup;
protected int startDelay, stopDelay;
protected javax.swing.Timer startShowingTimer, stopShowingTimer;
protected javax.swing.JComponent owner;
protected boolean isSticky;
public PrefuseTooltip(javax.swing.JComponent owner) {
this(owner, 1000, 1000);
}
public PrefuseTooltip(javax.swing.JComponent owner, int startDelay, int stopDelay) {
this.owner = owner;
this.startDelay = startDelay;
this.stopDelay = stopDelay;
this.isSticky = false;
startShowingTimer = new javax.swing.Timer(startDelay, new ShowTimerAction(true));
stopShowingTimer = new javax.swing.Timer(stopDelay, new ShowTimerAction(false));
startShowingTimer.setRepeats(false);
stopShowingTimer.setRepeats(false);
}
public void startShowing(int x, int y) {
java.awt.Component contents = getContents();
contents.addMouseListener(new PrefuseTooltipListener());
popup = new javax.swing.JPanel(new java.awt.BorderLayout(), true);
popup.setVisible(false);
popup.setLocation(x, y);
popup.setSize(contents.getPreferredSize());
popup.add(contents, java.awt.BorderLayout.CENTER);
owner.add(popup);
startShowingTimer.start();
}
public void stopShowing() {
if(PrefuseTooltip.this.popup.isVisible() && !isSticky) {
stopShowingTimer.start();
} else {
startShowingTimer.stop();
}
}
public void startShowingImmediately() {
stopShowingTimer.stop();
if(!PrefuseTooltip.this.popup.isVisible()) {
startShowingTimer.stop();
bringToFront();
popup.setVisible(true);
}
}
public void stopShowingImmediately() {
startShowingTimer.stop();
if(PrefuseTooltip.this.popup.isVisible() && !isSticky) {
stopShowingTimer.stop();
popup.setVisible(false);
}
}
public void setSticky(boolean isSticky) {
this.isSticky = isSticky;
}
public boolean isSticky() { return isSticky; }
public void bringToFront() {
popup.getParent().setComponentZOrder(popup, 0);
}
protected class ShowTimerAction implements java.awt.event.ActionListener
{
protected boolean showTimer;
protected ShowTimerAction(boolean showTimer) {
this.showTimer = showTimer;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
if(showTimer) {
PrefuseTooltip.this.startShowingImmediately();
} else {
PrefuseTooltip.this.stopShowingImmediately();
}
}
}
protected class PrefuseTooltipListener extends java.awt.event.MouseAdapter {
public void mouseEntered(MouseEvent e) {
stopShowingTimer.stop();
}
public void mouseExited(MouseEvent e) {
if(((java.awt.Component)e.getSource()).getMousePosition() != null) {
// don't stop showing if we are still inside the contents.
// this is to fix the "feature" where mouseExited is fired when
// the cursor is moved over a child component of contents. eg,
// when the cursor is moved onto a JButton that is inside a
// JPanel contents box, etc.
return;
}
PrefuseTooltip.this.stopShowing();
}
}
// override this method when you implement a PrefuseTooltip
abstract protected java.awt.Component getContents();
}
class HoverTooltip extends ControlAdapter {
PrefuseTooltip activeTooltip;
public void itemExited(VisualItem item, MouseEvent e) {
if(activeTooltip != null) {
activeTooltip.stopShowing();
}
}
public void itemEntered(VisualItem item, MouseEvent e) {
if(item instanceof Node) {
showNodeTooltip(item, e);
} else if(item instanceof Edge) {
showEdgeTooltip(item, e);
}
}
public void itemPressed(VisualItem item, java.awt.event.MouseEvent e) {
if(activeTooltip != null) {
activeTooltip.stopShowingImmediately();
}
}
public void itemReleased(VisualItem item, java.awt.event.MouseEvent e) {
if(item instanceof Node) {
showNodeTooltip(item, e);
} else if(item instanceof Edge) {
showEdgeTooltip(item, e);
}
}
protected void showNodeTooltip(VisualItem item, java.awt.event.MouseEvent e) {
Visualization v = item.getVisualization();
showTooltip(new GraphViewNodeTooltip(
(Display)e.getSource(),
((prefuse.data.Node)v.getSourceTuple(item)).getString("name"),
((prefuse.data.Node)v.getSourceTuple(item)).getString("info")),
item,
e);
}
protected void showEdgeTooltip(VisualItem item, java.awt.event.MouseEvent e) {
/*
Visualization v = item.getVisualization();
Edge edge = (prefuse.data.Edge)v.getSourceTuple(item);
String connector;
if(edge.isDirected()) {
connector = " -> ";
} else {
connector = " - ";
}
showTooltip(new InterlinkenEdgeTooltip(
(Display)e.getSource(),
edge.getSourceNode().getString("name") + connector + edge.getTargetNode().getString("name")),
item,
e);
*/
}
protected void showTooltip(PrefuseTooltip ptt, VisualItem item, java.awt.event.MouseEvent e) {
if(activeTooltip != null) {
activeTooltip.stopShowingImmediately();
}
activeTooltip = ptt;
activeTooltip.startShowing(e.getX(), e.getY());
}
}
class GraphViewNodeTooltip extends PrefuseTooltip {
protected javax.swing.JLabel nameLabel;
protected javax.swing.JLabel infoLabel;
protected javax.swing.JPanel contentsPanel;
protected String info;
GraphViewNodeTooltip(javax.swing.JComponent owner, String name, String info) {
super(owner);
this.info = info;
contentsPanel = new javax.swing.JPanel(new GridLayout(0,1));
nameLabel = new javax.swing.JLabel();
nameLabel.setText(name);
infoLabel = new javax.swing.JLabel();
infoLabel.setText(this.info);
contentsPanel.add(nameLabel);
contentsPanel.add(infoLabel);
//contentsPanel.add(new javax.swing.JButton(new javax.swing.AbstractAction("Context Menu") {
// public void actionPerformed (java.awt.event.ActionEvent e) {
// System.out.println("Gender for " + GraphViewNodeTooltip.this.nameLabel.getText() + ": " + GraphViewNodeTooltip.this.gender);
// }
//}
//));
contentsPanel.setBorder(BorderFactory.createLineBorder(Color.gray));
contentsPanel.setBackground(new Color(255, 250, 205));
}
public java.awt.Component getContents() {
return contentsPanel;
}
}