An Oracle blog about Data Visualizations

  • July 14, 2014

A Guide to Diagram – Part 9 – Attribute Groups and Node Stacking

Duncan Mills
In Part 8 of this series I showed how nodes could be grouped together inside of a container node. This can provide a very effective way of organizing your diagram to allow progressive disclosure of large amounts of data and of course it is a very good way to plot hierarchical data sets. In some data sets though, you have large numbers of nodes at the same level from a hierarchical perspective, but would like to be able to selectively filter or otherwise distinguish between sets of nodes.  This is where attribute groups come in.

Understanding Attribute Groups 

Attribute groups are a way of varying the look of nodes of the same type based on some underlying property of the node contents. Effectively this allows you to group nodes with a shared property value in a visual manner without having to write complex expression language or define multiple node definitions. 
As an example, I've made a slight change to the Node definition that this series has been using to add a status attribute to the nodes and this will have one of three values "Planned", "In Progress" or "Complete",
I can then use an attribute group to categorize the nodes on the diagram using that property as the grouping factor. (I've reverted to the flat node model with just 5 per nodes here)
Diagram using attributeGroups to color nodes
And here's the modified diagramNode definition:
<dvt:diagramNodes id="dns1" 
  <dvt:diagramNode id="dn1" 
    <f:facet name="zoom100">
      <dvt:marker id="nodeMarker" 
                  height="80" width="80" 
        <dvt:attributeGroups id="statusGroup" 
Notice the following about this version of the code:
  1. I've removed the fillColor from the marker, this is now provided by the attributeGroup
  2. The status attribute of the node is passed as the value of the attributeGroup, this is the grouping value.  (I also set the label attribute as well which we'll discuss in a moment) 
As well as varying by color you can also vary the fill pattern, x scaling and y scaling or even several attributes together using a space delimited list type="color pattern":
VArying color and pattern with an attribute group

Controlling the Assignments

You'll notice that when I varied the color (and indeed the pattern), nowhere did I specify the "pool" of color options to be used or the order.  The default behavior here is actually defined in the skin being used (see the tagdoc on <dvt:attributeGroups> for that ).  You can, however, explicitly control things within a specific diagram, using the <dvt:attributeMatchRule> and <dvt:attributeExceptionRule> tags.  Using the match rule I can assign specific colors to each different value for status:
<dvt:marker id="nodeMarker" 
            height="80" width="80" shape="circle" 
            borderColor="#000000" borderStyle="solid" borderWidth="1.0">
  <dvt:attributeGroups id="statusGroup" 
    <dvt:attributeMatchRule id="statPln" group="Pending">
      <f:attribute name="color" value="red"/>
    <dvt:attributeMatchRule id="statIn" group="In Progress">
      <f:attribute name="color" value="yellow"/>
    <dvt:attributeMatchRule id="statComp" group="Complete">
      <f:attribute name="color" value="green"/>
This results in the control I need:
Specific colors assigned with attribute match rules
The <dvt:attributeExceptionRule> tag can be used in a similar way except rather than explicitly matching a value, it takes an expression in its condition property that can be evaluated using information from the current node to apply the property or not.

Using the Legend

One advantage of using attributeGroups for node formatting is that also integrates the diagram into the  <dvt:legend> component.  The legend appears in the top right of the diagram, optionally as a slide-out box, although it can be fixed as well shoudl you desire:
Diagram Legend
The legend is nested within the <dvt:diagram> tag thus:
<dvt:legend disclosed="false" 
  <dvt:showLegendGroup label="Current Status">
    <dvt:legendSection source="dns1:statusGroup"/>
The source attribute on the legendSection points to the relative id of the attributeGroups tag.  When the legendSection is rendered the label used for each entry corresponds to the label property defined within the attributeGroups tag.

Functionality Added by the Legend   

The legend not only provides a visual key for the diagram, but can also be used as a filter to control the display of whole groups of nodes at once.  The user can click on the entry inside of the legend to toggle the display of that class or group of nodes. Here I've filtered the diagram to hide the nodes marked as "Completed":
Filtered diagram
As you hide or display groups of nodes using the Legend, the diagram will animate in an appropriate fashion.
Note that if you want to add this kind of filtering functionality to the diagram, then your layouts will need to be fairly forgiving and be able to cope with nodes being hidden and displayed. 

Stacking Nodes

A final feature of nodes that use attributeGroups is that you can use the grouping to "stack" all the nodes of the same type into a pile.  Such a pile (from a different diagram) would look like this:
Stacked nodes
The number 16 overlaid on top of the node indicates how many nodes are in the "stack".
When you have a stack of nodes like this, you can either preview the contents of the stack using the preview icon that appears when you select the stack:
Stack Preview icon
This will pop an overlay on top of the current diagram with a simple folder-style (you have no control of the layout) view of the nodes in the stack:
Preview of stacked nodes
Or, you can also select the unstack option:
Stack explode or unstack option icon
To un-stack the nodes into the diagram itself.  Naturally you can re-stack in a similar way.

Enabling Stacking

In order to use node stacking, you do of course need to be using attributeGroups, but in addition to this you need to reference the id of the attributeGroup that you want to use to stack by using the groupBy property on the <dvt:diagramNodes> tag.  The diagram will initially display with the nodes stacked. 

Design Considerations when using Stacking

Be aware of the following minor points:
  1. You have no control of the actual stacking order.  Generally the first node within the nodes collection that represents a particular group will be the one displayed on the top of the stack, but you have no explicit control over this other than that ordering. 
  2. When links are rendered between stacks on the diagram they essentially represent a union of all the defined links between individual nodes within those stacks.  As a result your layout will be passed generated "summary" links which will not, for example, have any label information (as that would make no sense).  Therefore any layout code that may be used in a stacked node scenario should be prepared for a null result from any call to getLabelBounds() on the link. Code defensively in your layout code for this scenario.  

In the Next Article

Now that we have covered most of the visual and layout aspects of diagram it's time to look how your diagram can be decorated with a little interactivity.  I'll start off in the next article which will talk about the definition of pop-ups on various artifacts within the diagram.

Join the discussion

Comments ( 2 )
  • Lucas Jellema Sunday, July 27, 2014

    hi Duncan,

    Great series. I am anxious to read new installments on events and interactivity and on animation & push/poll based refresh. Can we have the diagram built in an animation - adding selected elements every few seconds for example?

    Warm regards


  • jerome Wednesday, August 20, 2014

    Hi Duncan,

    thanks for this guide, very helpful and one question:

    Is ADF planning on providing some predefined javascript layout algorithms (force directed graph layout, ...) out of the box or should each user implement them from scratch as you explained in this guide?



Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.