NonJavaBeans example: abstract model variant

Describes how to display a set of Java™ objects that are not JavaBeans™ by subclassing the abstract class IlvAbstractSDMModel.

Presents an example that displays the contents of a Swing JTree object as a graph.

Explains how to create a Swing JTree object.

Describes how to write a data model that transforms the tree data into an SDM model.

Describes the TreeSDMNode class, which represents the nodes of the graph.

Describes the TreeSDMLink class, which represents the links of the graph.

Shows how to load the data model and style sheet into the diagram component.

The Tree Model example

The Tree Model example displays the contents of a Swing JTree object as a graph. The nodes of the graph are the items in the tree (also called tree nodes), and the links of the graph represent the parent-child relationships between the items., see the following figure.

The Tree Model example: Swing JTree

This example uses the base class IlvAbstractSDMModel and implements nodes and links using the IlvSDMNode and IlvSDMLink interfaces, for the following reasons:

  • The nodes to be represented (the tree nodes) are existing Java™ objects, but they are not JavaBeans™.

  • The links do not exist as Java objects; you need to create them.

The example is supplied with JViews Diagrammer in the directory <installdir>/jviews-diagrammer/codefragments/datamodel/treemodel.

The Swing JTree

The data to be displayed is the contents of a Swing JTree. The example simply uses the contents of a default JTree, which contains names of various colors, sports and food. You create the JTree object as shown in the following code example.

Example    

 

TreeModel treeModel = new JTree().getModel();

The TreeSDMModel class

To display the data model of a tree in a diagram component, you must write a data model that transforms the tree data into an SDM model. In this example, the model is implemented by the class TreeSDMModel, which is a subclass of IlvAbstractSDMModel. Its definition is as shown in the following code example.

Example    

 

public class TreeSDMModel extends IlvAbstractSDMModel

{

...

Root of the tree

The nodes of the graph will be represented by instances of a class TreeSDMNode. The TreeSDMModel class creates a node that represents the root of the tree, and keeps a reference to it as shown in the following code example.

Example    

 

 private TreeSDMNode root;

 

  public TreeSDMModel(TreeModel treeModel)

  {

    root = new TreeSDMNode(treeModel, null, treeModel.getRoot());

  }

When asked to return the top-level objects of the graph, the getObjects method just returns a single element: the root of the tree, as shown in the following code example.

Example    

 

public Enumeration getObjects()

  {

    Vector v = new Vector();

    v.addElement(root);

    return v.elements();

  }

Model is not editable

The clear method must be implemented, but it will never be called since the TreeSDMModel class in this example represents a model that is not editable. The following code example shows the method implementation.

Example    

 

  public void clear()

  {

    // Nothing, this model is immutable.

  }

}

The TreeSDMNode class

The class TreeSDMNode represents the nodes of the graph. Its definition is as shown in the following code example.

Example    

 

public class TreeSDMNode implements IlvSDMNode

{

Data stored

Each node in the graph (graphic object) has a reference to the corresponding node in the tree (model object). References to the parent node (graphic object) and the tree model are also needed. The children of the node are stored in a vector.

Example   Keeping track of the data: current node, parent, children, and model

 

private TreeSDMNode parent;

private TreeModel treeModel;

private Object treeNode;

private Vector children;

 

public TreeSDMNode(TreeModel treeModel, TreeSDMNode parent, Object treeNode)

{

  this.parent = parent;

  this.treeModel = treeModel;

  this.treeNode = treeNode;

 

  createChildren();

 }

Children vector

Note that the constructor calls the method createChildren. This method traverses the tree model and creates a TreeSDMNode instance for each item in the tree. In addition, it creates an instance of TreeSDMLink to draw a link between the parent node and each child node.

Example   Creating the child nodes and links (graphic objects)

 

private void createChildren()

{

  children = new Vector();

 

  // scan all the children of the root tree node, and create

  // a TreeSDMNode for each:

  //

  int count = treeModel.getChildCount(treeNode);

  for(int i = 0; i < count; i++){

    Object childTreeNode = treeModel.getChild(treeNode, i);

 

    // Create the TreeSDMNode. Note that this will recursively create

    // the SDM nodes for all sub-nodes.

    //

    TreeSDMNode childSDMNode = new TreeSDMNode(treeModel, this, childTreeNode);

    children.addElement(childSDMNode);

 

    // Create a parent/child link:

    //

    TreeSDMLink childSDMLink = new TreeSDMLink(this, childSDMNode);

    children.addElement(childSDMLink);

  }

}

Implementation of the IlvSDMNode interface

The following methods are the implementations of the methods belonging to the IlvSDMNode interface, which are inherited by TreeSDMNode.

The getTag method returns the type (or “tag”) of the node. In this example, the type is treenode.

Example   Retrieving the node type: the getTag method

 

  public String getTag()

 

  {

    return "treenode";

  }

The getID method returns the identifier of the node. The identifier of a node is its hash code.

Example   Retrieving the node ID: the getID method

 

  public String getID()

{

    return String.valueOf(hashCode());

  }

The getChildren method returns the children of the node, which are stored in the children data member.

Example   Retrieving the child objects: the getChildren method

 

public Enumeration getChildren()

 

