/* * TouchGraph LLC. Apache-Style Software License * * * Copyright (c) 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. * ==================================================================== * */ /* * Modifications by Miika Nurminen (minurmin@cc.jyu.fi) for KeyGraph. * Fixed node label positioning to work correctly with Linux. * 31.12.2003. */ 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; /** Node. * * @author Alexander Shapiro * @author Murray Altheim (2001-11-06; added support for round rects and alternate Node colors) * @version 1.20 */ 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; public static final String AUTO_ID_STRING = "AutoID "; public static final Font SMALL_TAG_FONT = new Font("Courier",Font.PLAIN,9); // Variables that store default values for colors + fonts + node type public static Color BACK_FIXED_COLOR = Color.red; public static Color BACK_SELECT_COLOR = new Color(255, 224, 0); public static Color BACK_DEFAULT_COLOR = new Color(208, 96, 0); public static Color BACK_HILIGHT_COLOR = Color.decode("#ffb200"); // altheim: new public static Color BORDER_DRAG_COLOR = Color.black; public static Color BORDER_MOUSE_OVER_COLOR = new Color(160,160,160); public static Color BORDER_INACTIVE_COLOR = Color.white; public static Color TEXT_COLOR = Color.white; public static Font TEXT_FONT = new Font("Courier",Font.PLAIN,12); 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; protected boolean visible; public double x; public double y; 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 localEdgeCount; private Vector edges; // ............ /** 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 ) { if (identifier != null) this.id = identifier; else this.id = AUTO_ID_STRING+new Date().getTime(); 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; localEdgeCount=0; } // setters and getters ............... public static void setNodeBackFixedColor( Color color ) { BACK_FIXED_COLOR = color; } public static void setNodeBackSelectColor( Color color ) { BACK_SELECT_COLOR = color; } public static void setNodeBackDefaultColor( Color color ) { BACK_DEFAULT_COLOR = color; } public static void setNodeBackHilightColor( Color color ) { BACK_HILIGHT_COLOR = color; } public static void setNodeBorderDragColor( Color color ) { BORDER_DRAG_COLOR = color; } public static void setNodeBorderMouseOverColor( Color color ) { BORDER_MOUSE_OVER_COLOR = color; } public static void setNodeBorderInactiveColor( Color color ) { BORDER_INACTIVE_COLOR = color; } public static void setNodeTextColor( Color color ) { TEXT_COLOR = color; } public static void setNodeTextFont( Font font ) { TEXT_FONT = font; } public static 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 */ 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 */ 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; } // .... /** Returns the number of Edges attached to this Node. */ public int edgeNum() { return edges.size(); } /** Returns the local Edge count. */ public int localEdgeNum() { return localEdgeCount; } /** 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 ( localEdgeNum()