Creating custom-rendered nodes

Class: NodeRendererTutorial

This tutorial shows how to customize the look of the nodes based on the semantic properties of the
nodes. It creates a graph which has a bunch of nodes with user objects of different types, and renders these nodes according to their types. The rendering looks like this:

First we set up a default renderer which is necessary to catch a type of node that does not have a specific renderer associated with it. If you wanted to disallow such nodes, you might have the default renderer throw a RuntimeException.

        NodeRenderer defaultRenderer =
            new BasicNodeRenderer(new Ellipse2D.Double(0.0,0.0,40.0,40.0),
                    new Ellipse2D.Double(0.0,0.0,600.0,600.0), Color.gray, Color.gray, .3);

The arguments are the single node shape, the composite node shape, the single-node color, the composite node color, and the scaling factor by which composite nodes shrink their contents.

We do the same for strings, integers, and sets.

        NodeRenderer stringRenderer =
            new BasicNodeRenderer(new Ellipse2D.Double(0.0,0.0,40.0,40.0),
                    new Ellipse2D.Double(0.0,0.0,600.0,600.0), Color.blue, Color.blue, .3);
        NodeRenderer integerRenderer =
            new BasicNodeRenderer(new Rectangle2D.Double(0.0,0.0,40.0,40.0), 
                    new Rectangle2D.Double(0.0,0.0,600.0,600.0), Color.orange, Color.orange, .3);
        NodeRenderer setRenderer =
            new BasicNodeRenderer(new Ellipse2D.Double(0.0,0.0,40.0,40.0),
                    new Ellipse2D.Double(0.0,0.0,600.0,600.0), Color.red, Color.red, .3);

Next, we instantiate a typed node renderer, which is sort of like a registry. We register each renderer with its corresponding node type. At first I tried to register "setRenderer" with "Set.class", but unfortunately this imperfect solution doesn't provide for inherited rendering style with class inheritence. Maybe in a later version.

        TypedNodeRenderer typedRenderer = new TypedNodeRenderer(defaultRenderer);
        typedRenderer.addTypedRenderer(Integer.class, integerRenderer);
        typedRenderer.addTypedRenderer(ArrayList.class, setRenderer);
        typedRenderer.addTypedRenderer(String.class, stringRenderer);

Finally, we set the renderer in the graph view, and we're set.

        JGraph g = new JGraph();
        g.getGraphPane().getGraphView().setNodeRenderer(typedRenderer); // <=== HERE!