  {

    return children.elements();

  }

The getParent method returns the parent node of the current node.

Example   Retrieving the parent object: the getParent method

 

  public IlvSDMNode getParent()

  {

    return parent;

  }

The getProperty and getPropertyNames methods must be implemented to give the diagram component access to the properties of the node. In this example, there is support for two properties, userObject and CSSclass:

  • The userObject property returns the sample food, color, and sports names.

  • The CSSclass property returns the type of item: food, color, or sport.

Example   Retrieving a property: the getProperty method

 

  public Object getProperty(String property)

  {

    if(treeNode instanceof DefaultMutableTreeNode){

      if(property.equals("userObject")){

        return ((DefaultMutableTreeNode)treeNode).getUserObject();

      }

      if(property.equals("CSSclass") && ((DefaultMutableTreeNode)treeNode).getParent() != null){

        return ((DefaultMutableTreeNode)((DefaultMutableTreeNode)treeNode).getParent()).getUserObject();

      }

    }

    return null;

  }

The getPropertyNames method retrieves the two property names.

Example   Retrieving property names: the getPropertyNames method

 

  public String[] getPropertyNames()

  {

    if(treeNode instanceof DefaultMutableTreeNode)

      return new String[] { "userObject", "CSSclass" };

    else

      return new String[0];

  }

The TreeSDMLink class

The class TreeSDMLink represents the links of the graph. Its definition is as shown in the following code example.

Example    

 

public class TreeSDMLink implements IlvSDMLink

{

...

The link implementation can therefore make use of all the predefined methods of the IlvSDMLink interface.

Data Stored

Each link has a reference to a parent node and a child node, which can be retrieved using the getFrom and getTo methods, see the following code example.

Example   Keeping track of link data: parent and child

 

  private TreeSDMNode parent, child;

 

  public TreeSDMLink(TreeSDMNode parent, TreeSDMNode child)

  {

    this.parent = parent;

    this.child = child;

  }

 

  public IlvSDMNode getFrom()

  {

    return parent;

  }

 

  public IlvSDMNode getTo()

  {

    return child;

  }

Implementation of the IlvSDMNode interface

The IlvSDMLink interface inherits from the IlvSDMNode interface and so the same methods must be implemented as for a node.

The tag (type) of links is treelink. and this value can be retrieved using the getTag method, see the following code example.

Example    

 

public String getTag()

  {

    return "treelink";

  }

The remaining methods are mostly empty, since in this example links have no properties.

Loading the data model and style sheet into the diagram component

The Tree Model sample is a subclass of IlvDiagrammerApplication. It therefore has the full application facilities as described in Customizing the predefined application.

The Data model

To load the TreeSDMModel object, the sample overrides the createDiagrammer method to perform extra operations, see the following code example.

Example    

 

protected IlvDiagrammer createDiagrammer()

  {

    // Create a default tree model. The JTree creates one

    // if you don't specify a model: let's use it.

    //

    TreeModel treeModel = new JTree().getModel();

 

    // Create the IlvDiagrammer instance.

    //

    IlvDiagrammer diagrammer = super.createDiagrammer();

 

    // Create a default tree model. The JTree creates one

The sample creates an instance of TreeSDMModel, giving it a default tree model as a parameter, see the following code example.

Example    

 

 // Create the Tree -> SDM model adapter.

    //

    TreeSDMModel sdmModel = new TreeSDMModel(treeModel);

The sample then gets the SDM engine for the IlvDiagrammer instance and sets the data model to the TreeSDMModel instance, as shown in the following code example.

Example    

 

  // Tell the IlvDiagrammer to use this model:

    //

    diagrammer.getEngine().setModel(sdmModel);

 

    return diagrammer;

  }

The style sheet

The style sheet used to display the tree model is located in <installdir>/jviews-diagrammer/codefragments/datamodel/treemodel/data.

To load the style sheet, you pass the relative path to the sample as a startup argument.

Example    

 

public TreeModelDemo()

  {

    super(new String[]{

      "-title", "Tree Model Demo",

      "-style", "data/tree.css",

    });

  }

The style sheet specifies a Tree layout in Radial mode with various parameters, in the two rules shown in the following code example.

Example    

 

SDM {

   GraphLayout : "Tree" ;

}

 

GraphLayout {

   flowDirection : "Bottom";

   layoutMode : "RADIAL";

   globalLinkStyle : "ORTHOGONAL_STYLE";

   position : "300,200";

   parentChildOffset : "10";

   siblingOffset : "10";

}

The style sheet also specifies the colors of the various objects.

Note that the CSSclass property of the TreeSDMNode class is recognized automatically by the CSS engine as specifying a CSS class because of its name, and therefore the values of this attribute can be used directly in rules. This allows you to set colors at the level of types of object with a simple syntax, see the following code example.

Example    

 

node.food {

  fillColor2 : "lightgreen" ;

  }

 

// node.treenode[userObject='food'] node.treenode {

// fillColor2 : "lightgreen" ;

// }

The comment lines show the alternative, longer way to set the color for food objects. This longer way relies on a parent-child construct in CSS for Java. Note that the parent-child construct is not supported in the Designer.