AT&T   AT&T Home | AT&T Labs
Labs image
AT&T Labs - Research


Home | Changes | JavaDocs | Download | Demo | GraphViz | FAQs

Change History

September 22, 2010

  • Substantial performance improvements courtesy of Charles Ballance.

March 4, 2008

  • Minor change to default style handling in

October 10, 2006

  • Fixed reported bugs 440 and 1031 relating to infinte paint looping in GrappaPanel.

April 27, 2006

  • Fixed bug with addTag in

March 4, 2006

  • Made 'filterMode' variable public in the Graph class. It is a flag that indicates that the edge name should be included in the edge attributes when output is generated by printGraph.

January 12, 2006

  • Moved call to java.awt.Toolkit.getDefaultToolkit() from to so that it is not actually called until it is really needed.

August 21, 2005

  • Added fix into suggested by Martin Bierkoch and also made changes to that allows Grappa to pass through labels that begin with < and end with >. Such labels are used by the graphviz tools to provide HTML-like formatting of labels. Grappa itself does not decipher them. The fix simply keeps Grappa from corrupting them.

May 26, 2005

  • Distribution now includes the proper license files (Grappa is licensed under Common Public License as put out by the Open Source Foundation).
  • Included a new demo file ( that shows how to build a graph up directly within a Java program (it places the nodes in a simple-minded manner, but provides a button to invoke the "dot" layout engine over the web).

May 25, 2005

  • Grappa will now compile under JDK1.5, though there will be the following warnings:
    Note: Some input files use unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    since the new Generics capabilities in JDK1.5 were not employed. It seems to me that the warnings can be safely ignored.

December 1, 2004

  • Grappa will now recognize headlabel, head_lp, taillabel and tail_lp as edge attributes. Both the label and position attribute must be present for the label to appear (i.e., Grappa will not even guess at a label position if it is not present).

November 18, 2004

  • Grappa will now recognize point as a node shape attribute.

October 8, 2004

  • Fixed bug in addGrappaListener that failed to remove old mouse activity listeners when addGrappaListener is used more than once. Thanks to Christope Dousson for finding and correcting the problem.

August 12, 2004

  • Added call to EventQueue.invokeLater in to position graph at center of a swept zoom box (needed to make sure scaling changes are completed before positioning is calculated)
  • Added centerPanelAtPoint method in GrappaPanel
  • Made the setName(String) method in Node public to allow the node name to be changed after the node has been created

February 7, 2003

  • Modified some string handling so that non-ASCII alphabetic characters could be used in node names without the need for double quotes.

June 13, 2002

  • Relaxed some GrappaAdapter field permissions so that classes that extend it can really access all they need to access to at least duplicate what is performed in GrappaAdapter itself (and hopefully more).
  • Added additional options when the rightmost mouse button is clicked within a GrappaPanel when GrappaAdapter is being used.

May 13, 2002

  • Now when clicking mouse button 1 to select a single element, the selction cycles through all possible choices with each subsequent click. For example, if there is a node within a subgraph within the main graph, then the first click in the node selects the node, the second selects the subgraph and third selects the main graph. The next click would once again select the node.
  • Added global variables in the Grappa class to make types of elements (subgraphs, nodes or edges) unselectable, if desired.
  • Finally made edge selection work better by creating a fat, invisible version of the edge shape for selection purposes. The problem here was that Java's contains and intersects methods do not work with straight lines since a straight line has no interior.

May 1, 2002

  • Modified parser to allow unquoted decimal numbers to serve as attribute values. Scientific notation numbers, numbers with a leading plus sign and negative numbers where a digit does not follow the minus sign still require quoting, as does a list of numbers.

March 27, 2002

  • GrappaPanel now implements the java.awt.print.Printable interface.
  • Added a 'Print' function to the pop-up menu provided by the GrappaAdapter class.

March 22, 2002

  • Fixed bug involving resetting of canonical element name when element name is changed (thanks to Bill Fowler, Mount Allison University, Canada).
  • Fixed a bug in the graph enumeration methods (thanks to Jean-Daniel Fekete, University of Maryland, USA).

October 1, 2001

  • Added a new variation of Edge constructor.
  • Edge names now remain unchanged when GrappaSupport.filterGraph(...) is used. Previously, any assigned Edge name was lost and replaced by an automatically generated name after filterGraph() was used.

September 24, 2001

  • Added a public Object to the Element class for applications writers to use as they will. It is not used by Grappa.

August 30, 2001

August 14, 2001

  • Re-fixed and re-implemented tagging so that the tag attribute (TAG_ATTR) behaves like any other attribute. Also modified and renamed the tag related methods in Element (i.e., addTag, hasTag, hasLocalTag, hasDefaultTag, hasTags, hasLocalTags, hasDefaultTags, removeTag and removeTags) and in Subgraph (i.e., addTypeTag, hasTypeTag, hasTypeTags, removeTypeTag and removeTypeTags).
  • As suggested by Ginny Travers (, added a printlist attribute (PRINTLIST_ATTR) that can be used to specify which attributes are to be included when using methods that involve printing the graph such as printSubgraph, printElement or filterGraph. Use of the PRINTLIST_ATTR can be activated either at the Element level setting usePrintList instance variable or at the global level by means of the usePrintList class variable in the Grappa class.
  • Also suggested by Ginny Travers, a printVisibleOnly class variable was added to the Grappa to suppress printing of invisible elements.
  • Following another suggestion by Ginny Travers, some StringBuffer variables in are now reused to be more efficient.

August 3, 2001

  • Fixed the element tagging mechanism so that setting the default tag attribute supplies default tags for all elements affected by that default attribute.
  • Added breadth-first and depth-first searching as method bdfs(int steps) in the Element class. The return value is a vector of vectors. The vector in the zeroth element of the return vector is always of length 1 and contains the element at which the search was initiated, the vector at position i, if present, contains the elements reachable in i steps from the initial element. When the steps argument is negative, the search is exhaustive. Reading the return vector in the forward (increasing) direction provides breadth-first results, while reading in the reverse direction provides depth-first results.

July 31, 2001

  • Empty subgraphs are now supplied with a default bounding box having zero width and zero height and a position of (0,0).

June 12, 2001

  • Corrected the drawing of subgraphs so that the bounding box outline is only drawn when the subgraph is a cluster subgraph or when the Grappa class variable outlineSubgraphs is set to true.

May 16, 2001

  • Made the GrappaPanel class into a ComponentListener so that when it is resized a revalidate() call can be made to make sure the scrollbars, etc. of any parent container are properly adjusted.

May 4, 2001

  • Added a public, static boolean called waitForImages to the class Grappa that causes Grappa to wait for the IMAGE_ATTR specified image to be loaded before before the element is drawn. By default, Grappa will wait.

May 3, 2001

  • Added image attribute (IMAGE_ATTR) that allows an image to be used as the background of an element. The attribute should specify a URL or local file path that locates a GIF, JPEG or PNG image (i.e., an image format understood by Java). The image is scaled to the bounding box of the element's GrappaShape and then clipped by that shape. The image is drawn after any filling, but before outlines or text are added. It works for all elements, though it does not make much sense for edges. The image begins loading when the GrappaNexus object associated with the element is constructed. If the image has not fully loaded by the time the graph is drawn, the image will be omitted until a request to repaint the graph is made.
  • When a node SHAPE_ATTR is set to "custom" and the CUSTOM_ATTR has been set to the name of a user-supplied class that extends the GrappaShape class, then that user-supplied class is used to specify the Shape of the node. The class constructor should look like:
       public UserClass(Element elem, double x, double y, double width, double height) {
          super(POLYGON_SHAPE, x, y, width, height, 0, 0, 0, 0, 0, false, false, null);
          // code to save arguments as global variables and
          // to set the GrappaShape path variable at a minimum
    Note that the path built in the constructor is used to determine the bounding box and clipping region of the non-text portion of the node. Further customization can be accomplished if the class also implements the CustomRenderer interface (see below).
  • Added an interface definition called CustomRenderer that can be used by a user-defined shape class to specify fill, draw and drawImage behavior. Comments in the CustomRenderer documentation indicate what default method definitions would look like. Note that the drawImage method would never be called if IMAGE_ATTR information is never supplied.
  • Started filling edges so that the arrow heads look nicer.
  • Added setlinewidth as a synonym for linewidth when used in the STYLE_ATTR so that dot can use it when generating PostScript output.
  • Started using integers instead of floats when calling drawString in GrappaPanel so that text does not get messed up when scrolling (I suspect a Java bug in the rounding rules drawString uses).

April 19, 2001

  • Fixed a bug which was probably introduced with the February 15th changes. The bug occurred while attempting to interactively create an edge between two nodes with the result that a node was created instead of the desired edge. The bug was in the code.

March 5, 2001

  • Added invis as a recognized style attribute element. When present, the associated element is not drawn and is not interactively selectable. The effect is the same as setting the visible field in an Element to false. To retain backward compatibility while striving to be true to the dot file format, the redundancy is necessary. Thus, for an element to be visible both the visible field must be true and invis must not be part of the style attribute. Naturally that is the default situation, so by working consistently with either one method or the other will keep unexpected results from occurring.

February 15, 2001

  • For RECORD_SHAPE and MRECORD_SHAPE shape, the RECTS_ATTR is now computed based on the LABEL_ATTR value. Previous releases of Grappa 1.2 relied on "dot" or some other layout engine to provide the RECTS_ATTR information. Consequently, changes to the LABEL_ATTR will be reflected in the graph once a repaint is done. Note that the width and height of the node are unaffected by this process.
  • Some improvements were made to the edge shapes to improve their selectability. In particular, the path (i.e., lineTo, curveTo) had only been specified in one direction and Java automatically closed the path back to the starting point with a straight line when asked to determine if a point was contained in the path. Now, the path is specified forward and backwards so the shape is correct - though it is still hard to select some edges in the parts where they are very straight - I am open to suggestions here, but it seems like Java's contains method for shapes returns false when the shape is one pixel wide and I don't want to force the edges to be wider. I'd like to think that it is just that I don't know how to use Java well enough and I am hoping someone out there knows the trick to getting this right.
  • Tightened up multi-line labels so that they correspond more closely to the way "dot" calculates things rather than relying on the Java FontMetrics and LineMetrics even though they are more correct, technically.

February 8, 2001

  • Started keeping a change history.
  • Added GrappaSupport.centerPanel(Point2D cpt, GrappaPanel gpanel), which is intended to work with a GrappaPanel whose parent is a JViewport (e.g, a GrappaPanel inside a JScrollPane) and will postion the graph in the viewport so that it is centered on the supplied point. Note that the center point of the bounding box of a graph element, elem, is available as:
       new Point2D.Double(
  • Adjusted the block increment for GrappaPanels whose parent is a JViewport so that clicking on the scroll bar (outside of the arrows or "bubble") causes the graph to scroll 90% of the visible area in the direction of the scroll bar.
  • Fixed interactive zoom behavior so that it is either centered on the swept zoom box or remains centered on the current view, depending on which zoom method is used.
  • Provided Grappa.nodeLabelsScaleCutoff, Grappa.edgeLabelsScaleCutoff and Grappa.subgLabelsScaleCutoff, which indicate the value of the scale factor below which text labels are suppressed when the graph is drawn.
  • Padded the clipping rectangle in the GrappaPanel by 1 pixel to account for Java's conservative view of when two rectangles intersect.
  • Fixed several bugs with subgraph bounding box behavior and the BBOX_ATTR ("bbox").
  • The DIR_ATTR ("dir") will now affect the appearance of edges after the edge is created (at edge creation, the information contained in the POS_ATTR ("pos") takes precedence).
  • Changed GrappaListener.grappaClicked() (and the corresponding method in GrappaAdapter) so that multiple mouse click information is available. Users that wrote their own grappaClicked() method will have to add a new int argument to the calling list that provides the click count, which can just be ignored if it is not needed. Refer to the documentation for grappaClicked().