TGGraphLayout/ 0000755 0001750 0001750 00000000000 11325566115 015271 5 ustar starswifter starswifter TGGraphLayout/com/ 0000755 0001750 0001750 00000000000 07561554546 016063 5 ustar starswifter starswifter TGGraphLayout/com/touchgraph/ 0000755 0001750 0001750 00000000000 07561554546 020227 5 ustar starswifter starswifter TGGraphLayout/com/touchgraph/graphlayout/ 0000755 0001750 0001750 00000000000 07561563420 022555 5 ustar starswifter starswifter TGGraphLayout/com/touchgraph/graphlayout/interaction/ 0000755 0001750 0001750 00000000000 07561561342 025075 5 ustar starswifter starswifter TGGraphLayout/com/touchgraph/graphlayout/graphelements/ 0000755 0001750 0001750 00000000000 07561561434 025416 5 ustar starswifter starswifter TGGraphLayout/TGGraphLayout.html 0000644 0001750 0001750 00000000556 07561472516 020667 0 ustar starswifter starswifter
* Parts of this code build upon Sun's Graph Layout example. * http://java.sun.com/applets/jdk/1.1/demo/GraphLayout/Graph.java *
* * @author Alexander Shapiro * @author Murray Altheim (2001-11-06; 2002-01-14 cleanup) * @version 1.22-jre1.1 $Id: TGPanel.java,v 1.2 2002/09/20 14:26:17 ldornbusch Exp $ */ public class TGPanel extends Panel { // static variables for use within the package public static Color BACK_COLOR = Color.white; // .... private GraphEltSet completeEltSet; private VisibleLocality visibleLocality; private LocalityUtils localityUtils; public TGLayout tgLayout; protected BasicMouseMotionListener basicMML; protected Edge mouseOverE; //mouseOverE is the edge the mouse is over protected Node mouseOverN; //mouseOverN is the node the mouse is over protected boolean maintainMouseOver = false; //If true, then don't change mouseOverN or mouseOverE protected Node select; Node dragNode; //Node currently being dragged protected Point mousePos; //Mouse location, updated in the mouseMotionListener Image offscreen; Dimension offscreensize; Graphics offgraphics; private Vector graphListeners; private Vector paintListeners; TGLensSet tgLensSet; // Converts between a nodes visual position (drawx, drawy), // and its absolute position (x,y). AdjustOriginLens adjustOriginLens; SwitchSelectUI switchSelectUI; /** Default constructor. */ public TGPanel() { setLayout(null); setGraphEltSet(new GraphEltSet()); addMouseListener(new BasicMouseListener()); basicMML = new BasicMouseMotionListener(); addMouseMotionListener(basicMML); graphListeners=new Vector(); paintListeners=new Vector(); adjustOriginLens = new AdjustOriginLens(); switchSelectUI = new SwitchSelectUI(); TGLayout tgLayout = new TGLayout(this); setTGLayout(tgLayout); tgLayout.start(); setGraphEltSet(new GraphEltSet()); } public void setLensSet( TGLensSet lensSet ) { tgLensSet = lensSet; } public void setTGLayout( TGLayout tgl ) { tgLayout = tgl; } public void setGraphEltSet( GraphEltSet ges ) { completeEltSet = ges; visibleLocality = new VisibleLocality(completeEltSet); localityUtils = new LocalityUtils(visibleLocality, this); } public AdjustOriginLens getAdjustOriginLens() { return adjustOriginLens; } public SwitchSelectUI getSwitchSelectUI() { return switchSelectUI; } // color and font setters ...................... public void setBackColor( Color color ) { BACK_COLOR = color; } // Node manipulation ........................... /** Returns an Iterator over all nodes in the complete graph. */ /* public Iterator getAllNodes() { return completeEltSet.getNodes(); } */ /** Return the current visible locality. */ public ImmutableGraphEltSet getGES() { return visibleLocality; } /** Returns the current node count. */ public int getNodeCount() { return completeEltSet.nodeCount(); } /** Returns the current node count within the VisibleLocality. * @deprecated this method has been replaced by the visibleNodeCount() method. */ public int nodeNum() { return visibleLocality.nodeCount(); } /** Returns the current node count within the VisibleLocality. */ public int visibleNodeCount() { return visibleLocality.nodeCount(); } /** Return the Node whose ID matches the String id, null if no match is found. * * @param id The ID identifier used as a query. * @return The Node whose ID matches the provided 'id', null if no match is found. */ public Node findNode( String id ) { if ( id == null ) return null; // ignore return completeEltSet.findNode(id); } /** Return the Node whose URL matches the String strURL, null if no match is found. * * @param strURL The URL identifier used as a query. * @return The Node whose URL matches the provided 'URL', null if no match is found. */ public Node findNodeByURL( String strURL ) { if ( strURL == null ) return null; // ignore return completeEltSet.findNodeByURL(strURL); } /** Return a Collection of all Nodes whose label matches the String label, * null if no match is found. */ /* public Collection findNodesByLabel( String label ) { if ( label == null ) return null; // ignore return completeEltSet.findNodesByLabel(label); } */ /** Return the first Nodes whose label contains the String substring, * null if no match is found. * @param substring The Substring used as a query. */ public Node findNodeLabelContaining( String substring ) { if ( substring == null ) return null; //ignore return completeEltSet.findNodeLabelContaining(substring); } /** Adds a Node, with its ID and label being the current node count plus 1. * @see com.touchgraph.graphlayout.Node */ public Node addNode() throws TGException { String id = String.valueOf(getNodeCount()+1); return addNode(id,null); } /** Adds a Node, provided its label. The node is assigned a unique ID. * @see com.touchgraph.graphlayout.graphelements.GraphEltSet */ public Node addNode( String label ) throws TGException { return addNode(null,label); } /** Adds a Node, provided its ID and label. * @see com.touchgraph.graphlayout.Node */ public Node addNode( String id, String label ) throws TGException { Node node; if (label==null) node = new Node(id); else node = new Node(id, label); updateDrawPos(node); // The addNode() call should probably take a position, this just sets it at 0,0 addNode(node); return node; } /** Add the Node node to the visibleLocality, checking for ID uniqueness. */ public void addNode( final Node node ) throws TGException { synchronized (localityUtils) { visibleLocality.addNode(node); resetDamper(); } } /** Remove the Node object matching the IDid
, returning true if the
* deletion occurred, false if a Node matching the ID does not exist (or if the ID
* value was null).
*
* @param id The ID identifier used as a query.
* @return true if the deletion occurred.
*/
public boolean deleteNodeById( String id )
{
if ( id == null ) return false; // ignore
Node node = findNode(id);
if ( node == null ) return false;
else return deleteNode(node);
}
public boolean deleteNode( Node node ) {
synchronized (localityUtils) {
if (visibleLocality.deleteNode(node)) { // delete from visibleLocality, *AND completeEltSet
if ( node == select ) clearSelect();
resetDamper();
return true;
}
return false;
}
}
public void clearAll() {
synchronized (localityUtils) {
visibleLocality.clearAll();
}
}
public Node getSelect() {
return select;
}
public Node getMouseOverN() {
return mouseOverN;
}
public synchronized void setMouseOverN( Node node ) {
if ( dragNode != null || maintainMouseOver ) return; // So you don't accidentally switch nodes while dragging
if ( mouseOverN != node ) {
Node oldMouseOverN = mouseOverN;
mouseOverN=node;
}
if (mouseOverN==null)
setCursor(new Cursor(Cursor.MOVE_CURSOR));
else
setCursor(new Cursor(Cursor.HAND_CURSOR));
}
// Edge manipulation ...........................
/** Returns an Iterator over all edges in the complete graph. */
/* public Iterator getAllEdges() {
return completeEltSet.getEdges();
}
*/
public void deleteEdge( Edge edge ) {
synchronized (localityUtils) {
visibleLocality.deleteEdge(edge);
resetDamper();
}
}
public void deleteEdge( Node from, Node to ) {
synchronized (localityUtils) {
visibleLocality.deleteEdge(from,to);
}
}
/** Returns the current edge count in the complete graph.
*/
public int getEdgeCount() {
return completeEltSet.edgeCount();
}
/** Return the number of Edges in the Locality.
* @deprecated this method has been replaced by the visibleEdgeCount() method.
*/
public int edgeNum() {
return visibleLocality.edgeCount();
}
/** Return the number of Edges in the Locality.
*/
public int visibleEdgeCount() {
return visibleLocality.edgeCount();
}
public Edge findEdge( Node f, Node t ) {
return visibleLocality.findEdge(f, t);
}
public void addEdge(Edge e) {
synchronized (localityUtils) {
visibleLocality.addEdge(e); resetDamper();
}
}
public Edge addEdge( Node f, Node t, int tens ) {
synchronized (localityUtils) {
return visibleLocality.addEdge(f, t, tens);
}
}
public Edge getMouseOverE() {
return mouseOverE;
}
public synchronized void setMouseOverE( Edge edge ) {
if ( dragNode != null || maintainMouseOver ) return; // No funny business while dragging
if ( mouseOverE != edge ) {
Edge oldMouseOverE = mouseOverE;
mouseOverE = edge;
}
}
// miscellany ..................................
protected class AdjustOriginLens extends TGAbstractLens {
protected void applyLens(TGPoint2D p) {
p.x=p.x+TGPanel.this.getSize().width/2;
p.y=p.y+TGPanel.this.getSize().height/2;
}
protected void undoLens(TGPoint2D p) {
p.x=p.x-TGPanel.this.getSize().width/2;
p.y=p.y-TGPanel.this.getSize().height/2;
}
}
public class SwitchSelectUI extends TGAbstractClickUI {
public void mouseClicked(MouseEvent e) {
if ( mouseOverN != null ) {
if ( mouseOverN != select )
setSelect(mouseOverN);
else
clearSelect();
}
}
}
void fireMovedEvent() {
Vector listeners;
synchronized(this) {
listeners = (Vector)graphListeners.clone();
}
for (int i=0;i* Parts of this code build upon Sun's Graph Layout example. * http://java.sun.com/applets/jdk/1.1/demo/GraphLayout/Graph.java *
* * @author Alexander Shapiro * @version 1.22-jre1.1 $Id: TGLayout.java,v 1.1 2002/09/19 15:58:08 ldornbusch Exp $ */ public class TGLayout implements Runnable { //private ImmutableGraphEltSet graphEltSet; private TGPanel tgPanel; private Thread relaxer; private double damper=0.0; // A low damper value causes the graph to move slowly private double maxMotion=0; // Keep an eye on the fastest moving node to see if the graph is stabilizing private double lastMaxMotion=0; private double motionRatio = 0; // It's sort of a ratio, equal to lastMaxMotion/maxMotion-1 private boolean damping = true; // When damping is true, the damper value decreases private double rigidity = 1; // Rigidity has the same effect as the damper, except that it's a constant // a low rigidity value causes things to go slowly. // a value that's too high will cause oscillation private double newRigidity = 1; Node dragNode=null; // ............ /** Constructor with a supplied TGPanel tgp. */ public TGLayout( TGPanel tgp ) { tgPanel = tgp; //graphEltSet = tgPanel.getGES(); relaxer = null; } void setRigidity(double r) { newRigidity = r; //update rigidity at the end of the relax() thread } void setDragNode(Node n) { dragNode = n; } //relaxEdges is more like tense edges up. All edges pull nodes closes together; private synchronized void relaxEdges() { TGForEachEdge fee = new TGForEachEdge() { public void forEachEdge(Edge e) { double vx = e.to.x - e.from.x; double vy = e.to.y - e.from.y; double len = Math.sqrt(vx * vx + vy * vy); double dx=vx*rigidity; //rigidity makes edges tighter double dy=vy*rigidity; dx /=(e.getLength()*100); dy /=(e.getLength()*100); // Edges pull directly in proportion to the distance between the nodes. This is good, // because we want the edges to be stretchy. The edges are ideal rubberbands. They // They don't become springs when they are too short. That only causes the graph to // oscillate. if (e.to.justMadeLocal || e.to.markedForRemoval || (!e.from.justMadeLocal && !e.from.markedForRemoval)) { e.to.dx -= dx*len; e.to.dy -= dy*len; } else { double massfade = (e.from.markedForRemoval ? e.from.massfade : 1-e.from.massfade); massfade*=massfade; e.to.dx -= dx*len*massfade; e.to.dy -= dy*len*massfade; } if (e.from.justMadeLocal || e.from.markedForRemoval || (!e.to.justMadeLocal && !e.to.markedForRemoval)) { e.from.dx += dx*len; e.from.dy += dy*len; } else { double massfade = (e.to.markedForRemoval ? e.to.massfade : 1-e.to.massfade); massfade*=massfade; e.from.dx += dx*len*massfade; e.from.dy += dy*len*massfade; } } }; tgPanel.getGES().forAllEdges(fee); } /* private synchronized void avoidLabels() { for (int i = 0 ; i < graphEltSet.nodeNum() ; i++) { Node n1 = graphEltSet.nodeAt(i); double dx = 0; double dy = 0; for (int j = 0 ; j < graphEltSet.nodeNum() ; j++) { if (i == j) { continue; // It's kind of dumb to do things this way. j should go from i+1 to nodeNum. } Node n2 = graphEltSet.nodeAt(j); double vx = n1.x - n2.x; double vy = n1.y - n2.y; double len = vx * vx + vy * vy; // so it's length squared if (len == 0) { dx += Math.random(); // If two nodes are right on top of each other, randomly separate dy += Math.random(); } else if (len <600*600) { //600, because we don't want deleted nodes to fly too far away dx += vx / len; // If it was sqrt(len) then a single node surrounded by many others will dy += vy / len; // always look like a circle. This might look good at first, but I think // it makes large graphs look ugly + it contributes to oscillation. A // linear function does not fall off fast enough, so you get rough edges // in the 'force field' } } n1.dx += dx*100*rigidity; // rigidity makes nodes avoid each other more. n1.dy += dy*100*rigidity; // I was surprised to see that this exactly balances multiplying edge tensions // by the rigidity, and thus has the effect of slowing the graph down, while // keeping it looking identical. } } */ private synchronized void avoidLabels() { TGForEachNodePair fenp = new TGForEachNodePair() { public void forEachNodePair(Node n1, Node n2) { double dx=0; double dy=0; double vx = n1.x - n2.x; double vy = n1.y - n2.y; double len = vx * vx + vy * vy; //so it's length squared if (len == 0) { dx = Math.random(); //If two nodes are right on top of each other, randomly separate dy = Math.random(); } else if (len <600*600) { //600, because we don't want deleted nodes to fly too far away dx = vx / len; // If it was sqrt(len) then a single node surrounded by many others will dy = vy / len; // always look like a circle. This might look good at first, but I think // it makes large graphs look ugly + it contributes to oscillation. A // linear function does not fall off fast enough, so you get rough edges // in the 'force field' } int repSum = n1.repulsion * n2.repulsion/100; if(n1.justMadeLocal || n1.markedForRemoval || (!n2.justMadeLocal && !n2.markedForRemoval)) { n1.dx += dx*repSum*rigidity; n1.dy += dy*repSum*rigidity; } else { double massfade = (n2.markedForRemoval ? n2.massfade : 1-n2.massfade); massfade*=massfade; n1.dx += dx*repSum*rigidity*massfade; n1.dy += dy*repSum*rigidity*massfade; } if (n2.justMadeLocal || n2.markedForRemoval || (!n1.justMadeLocal && !n1.markedForRemoval)) { n2.dx -= dx*repSum*rigidity; n2.dy -= dy*repSum*rigidity; } else { double massfade = (n1.markedForRemoval ? n1.massfade : 1-n1.massfade); massfade*=massfade; n2.dx -= dx*repSum*rigidity*massfade; n2.dy -= dy*repSum*rigidity*massfade; } } }; tgPanel.getGES().forAllNodePairs(fenp); } public void startDamper() { damping = true; } public void stopDamper() { damping = false; damper = 1.0; //A value of 1.0 means no damping } public void resetDamper() { //reset the damper, but don't keep damping. damping = true; damper = 1.0; } public void stopMotion() { // stabilize the graph, but do so gently by setting the damper to a low value damping = true; if (damper>0.3) damper = 0.3; else damper = 0; } public void damp() { if (damping) { if(motionRatio<=0.001) { //This is important. Only damp when the graph starts to move faster //When there is noise, you damp roughly half the time. (Which is a lot) // //If things are slowing down, then you can let them do so on their own, //without damping. //If max motion<0.2, damp away //If by the time the damper has ticked down to 0.9, maxMotion is still>1, damp away //We never want the damper to be negative though if ((maxMotion<0.2 || (maxMotion>1 && damper<0.9)) && damper > 0.01) damper -= 0.01; //If we've slowed down significanly, damp more aggresively (then the line two below) else if (maxMotion<0.4 && damper > 0.003) damper -= 0.003; //If max motion is pretty high, and we just started damping, then only damp slightly else if(damper>0.0001) damper -=0.0001; } } if(maxMotion<0.001 && damping) { damper=0; } } private synchronized void moveNodes() { lastMaxMotion = maxMotion; final double[] maxMotionA = new double[1]; maxMotionA[0]=0; TGForEachNode fen = new TGForEachNode() { public void forEachNode(Node n) { double dx = n.dx; double dy = n.dy; dx*=damper; //The damper slows things down. It cuts down jiggling at the last moment, and optimizes dy*=damper; //layout. As an experiment, get rid of the damper in these lines, and make a //long straight line of nodes. It wiggles too much and doesn't straighten out. n.dx=dx/2; //Slow down, but don't stop. Nodes in motion store momentum. This helps when the force n.dy=dy/2; //on a node is very low, but you still want to get optimal layout. double distMoved = Math.sqrt(dx*dx+dy*dy); //how far did the node actually move? if (!n.fixed && !(n==dragNode) ) { n.x += Math.max(-30, Math.min(30, dx)); //don't move faster then 30 units at a time. n.y += Math.max(-30, Math.min(30, dy)); //I forget when this is important. Stopping severed nodes from //flying away? } maxMotionA[0]=Math.max(distMoved,maxMotionA[0]); if(!n.justMadeLocal && !n.markedForRemoval) { n.massfade=1; } else { if(n.massfade>=0.004) n.massfade-=0.004; } } }; tgPanel.getGES().forAllNodes(fen); maxMotion=maxMotionA[0]; if (maxMotion>0) motionRatio = lastMaxMotion/maxMotion-1; //subtract 1 to make a positive value mean that else motionRatio = 0; //things are moving faster damp(); } private synchronized void relax() { for (int i=0;i<10;i++) { relaxEdges(); avoidLabels(); moveNodes(); } if(rigidity!=newRigidity) rigidity= newRigidity; //update rigidity tgPanel.repaintAfterMove(); } private void myWait() { //I think it was Netscape that caused me not to use Wait, or was it java 1.1? try { Thread.sleep(100); } catch (InterruptedException e) { //break; } } public void run() { Thread me = Thread.currentThread(); // me.setPriority(1); //Makes standard executable look better, but the applet look worse. while (relaxer == me) { relax(); try { relaxer.sleep(20); //Delay to wait for the prior repaint command to finish. while(damper<0.1 && damping && maxMotion<0.001) myWait(); //System.out.println("damping " + damping + " damp " + damper + " maxM " + maxMotion + " motR " + motionRatio ); } catch (InterruptedException e) { break; } } } public void start() { relaxer = new Thread(this); relaxer.start(); } public void stop() { relaxer = null; } } // end com.touchgraph.graphlayout.TGLayout TGGraphLayout/com/touchgraph/graphlayout/TGException.java 0000644 0001750 0001750 00000010777 07561561054 025626 0 ustar starswifter starswifter /* * TouchGraph LLC. Apache-Style Software License * * * Copyright (c) 2001-2002 Alexander Shapiro. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by * TouchGraph LLC (http://www.touchgraph.com/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "TouchGraph" or "TouchGraph LLC" must not be used to endorse * or promote products derived from this software without prior written * permission. For written permission, please contact * alex@touchgraph.com * * 5. Products derived from this software may not be called "TouchGraph", * nor may "TouchGraph" appear in their name, without prior written * permission of alex@touchgraph.com. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL TOUCHGRAPH OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * */ package com.touchgraph.graphlayout; /**An class for exceptions thrown during TouchGraph processing.
* * @author Alexander Shapiro * @author Murray Altheim * @version 1.22-jre1.1 $Id: TGException.java,v 1.1 2002/09/19 15:58:08 ldornbusch Exp $ */ public class TGException extends Exception { /** An exception occurring when a Node already exists. */ public final static int NODE_EXISTS = 1; /** An exception occurring when a Node doesn't exist. */ public final static int NODE_DOESNT_EXIST = 2; /** An exception occurring when a Node is missing its required ID. */ public final static int NODE_NO_ID = 3; /** An int containing an exception type identifier (ID). */ protected int id = -1; /** The embedded Exception if tunnelling. * @serial The embedded exception if tunnelling, or null. */ public Exception exception = null; // ............. /** Constructor for TGException with Exception ID. * * @param id The unique message identifier. */ public TGException( int id ) { super(); this.id = id; } /** Constructor for TGException with Exception ID and error message String. * * @param id The unique message identifier. * @param message The Exception message. */ public TGException( int id, String message ) { super(message); this.id = id; } /** Constructor for TGException with an error message String. * * @param message The Exception message. */ public TGException( String message ) { super(message); } /** Constructor for TGException tunnelling the original Exception. * * @param exception The original Exception. */ public TGException( Exception exception ) { super(); this.exception = exception; } /** If the message was expressed as a MessageId, return the original * id (e.g. "45"). * * @return the exception identifier. */ public int getId() { return id; } } // end com.touchgraph.graphlayout.TGException TGGraphLayout/com/touchgraph/graphlayout/TGAbstractLens.java 0000644 0001750 0001750 00000005406 07561561054 026246 0 ustar starswifter starswifter /* * TouchGraph LLC. Apache-Style Software License * * * Copyright (c) 2001-2002 Alexander Shapiro. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by * TouchGraph LLC (http://www.touchgraph.com/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "TouchGraph" or "TouchGraph LLC" must not be used to endorse * or promote products derived from this software without prior written * permission. For written permission, please contact * alex@touchgraph.com * * 5. Products derived from this software may not be called "TouchGraph", * nor may "TouchGraph" appear in their name, without prior written * permission of alex@touchgraph.com. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL TOUCHGRAPH OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * */ package com.touchgraph.graphlayout; /** TGAbstractLens. A lens warps 2D space. * * @author Alexander Shapiro * @version 1.22-jre1.1 $Id: TGAbstractLens.java,v 1.1 2002/09/19 15:58:07 ldornbusch Exp $ */ public abstract class TGAbstractLens { protected void applyLens( TGPoint2D p ) {} protected void undoLens( TGPoint2D p ) {} } // end com.touchgraph.graphlayout.TGAbstractLens TGGraphLayout/com/touchgraph/graphlayout/Node.java 0000644 0001750 0001750 00000041067 07561561052 024314 0 ustar starswifter starswifter /* * TouchGraph LLC. Apache-Style Software License * * * Copyright (c) 2001-2002 Alexander Shapiro. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by * TouchGraph LLC (http://www.touchgraph.com/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "TouchGraph" or "TouchGraph LLC" must not be used to endorse * or promote products derived from this software without prior written * permission. For written permission, please contact * alex@touchgraph.com * * 5. Products derived from this software may not be called "TouchGraph", * nor may "TouchGraph" appear in their name, without prior written * permission of alex@touchgraph.com. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL TOUCHGRAPH OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * */ package com.touchgraph.graphlayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.util.Date; import java.util.Vector; //import java.util.Iterator; /** Node. * * @author Alexander Shapiro * @author Murray Altheim (2001-11-06; added support for round rects and alternate Node colors) * @version 1.22-jre1.1 $Id: Node.java,v 1.2 2002/09/20 14:00:22 ldornbusch Exp $ */ public class Node { /** This Node's type is a Rectangle. */ public final static int TYPE_RECTANGLE = 1; /** This Node's type is a Round Rectangle. */ public final static int TYPE_ROUNDRECT = 2; /** This Node's type is an Ellipse. */ public final static int TYPE_ELLIPSE = 3; /** This Node's type is a Circle. */ public final static int TYPE_CIRCLE = 4; public static final Font SMALL_TAG_FONT = new Font("Courier",Font.PLAIN,9); // Variables that store default values for colors + fonts + node type public Color BACK_FIXED_COLOR = new Color(255, 32, 20); public Color BACK_SELECT_COLOR = new Color(225, 164, 0); public Color BACK_DEFAULT_COLOR = Color.decode("#4080A0"); public Color BACK_HILIGHT_COLOR = new Color(205, 192, 166); public Color BACK_MRF_COLOR = new Color(2,35,81); public Color BACK_JML_COLOR = new Color(58, 176, 255); public Color BORDER_DRAG_COLOR = new Color(130,130,180); public Color BORDER_MOUSE_OVER_COLOR = new Color(160,160,180); public Color BORDER_INACTIVE_COLOR = new Color(30,50,160); public Color TEXT_COLOR = Color.white; public static Font TEXT_FONT = new Font("Verdana",Font.PLAIN,10); public static int DEFAULT_TYPE = 1; /** an int indicating the Node type. * @see TYPE_RECTANGLE * @see TYPE_ROUNDRECT * @see TYPE_ELLIPSE */ protected int typ = TYPE_RECTANGLE; private String id; public double drawx; public double drawy; protected FontMetrics fontMetrics; protected Font font; protected String lbl; protected Color backColor = BACK_DEFAULT_COLOR; protected Color textColor = TEXT_COLOR; public double x; public double y; public double massfade=1; //Used by layout protected double dx; //Used by layout protected double dy; //Used by layout protected boolean fixed; protected int repulsion; //Used by layout public boolean justMadeLocal = false; public boolean markedForRemoval = false; public int visibleEdgeCnt; //Should only be modified by graphelements.VisibleLocality protected boolean visible; private Vector edges; // ............ // Modification by Lutz private String strUrl; /** Minimal constructor which will generate an ID value from Java's Date class. * Defaults will be used for type and color. The label will be taken from the ID value. */ public Node() { initialize(null); lbl = id; } /** Constructor with the required ID id, using defaults * for type (rectangle), color (a static variable from TGPanel). * The Node's label will be taken from the ID value. */ public Node( String id ) { initialize(id); lbl = id; } /** Constructor with Strings for ID id and label, using defaults * for type (rectangle) and color (a static variable from TGPanel). * If the label is null, it will be taken from the ID value. */ public Node( String id, String label ) { initialize(id); if ( label == null ) lbl = id; else lbl = label; } /** Constructor with a String ID id, an int type, Background Color bgColor, * and a String label. If the label is null, it will be taken from the ID value. * @see TYPE_RECTANGLE * @see TYPE_ROUNDRECT */ public Node( String id, int type, Color color, String label ) { initialize(id); typ = type; backColor = color; if ( label == null ) lbl = id; else lbl = label; } private void initialize( String identifier ) { this.id = identifier; edges = new Vector(); x = Math.random()*2-1; // If multiple nodes are added without repositioning, y = Math.random()*2-1; // randomizing starting location causes them to spread out nicely. repulsion = 100; font = TEXT_FONT; fixed = false; typ = DEFAULT_TYPE; visibleEdgeCnt=0; visible = false; } // setters and getters ............... public void setNodeBackFixedColor( Color color ) { BACK_FIXED_COLOR = color; } public void setNodeBackSelectColor( Color color ) { BACK_SELECT_COLOR = color; } public void setNodeBackDefaultColor( Color color ) { BACK_DEFAULT_COLOR = color; } public void setNodeBackHilightColor( Color color ) { BACK_HILIGHT_COLOR = color; } public void setNodeBorderDragColor( Color color ) { BORDER_DRAG_COLOR = color; } public void setNodeBorderMouseOverColor( Color color ) { BORDER_MOUSE_OVER_COLOR = color; } public void setNodeBorderInactiveColor( Color color ) { BORDER_INACTIVE_COLOR = color; } public void setNodeTextColor( Color color ) { TEXT_COLOR = color; } public void setNodeTextFont( Font font ) { TEXT_FONT = font; } public void setNodeType( int type ) { DEFAULT_TYPE = type; } /** Set the ID of this Node to the String id. */ public void setID( String id ) { this.id = id; } /** Return the ID of this Node as a String. */ public String getID() { return id; } /** Set the location of this Node provided the Point p. */ public void setLocation( Point p ) { this.x = p.x; this.y = p.y; } /** Return the location of this Node as a Point. */ public Point getLocation() { return new Point((int)x,(int)y); } /** Set the visibility of this Node to the boolean v. */ public void setVisible( boolean v) { visible = v; } /** Return the visibility of this Node as a boolean. */ public boolean isVisible() { return visible; } /** Set the type of this Node to the int type. * @see TYPE_RECTANGLE * @see TYPE_ROUNDRECT * @see TYPE_ELLIPSE * @see TYPE_CIRCLE */ public void setType( int type ) { typ = type; } /** Return the type of this Node as an int. * @see TYPE_RECTANGLE * @see TYPE_ROUNDRECT * @see TYPE_ELLIPSE * @see TYPE_CIRCLE */ public int getType() { return typ; } /** Set the font of this Node to the Font font. */ public void setFont( Font font ) { this.font = font; } /** Returns the font of this Node as a Font*/ public Font getFont() { return font; } /** Set the background color of this Node to the Color bgColor. */ public void setBackColor( Color bgColor ) { backColor = bgColor; } /** Return the background color of this Node as a Color. */ public Color getBackColor() { return backColor; } /** Set the text color of this Node to the Color txtColor. */ public void setTextColor( Color txtColor ) { textColor = txtColor; } /** Return the text color of this Node as a Color. */ public Color getTextColor() { return textColor; } /** Set the label of this Node to the String label. */ public void setLabel( String label ) { lbl = label; } /** Return the label of this Node as a String. */ public String getLabel() { return lbl; } /** Set the fixed status of this Node to the boolean fixed. */ public void setFixed( boolean fixed ) { this.fixed = fixed; } /** Returns true if this Node is fixed (in place). */ public boolean getFixed() { return fixed; } // .... /** Return the number of Edges in the cumulative Vector. * @deprecated this method has been replaced by the edgeCount() method. */ public int edgeNum() { return edges.size(); } /** Return the number of Edges in the cumulative Vector. */ public int edgeCount() { return edges.size(); } /** Return an iterator over the Edges in the cumulative Vector, null if it is empty. */ /* public Iterator getEdges() { if ( edges.size() == 0 ) return null; else return edges.iterator(); } */ /** Returns the local Edge count. */ public int visibleEdgeCount() { return visibleEdgeCnt; } /** Return the Edge at int index. */ public Edge edgeAt( int index ) { return (Edge)edges.elementAt(index); } /** Add the Edge edge to the graph. */ public void addEdge( Edge edge ) { if ( edge == null ) return; edges.addElement(edge); } /** Remove the Edge edge from the graph. */ public void removeEdge( Edge edge ) { edges.removeElement(edge); } /** Return the width of this Node. */ public int getWidth() { if ( fontMetrics != null && lbl != null ) { return fontMetrics.stringWidth(lbl) + 12; } else { return 10; } } /** Return the height of this Node. */ public int getHeight() { if ( fontMetrics != null ) { return fontMetrics.getHeight() + 6; } else { return 6; } } /** Returns true if this Node intersects Dimension d. */ public boolean intersects( Dimension d ) { return ( drawx > 0 && drawx < d.width && drawy>0 && drawy < d.height ); } /** Returns true if this Node contains the Point px,py. */ public boolean containsPoint( double px, double py ) { return (( px > drawx-getWidth()/2) && ( px < drawx+getWidth()/2) && ( py > drawy-getHeight()/2) && ( py < drawy+getHeight()/2)); } /** Returns true if this Node contains the Point p. */ public boolean containsPoint( Point p ) { return (( p.x > drawx-getWidth()/2) && ( p.x < drawx+getWidth()/2) && ( p.y > drawy-getHeight()/2) && ( p.y < drawy+getHeight()/2)); } /** Paints the Node. */ public void paint( Graphics g, TGPanel tgPanel ) { if (!intersects(tgPanel.getSize()) ) return; paintNodeBody(g, tgPanel); if ( visibleEdgeCount()