UIX Developer's Guide
Go to Table of Contents
Contents
Go to previous page
Previous
Go to next page
Next

11. Data Trees

The TreeBean, BrowseMenuBeanand HGridBeanallow users to browse through complex sets of hierarchical data. This chapter examines these three beans and provide extensive examples on how to use them.

This chapter contains the following sections:

Tree Structured Data

Some data is naturally tree structured. Consider, for example, the categories, subcategories and items in a shopping application. Let's start with an example of a small tree of data. The top node is "Shop," and under it are the nodes "Books" and "Hardware," which contain their own subnodes.

Figure 15-1: Hierarchical Tree

Diagram of hierarchical "Shop" tree

So what does a tree of data look like in UIX? Let's look at how to build such a tree in uiXML. Each node in the tree is a DataObjectcontaining key-value pairs. We will often refer to a node by the value associated with the 'text' key. So we will refer to the root of the tree below as the "Shop" node. Note that uiXML has some special syntax for creating a value that is a DataObjectList. In the example below a node queried with the key 'nodes' will return a DataObjectListcontaining its children. So for example when the "Shop" node is queried with the 'nodes' key a DataObjectListcontaining the nodes "Books" and "Hardware" is returned.

Each DataObjectin the tree may contain any set of key-value pairs. We shall see a little later that certain keys have special meaning. For now let's take the example above and write it in uiXML, with the addition of some seemingly arbitrary key-value pairs.

<nodes text="Shop"
               destination="http://www.oracle.com"
               destinationText="More Information"
               expandable="expanded">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 destinationText="More Information"
                 description="Instructions: buy, buy, buy!"
                 expandable="expanded">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com"/>
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded" >
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>

The TreeBeanand BrowseMenuBeanare the UIX Components designed to view such tree-structured data. In fact these two beans can show two different views of the same data source. Let's look at an example of how each bean displays the same data. First let's look at an image of how the above data is viewed in a TreeBean.

Figure 15-2: Hierarchical Tree Rendered in a Browser

The "Shop" tree rendered as a graphical tree control in a browser

Now let's look at an image of the same data displayed in a BrowseMenuBeanwhen the user is looking at the "Books" node.

Figure 15-3: Hierarchical Tree Rendered as Phrases in a Browser

The "Shop" tree rendered as a hierarchy of phrases in a browser

Both beans allow the user to navigate through the tree hierarchy. The hierarchy of the data as displayed by the TreeBeanshould be fairly obvious. In the BrowseMenuBeanthe entire hierarchy is not seen, however the user can see the path from the root to the current node in the breadcrumbs at the top. The user can also see the children of the current node as links under the "Categories" and "Items" headers. Links under the "Categories" header are non-leaf nodes, while links under the "Items" header are leaf nodes. Thus when we are looking at the "Books" node we see that the path from the root is "Shop> Books". We also see that the children of "Books" are "Sale", "Fiction", and "Nonfiction" and that the nodes "Fiction" and "Nonfiction" are leaves, while the "Sale" node is not a leaf. Clicking on the links in the breadcrumbs or the links under the header "Categories" should bring the user to a similar page. For example if we clicked on the link that says "Sale" we should see a similar page with the breadcrumbs "Shop> Books> Sale" at the top and the link "Paperbacks" under the "Items" header. Later we will see an interactive version of this example.

Looking at the data we see that in the "Books" node the value associated with the 'description' key is "Instructions: buy, buy, buy!". Looking at the images we see that this text is displayed by the BrowseMenuBeanbut not by the TreeBean. Indeed, the TreeBeanignores the value for the 'description' key. Similarly the BrowseMenuBeanignores the value associated with the 'expandable' key, while the TreeBeanuses this information to determine whether the children of a node should be displayed. We will discuss the exact keys expected by both beans extensively in later sections.

The TreeBean

We will begin with a discussion of the TreeBean.

Children and Attributes

The TreeBeansupports the following named child:

uiXML Key UIConstant Description
nodeStamp NODE_STAMP_CHILD

Bean to render once for each DataObjectin the tree of data.

The TreeBeansupports the following attributes:

uiXML Key UIConstant Type Description
id ID_ATTR String

A page-wide unique id.

formName FORM_NAME_ATTR String

The name of the form to submit.

formSubmitted FORM_SUBMITTED_ATTR Boolean

Whether or not to use form submission. Form submission is not the default, thus if form submission is desired then this attribute must be explicitly set to true.

The TreeBeansupports the following children which have a special attribute syntax. When used with the attribute syntax they must be databound.

uiXML Key UIConstant Type Description
nodes NODES_ATTR DataObjectList

The tree of data. This DataObjectListindicates all of the "root", or top level nodes.

proxy PROXY_ATTR TreeDataProxy

The proxy keeps track of the expanded/collapsed state of the tree by setting up the expand and collapse destinations. It optionally tracks the currently selected node in the tree.

Let's start with a look at the most basic tree.

In this example and those that follow some of the actual UIX is left out in order to focus attention on the issue at hand, however the examples themselves have a link to view the full source.

<tree/>

This example is so basic you don't see a thing. In it, we've only declared that we want to show a tree element, however in order to display something we need to add some data.

Tree Data

The tree data is set with the NODESattribute. Not surprisingly, the data for a TreeBeanis itself in tree form. The nodes in this tree of data are DataObjects. Each DataObjectis expected to store certain data at specific keys. The following table describes the key-value pairs expected in each DataObject.

uiXML Key UIConstant Type Description
text TEXT_KEY String

The text displayed for the node.

icon ICON_KEY String

The URI of the icon to display for the node. The image file should be 16 pixels wide and 22 pixels high. The defaults are that no icon is rendered for leaf nodes, and a default folder icon is rendered for nodes with children.

selected SELECTED_KEY Boolean

This is set to true for nodes to be drawn as selected.

destination DESTINATION_KEY String

The URI to go to when the text is clicked.

targetFrame TARGET_FRAME_KEY String

The target frame for the destination.

expandable EXPANDABLE_KEY String

Used to determine if node is expanded, collapsed, or leaf. The possible values are:

  • "expanded"- node is rendered as "open", meaning the children are displayed.
  • "collapsed"- node is rendered as having children which are currently hidden.
  • "no"- node is rendered as leaf.
collapseDestination COLLAPSE_DESTINATION_KEY String

The URI used to collapse the node when it's currently expanded.

expandDestination EXPAND_DESTINATION_KEY String

The URI used to expand the node when it's currently collapsed.

nodes NODES_KEY DataObjectList

The children of the node.

So let's take a look at an example which adds some data.

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
 <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" />
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
       <nodes text="Shop"
               destination="http://www.oracle.com"
               expandable="expanded">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="collapsed">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="collapsed">
             <nodes text="Paperbacks"
                     expandable="no"
                     destination="http://www.oracle.com" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"
                   expandable="no"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"
                   expandable="no"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="collapsed">
           <nodes text="Desktops"
                   destination="http://www.oracle.com"
                   expandable="no"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

The example above should start to clarify the link between the key-value pairs on the DataObjects and how these are displayed by the tree. The value returned by the "text"key is displayed as the text for the node. The nodes "Shop" and "Books" are links because we have set a value for the "destination"key, while we have not done so for "Hardware" and so this node is therefore not clickable. The value returned by the "expandable"key determines whether or not the children are visible. Thus the children of "Shop" are visible while those for "Books" are not.

You might wonder why nothing happens when you click on the plus and minus icons. The TreeBeanitself only renders the tree as indicated by the key-value pairs on each DataObject, it does not handle making the tree interactive. Remember, the TreeBeanis a UIX Component; it is meant to take its children and attributes and output the appropriate content for one render, or one pass through the bean. To make it interactive we need something to handle the flow from one state to another. This can be accomplished with the UIX Controller, for example, or a servlet that you write. We have provided a class to simplify making the tree interactive, which will be discussed below. First, however, we will discuss how to influence the way the tree looks.

Now let's change a few "collapsed" values to "expanded" and look at the difference.

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
   <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" />
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
       <nodes text="Shop"
               destination="http://www.oracle.com"
               expandable="expanded">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="expanded">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded">
             <nodes text="Paperbacks"
                     expandable="no"
                     destination="http://www.oracle.com" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"
                   expandable="no"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"
                   expandable="no"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded">
           <nodes text="Desktops"
                   destination="http://www.oracle.com"
                   expandable="no"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"
                   expandable="no"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

Note that the default is expanded="no" so you can leave off this key-value pair for leaves. If you leave it off for non-leaf items or put "no" as the value then the icon indicating +/- is missing. Note that on the "Shop" node there is no expandable key and the icon is removed. Note also that the "Hardware" node has the "expandable" key set to "no" despite it's not being a leaf, and the icon is removed.

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
 <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" />
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
        <!-- "expandable" key removed -->
       <nodes text="Shop"
               destination="http://www.oracle.com" >
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="expanded">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
          <!-- "expandable" changed to "no" -->
         <nodes text="Hardware"
                 expandable="no" >
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

You can also set nodes to look selected by setting the value for the "selected"key to true. In the following example "Shop" and "Sale" are highlighted with a blue background and white text.

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
 <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" />
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
       <nodes text="Shop"
               destination="http://www.oracle.com"
               expandable="expanded"
               selected="true">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="expanded">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded"
                   selected="true">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded" >
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

By default nodes with children will render with a folder icon. You can add icons to leaves or replace the folder icon by setting the value for the "icon"key to the URI of another image. Let's look at an example:

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
 <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" />
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
       <nodes text="Shop"
               destination="http://www.oracle.com"
               expandable="expanded"
               icon="/docs/devguide/images/data_trees/info.gif">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="expanded"
                 icon="/docs/devguide/images/data_trees/info.gif">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded"
                   icon="/docs/devguide/images/data_trees/info.gif">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded"
                 icon="/docs/devguide/images/data_trees/info.gif">
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

Node Stamp

By default a link is displayed for each node in the tree, but setting the "nodeStamp"allows you more control over what is displayed. The "nodeStamp"is a named child of the TreeBean.

What is a stamp? A stamp is just a UINode -- any UINode -- that is rendered more than once on a given page. In the tree there is one stamp and this stamp is repeated, or rendered once for each node in the tree. This means each node looks similar, but can have different data through data binding. The following example uses a node stamp. Notice that we can add arbitrary key-value pairs into the DataObjects in the tree and then use data binding to extract these values.

<dataScope xmlns="http://xmlns.oracle.com/uix/ui"
           xmlns:data="http://xmlns.oracle.com/uix/ui"
           xmlns:ctrl="http://xmlns.oracle.com/uix/controller" >
 <contents>

   <!-- UIX Components -->
   <form name="myForm" >
     <contents>
       <tree data:nodes="nodes@data:Nodes" >
         <nodeStamp>
           <flowLayout>
             <contents>
               <checkBox data:rendered="rendered"
                          data:disabled="disabled"
                          data:checked="checked"/>
               <styledText data:text="text" />
             </contents>
           </flowLayout>
         </nodeStamp>
       </tree>
     </contents>
   </form>
 </contents>

 <!-- Data -->
 <provider>
   <data name="data:Nodes">
     <inline>
       <nodes text="Shop"
               destination="http://www.oracle.com"
               expandable="expanded"
               rendered="false" 
               icon="/docs/devguide/images/data_trees/info.gif">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 expandable="expanded"
                 rendered="false"
                 icon="/docs/devguide/images/data_trees/info.gif">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded"
                   rendered="false"
                   icon="/docs/devguide/images/data_trees/info.gif">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com"
                     disabled="true" />
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"
                   checked="true"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded"
                 rendered="false"
                 icon="/docs/devguide/images/data_trees/info.gif">
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>
     </inline>
   </data>

 </provider>
</dataScope>

Warning iconNote that the height of the nodes cannot be arbitrarily large. Currently each node can be about 45 pixels high.

Tree Proxy

Now let's make the tree interactive. When a node is in the collapsed state, the value associated with the "expandDestination"key is used as the destination to expand the node. When a node is in the expanded state, the value associated with the "collapseDestination"key is used as the destination to collapse the node. Users setting these destinations themselves must keep track of the state of the tree, in other words which nodes are expanded/collapsed and which are selected.

In order to simplify using the tree, we have provided the class ClientStateTreeDataProxy. This proxy keeps track of the expanded/collapsed state of the tree by setting up the expand and collapse destinations. The proxy to be used is set using the "proxy"attribute.

When using the ClientStateTreeDataProxythe state of the tree is kept on the client. The proxy sets the expand/collapse destinations such that the following name-value pairs are sent to the server when a node is expanded or collapsed.

The value of 'event' is the name of a UIX Controller event. Note that the value is 'expand' whether or not a node is being expanded or collapsed.

The value of 'source' is the value set for the IDattribute. We have not yet used the IDattribute but we will include it in the next example.

The values associated with 'node', 'state', and 'selection' are used at the server to create a new proxy. Users do not need to worry about what these values actually are, they must only ask for the values and pass these values to the ClientStateTreeDataProxyconstructor. The example below should clarify this process.

If you set up the tree with the proper state and then use the ClientStateTreeDataProxyconstructor that takes null for the tree state, the proxy will attempt to pull the expanded/collapsed state from the node data. So, to have a tree opened up to a specific node by default, you need only set the nodes along the path to the root to be expanded. Again, the following examples should clarify how to use ClientStateTreeDataProxy.

This example requires Java code. The Java follows the UIX example.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui">

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->
           <form name="myForm" >
             <contents>
               <tree id="tree"
                  formSubmitted="true"
                  data:nodes="nodes@data:Nodes"
                  data:proxy="proxy@TreeProxy"/>
             </contents>
           </form>
         </contents>

         <!-- Data -->
         <provider>

           <data name="TreeProxy">
             <method class="oracle.cabo.doc.demo.DataTrees"
                      method="getTreeProxy"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com" />
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded">
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
  <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="expand">
     <method class="oracle.cabo.doc.demo.DataTrees"
        method="expandEventHandler"/>
   </event>

 </ctrl:handlers>
</ctrl:page>

The following are the two methods in bold above. All subsequent TreeBeanexamples use these same methods. The first method is the getTreeProxymethod which returns a DataObjectthat returns a proxy.

public static DataObject getTreeProxy(
  RenderingContext rc,
  String ns,
  String name)
  {
    return new TreeProxyDataObject(null);
  }

  private static class TreeProxyDataObject implements DataObject
  {
        public TreeProxyDataObject(
            String submitURL
          )
        {
          _submitURL = submitURL;
        }

        public Object selectValue(
            RenderingContext rc,
            Object key
          )
        {
          BajaContext bc = BajaRenderingContext.getBajaContext(rc);
          EventResult result = EventResult.getEventResult(bc);
          Object proxy = (result==null) ? null : result.getProperty("proxy");
          if (proxy==null)
            proxy =  new ClientStateTreeDataProxy( _submitURL, null, null, null);

          return proxy;
        }

        String _submitURL;
  }

The expandEventHandlermethod handles 'expand' events when they are generated. Note in expandEventHandleryou just pass the values associated with the parameters 'state' (UIConstants.STATE_PARAM), 'node' (UIConstants.NODE_PARAM), and 'selection' (UIConstants.SELECTION_PARAM)to a new ClientStateTreeProxy. This new proxy is set as a property on the context and is subsequently returned by the TreeProxyDataObjectcreated in the method above.

public static EventResult expandEventHandler(
    BajaContext context,
    Page page,
    PageEvent event )throws Throwable
  {
    String state = event.getParameter(UIConstants.STATE_PARAM);
    String node = event.getParameter(UIConstants.NODE_PARAM);
    String selection = event.getParameter(UIConstants.SELECTION_PARAM);
    EventResult result = new EventResult(page);
    Object proxy = new ClientStateTreeDataProxy(null, state, node, selection);
    result.setProperty("proxy", proxy);
    return result;
  }

Selection will be handled by the proxy if the constructor that takes a selection parameter is used. Currently the proxy only supports single selection. A node will remain selected (until a new selection is made) even if it is not visible. The selection state is handled through an onClick handler. Let's look at an example that uses a node stamp. Notice that the background and text change color as a node's check box is clicked.

Warning iconSELECTION IS NOT AVAILABLE ON NETSCAPE WHEN USING A PROXY.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui"
  xmlns:html="http://www.w3.org/TR/REC-html40">

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->
           <form name="myForm" >
             <contents>
               <tree id="tree"
                  formSubmitted="true"
                  data:nodes="nodes@data:Nodes"
                  data:proxy="proxy@TreeProxy">
                 <nodeStamp>
                   <flowLayout>
                     <contents>
                       <checkBox data:rendered="rendered"
                                  data:disabled="disabled"
                                  data:checked="checked"/>
                       <link data:destination="destination" data:text="text" />
                     </contents>
                   </flowLayout>
                 </nodeStamp>
               </tree>
             </contents>
           </form>
         </contents>

         <!-- Data -->
         <provider>

           <data name="TreeProxy">
             <method class="oracle.cabo.doc.demo.DataTrees"
                      method="getTreeProxy"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       expandable="expanded"
                       rendered="false"
                       icon="/docs/devguide/images/data_trees/info.gif" >
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         expandable="expanded"
                         rendered="false"
                         icon="/docs/devguide/images/data_trees/info.gif" >
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded"
                           rendered="false"
                           icon="/docs/devguide/images/data_trees/info.gif">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"
                             disabled="true" />
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"
                           checked="true"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded"
                         rendered="false"
                         icon="/docs/devguide/images/data_trees/info.gif" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="expand">
     <method class="oracle.cabo.doc.demo.DataTrees"
        method="expandEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

Trees and Frames

Many developers will want to use frames with the TreeBean. The following is an example of how to do just that. This involves three uiXML files. The first sets up the frames.

<page xmlns="http://xmlns.oracle.com/uix/controller"
      xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
      xmlns:data="http://xmlns.oracle.com/uix/ui"
      xmlns:http="http://www.w3.org/TR/REC-html40">
 <content>

   <frameBorderLayout  xmlns="http://xmlns.oracle.com/uix/ui" >

    <left>
     <frame source="B-2-11.uix" name="tree" width="30%" />
    </left>

    <center>
     <frame source="B-2-12.uix" name="contents" />
    </center>

   </frameBorderLayout>

 </content>
</page>

The next is the tree itself with some new destinations and the addition of the "targetFrame"key which specifies the frame to direct the content to.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui"
  xmlns:html="http://www.w3.org/TR/REC-html40">

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>
      <!-- UIX Components -->
           <form name="myForm" >
             <contents>
               <tree id="tree"
                  formSubmitted="true"
                  data:nodes="nodes@data:Nodes"
                  data:proxy="proxy@TreeProxy"/>
             </contents>
           </form>
         </contents>

         <provider>

           <!-- Data -->
           <data name="TreeProxy">
             <method class="oracle.cabo.doc.demo.DataTrees"
                      method="getTreeProxy"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://otn.oracle.com/index.html"
                       targetFrame="contents"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.osborne.com/oracle/"
                         targetFrame="contents"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           targetFrame="contents"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com/appsnet/"
                             targetFrame="contents"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com/oramag/"
                           targetFrame="contents"/>
                   <nodes text="Nonfiction"
                           destination="http://otn.oracle.com/support/content.html"
                           targetFrame="contents"/>
                 </nodes>

                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://otn.oracle.com/training/content.html"
                           targetFrame="contents"/>
                   <nodes text="Notebooks"
                           destination="http://otn.oracle.com/tech/content.html"
                           targetFrame="contents"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="expand">
     <method class="oracle.cabo.doc.demo.DataTrees"
        method="expandEventHandler"/>
   </event>

 </ctrl:handlers>
</ctrl:page>

The last is an empty uiXML file.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui"
  xmlns:html="http://www.w3.org/TR/REC-html40"/>

The BrowseMenuBean

The BrowseMenuBeanprovides another way to view hierarchical or tree-structured data.

Named Children and Attributes

The BrowseMenuBeansupports four named children:

uiXML Key UIConstant Description
location LOCATION_CHILD

Bean to use to render locator element on top of BrowseMenu.

contentLink CONTENT_LINK_CHILD

Bean to use to link to content of the current category.

categories CATEGORIES_CHILD

Bean to use to render categories.

items ITEMS_CHILD

Bean to use to render items.

The BrowseMenuBeanis essentially a layout manager which places these named children at the appropriate locations. The Browser Look and Feel (BLAF) guidelines show a BreadCrumbsBeanas the location element, a LinkBeanas the content link element, a BulletedListBeanto display categories and another BulletedListBeanto display items.

The BrowseMenuBeansupports the following attributes:

uiXML Key UIConstant Type Description
id ID_ATTR String

A page-wide unique id.

title TITLE_ATTR String

Sets the title of the BrowseMenu. This text will be displayed in the top header. If this attribute is not set the default text will be set to "Browse".

categoryTitle CATEGORY_TITLE_ATTR String

Sets the title of the category section. This text will be displayed in the header above the categories. If this attribute is not set the default text will be set to "Categories".

itemTitle ITEM_TITLE_ATTR String

Sets the title of the items section. This text will be displayed in the header above the items. If this attribute is not set the default text will be set to "Items".

longDesc LONG_DESC_ATTR String

Sets the description seen just under the title to describe the current location. If this attribute is not set the default text will be set to the empty string.

formName FORM_NAME_ATTR String

The name of the form to submit.

formSubmitted FORM_SUBMITTED_ATTR Boolean

Whether or not to use form submission. Form submission is not the default, thus if form submission is desired then this attribute must be explicitly set to true.

Let's look at an image which may clarify how these named children and attributes are used.

Figure 15-4: Hierarchical Tree Rendered as Phrases in a Browser

"Shop" tree, with callouts identifying named children and attributes

We will start our BrowseMenuBeandiscussion with some simple examples in which everything is hardcoded. We will provide more complicated examples below.

Note that the "View Source" link has been moved to the bottom of the page.

<browseMenu/>

This is the simplest example and all we see is a header with the text "Browse". In order to make this more interesting we need to add data.

First we will add a "categories"child. The categories correspond to tree nodes that have children, or are not leaves.

<browseMenu>
      <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
   </browseMenu>

You might remember that in the introduction we said that when you click on the "Sale" link we should see a similar page with the breadcrumbs "Shop> Books> Sale" at the top and the link "Paperbacks" under the "Items" header, however the sale link in the above example doesn't do this. Like the TreeBean, the BrowseMenuBeanitself does not handle interactivity. Remember, the BrowseMenuBeanis a UIX Component; it is meant to take its children and attributes and output the appropriate content for one render, or one pass through the bean. To make it interactive we need something to handle the flow from one state to another. This can be accomplished with the UIX Controller, for example, or a servlet that you write. We have provided a class to simplify making the BrowseMenuBeaninteractive, which will be discussed below. First, however, we will discuss how to influence the way the BrowseMenuBeanlooks.

To continue we will add an "items"child. The items correspond to leaves in the tree.

<browseMenu>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
      <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

Now we will add a "location"child. This helps orient the user as to their location in the tree.

<browseMenu>
      <location>
       <breadCrumbs>
         <contents>
           <link text="Shop" destination="http://www.oracle.com"/>
           <link text="Books" destination="http://www.oracle.com"/>
         </contents>
       </breadCrumbs>
     </location>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
     <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

Finally we will add a "contentLink"child. The content link allows the user to access additional information/instructions.

<browseMenu>
     <location>
       <breadCrumbs>
         <contents>
           <link text="Shop" destination="http://www.oracle.com"/>
           <link text="Books" destination="http://www.oracle.com"/>
         </contents>
       </breadCrumbs>
     </location>
      <contentLink>
       <link text="More Information" destination="http://www.oracle.com"/>
     </contentLink>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
     <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

Now that we've seen the basic layout of the BrowseMenu let's take a look at the attributes.

First we will set the "title"attribute, changing the title from "Browse" to "Books".

<browseMenu title="Books">
     <location>
       <breadCrumbs>
         <contents>
           <link text="Shop" destination="http://www.oracle.com"/>
           <link text="Books" destination="http://www.oracle.com"/>
         </contents>
       </breadCrumbs>
     </location>
     <contentLink>
       <link text="More Information" destination="http://www.oracle.com"/>
     </contentLink>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
     <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

Next we will set the "categoryTitle"attribute, changing the text from "Categories" to "Have Subcategories". We will also set the "itemTitle"attribute, changing the text from "Items" to "No Subcategories".

<browseMenu title="Books"
                categoryTitle="Have Subcategories"
                itemTitle="No Subcategories">
     <location>
       <breadCrumbs>
         <contents>
           <link text="Shop" destination="http://www.oracle.com"/>
           <link text="Books" destination="http://www.oracle.com"/>
         </contents>
       </breadCrumbs>
     </location>
     <contentLink>
       <link text="More Information" destination="http://www.oracle.com"/>
     </contentLink>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
     <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

Now we will set the "longDesc"attribute. This area can be used for descriptions or instructions.

<browseMenu title="Books"
                categoryTitle="Have Subcategories"
                itemTitle="No Subcategories"
                longDesc="Instructions: buy, buy, buy!">
     <location>
       <breadCrumbs>
         <contents>
           <link text="Shop" destination="http://www.oracle.com"/>
           <link text="Books" destination="http://www.oracle.com"/>
         </contents>
       </breadCrumbs>
     </location>
     <contentLink>
       <link text="More Information" destination="http://www.oracle.com"/>
     </contentLink>
     <categories>
       <bulletedList rows="10">
         <contents>
           <link text="Sale" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </categories>
     <items>
       <bulletedList rows="10">
         <contents>
           <link text="Fiction" destination="http://www.oracle.com"/>
           <link text="Nonfiction" destination="http://www.oracle.com"/>
         </contents>
       </bulletedList>
     </items>
   </browseMenu>

There are two final attributes, "formSubmitted"and "formName". We will see the application of these attributes below.

So what happened to our tree-structured data? The next section discusses how to use a BrowseMenuBeanwith tree-structured data.

BrowseNodeDataObject

While the purpose of the BrowseMenuBeanis to allow users to browse through complex sets of hierarchical objects, the hierarchical data isn't added to the BrowseMenu itself as it is for the TreeBean. In fact the BrowseMenuBeanexpects the named children and attributes to contain all the appropriate data. We provide a class to make binding this data relatively simple. BrowseNodeDataObjecttakes a tree of DataObjects and a current location and extracts the appropriate information. The "tree of DataObjects" part should sound familiar. In fact an instance of BrowseNodeDataObjectcan take the same tree of data used by a TreeBean.

BrowseNodeDataObjectexpects the nodes in the tree to use the following keys.

uiXML Key UIConstant Type Description
text TEXT_KEY String

The text for the node.

destination DESTINATION_KEY String

The URI for a link.

destinationText DESTINATION_TEXT_KEY String

The text for a link.

description DESCRIPTION_KEY String

A description or instruction.

nodes NODES_KEY DataObjectList

The children of the node.

Again, this should be familiar. There are two new keys. The value associated with the "description"key is intended to map to the value of the "longDesc"attribute.

The value of the "destinationText"key is intended to be the text for the "contentLink"child. In the TreeBeanif a node has a destination it can be displayed as a link, even if the node has children. For example looking at a tree example if we click on the text "Books" it is a link. In the BrowseMenu the text "Books" is in a header, and is not clickable. Thus a separate link is needed and this is the purpose of the "contentLink"child.

Let's look at an updated version of the tree of data that uses these keys. Notice that it is fine for a DataObjectto include key-value pairs not needed by the BrowseMenu. For example, the BrowseMenu will ignore the "expanded"key and its associated value.

<nodes text="Shop"
               destination="http://www.oracle.com"
               destinationText="More Information"
               expandable="expanded">
         <nodes text="Books"
                 destination="http://www.oracle.com"
                 destinationText="More Information"
                 description="Instructions: buy, buy, buy!"
                 expandable="expanded">
           <nodes text="Sale"
                   destination="http://www.oracle.com"
                   expandable="expanded">
             <nodes text="Paperbacks"
                     destination="http://www.oracle.com"/>
           </nodes>
           <nodes text="Fiction"
                   destination="http://www.oracle.com"/>
           <nodes text="Nonfiction"
                   destination="http://www.oracle.com"/>
         </nodes>
         <nodes text="Hardware"
                 expandable="expanded" >
           <nodes text="Desktops"
                   destination="http://www.oracle.com"/>
           <nodes text="Notebooks"
                   destination="http://www.oracle.com"/>
         </nodes>
       </nodes>

The BrowseNodeDataObjectconstructor takes a tree of data and the current location in the tree. From that it creates values for the following keys:

uiXML Key Java Key Type Description
locationData BrowseNodeDataObject.
LOCATION_DATA_KEY
DataObjectList

The nodes for the location child. These are all the nodes along the path from the root of the tree to the current location node.

categoriesData BrowseNodeDataObject.
CATEGORIES_DATA_KEY
DataObjectList

The nodes for the categories child. These are all the children of the current location data object who have children themselves, or are not leaves in the tree.

itemsData BrowseNodeDataObject.
ITEMS_DATA_KEY
DataObjectList

The nodes for the items child. These are all the children of the current location data object who do not have children themselves, or are leaves in the tree.

renderLocation BrowseNodeDataObject.
RENDER_LOCATION_KEY
Boolean

If the current location node is one of the 'roots' of the tree, this is set to Boolean.FALSEsince the location child should only be seen relative to one of the 'roots'.

renderContentLink BrowseNodeDataObject.
RENDER_CONTENT_LINK_KEY
Boolean

If the current location node is queried with UIConstants.DESTINATION_TEXT_KEYand it returns no value or an empty string then this is set to Boolean.FALSE.

renderCategories BrowseNodeDataObject.
RENDER_CATEGORIES_KEY
Boolean

If the current location node has no children who are categories, or internal nodes in the tree, this is set to Boolean.FALSE.

renderItems BrowseNodeDataObject.
RENDER_ITEMS_KEY
Boolean

If the current location node has no children who are items, or tree leaves, this is set to Boolean.FALSE.

currentState BrowseNodeDataObject.
CURRENT_STATE_KEY
String

The current state of the browse menu as passed in to the constructor.

So let's say the current location being viewed by the user is the "Books" node in the tree above. The keys above would return the following.

The "location" and "categories" data are DataObjectLists where the destination on each DataObjectis retrieved with the key UIConstant.DESTINATION_KEY. The destination is set such that if a location or categories element is pressed the following name-value pairs are returned to the server:

The value of 'event' is the name of a UIX Controller event, which is 'browse' in this case.

The value of 'source' is the value set for the IDattribute. We have not yet used the IDattribute but we will include it in the next example.

The value associated with 'location' is used at the server to create a new BrowseNodeDataObject. Users do not need to worry about what this value is, they must only ask for the value and pass this value to the BrowseNodeDataObjectconstructor. The example below should clarify this process.

Users do have to set up an initial BrowseNodeDataObject, passing in a Stringrepresenting the the location of the node in the tree to view, also referred to as the current location. This Stringis a comma-separated string of zero-based indices. For example if the node requested is the 4th child of the first root node then the value would be "0,3". That's 0 for the first root node and 3 for its fourth child. The location for the 7th child of the 4th child of the first root node would be stored as "0,3,6" and so on. The value of the current location in the initial BrowseNodeDataObjectwould normally be something like "0" or "1", indicating one of the roots of the tree of data. The default is "0" if the current location passed in is null. Again, the example below should clarify.

Let's look at an example of how to use BrowseNodeDataObject. The Java code required by this example follows uiXML example. In this example we have bound the value of the "title"attribute and the data for the "categories"child.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui" >

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->

           <browseMenu id="myBrowseMenu"
                        data:title="text@data:browseData">
             <categories>
               <bulletedList>
                 <contents data:childData="categoriesData@data:browseData">
                   <link data:text="text" data:destination="destination"/>
                 </contents>
               </bulletedList>
             </categories>
           </browseMenu>
         </contents>

         <!-- Data -->
         <provider>

            <data name="data:browseData">
             <method class="oracle.cabo.doc.demo.DataTrees" method="getBrowseNodeDataObject"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       destinationText="More Information"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         destinationText="More Information"
                         description="Instructions: buy, buy, buy!"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
  <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="browse">
     <method class="oracle.cabo.doc.demo.DataTrees" method="browseEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

The following are the java methods that make this interactive. All subsequent BrowseMenuBeanexamples use these same methods. The first method creates an instance of BrowseNodeDataObject, passing in the inline tree of data and the location. The first time this method is called the value of locationis null and the default used is "0", indicating the first root which is the "Shop" node.

public static DataObject getBrowseNodeDataObject(
    RenderingContext context,
    String           namespace,
    String           name
    )
  {
    BajaContext bajaContext = BajaRenderingContext.getBajaContext(context);

    // get location property stored on context
    String location = (String) bajaContext.getProperty("browse", "location");

    // get inline data object
    DataObject data =
         context.getDataObject(UIConstants.MARLIN_NAMESPACE , "Nodes");

    if ( data == null )
      return null;

    // get tree roots
    DataObjectList tree = (DataObjectList) data.selectValue(context, "nodes");

    // if location is null the default of "0" is used
    return new BrowseNodeDataObject( tree, location);
  }

The next method is called when there is a 'browse' event. The value of the 'location' (UIConstants.LOCATION_PARAM)parameter is set as a property on the context. This property is subsequently passed to the BrowseNodeDataObjectconstructor in the method above.

public static EventResult browseEventHandler(
    BajaContext context,
    Page page,
    PageEvent event ) throws Throwable
  {
    String location = event.getParameter( UIConstants.LOCATION_PARAM );

    // set value on context as property
    context.setProperty( "browse", "location", location);

    EventResult result = new EventResult( page );
    return result;
  }

Next we will look at a more complete example of how to use the rest of the keys of BrowseNodeDataObject. A little later we will show you a utility class that simplifies wiring up a BrowseMenuBeanto a BrowseNodeDataObject.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui" >

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->
           <browseMenu id="myBrowseMenu"
                        data:title="text@data:browseData"
                        data:longDesc="description@data:browseData">
             <location>
               <breadCrumbs data:rendered="renderLocation@data:browseData">
                 <contents data:childData="locationData@data:browseData">
                   <link data:text="text" data:destination="destination"/>
                 </contents>
               </breadCrumbs>
             </location>
             <contentLink>
               <link data:text="destinationText@data:browseData"
                      data:destination="destination@data:browseData"
                      data:rendered="renderContentLink@data:browseData"/>
             </contentLink>
             <categories>
               <bulletedList data:rendered="renderCategories@data:browseData">
                 <contents data:childData="categoriesData@data:browseData">
                   <link data:text="text" data:destination="destination"/>
                 </contents>
               </bulletedList>
             </categories>
              <items>
               <bulletedList data:rendered="renderItems@data:browseData">
                 <contents data:childData="itemsData@data:browseData">
                   <link data:text="text" data:destination="destination"/>
                 </contents>
               </bulletedList>
             </items>
           </browseMenu>

         </contents>

         <!-- Data -->
         <provider>

           <data name="data:browseData">
             <method class="oracle.cabo.doc.demo.DataTrees" method="getBrowseNodeDataObject"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       destinationText="More Information"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         destinationText="More Information"
                         description="Instructions: buy, buy, buy!"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="browse">
     <method class="oracle.cabo.doc.demo.DataTrees" method="browseEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

While running the examples you can see the destination for a link in the status bar by resting your mouse over the link. In the previous examples the destinations for the links in the breadcrumbs and under the "Categories" header contain the destination passed in to the BrowseNodeDataObjectconstructor, to which the name-value pairs described above are appended. If the destination is not specified then it defaults to the value returned by the call context.getURLEncoder().getDefaultURL(). An example of this default destination can be seen in the getBrowseNodeDataObjectmethod described above where we use a constructor which takes no destination.

When the BrowseMenu's "formSubmitted"attribute is set to true, then the name-value pairs are returned through form submission. In the following example we will use form submission. Notice that now the destinations for the links in the breadcrumbs and under the "Categories" header call a function to submit the form.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui" >

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->

            <form name="myForm">
             <contents>

               <browseMenu id="myBrowseMenu"
                            data:title="text@data:browseData"
                            data:longDesc="description@data:browseData"
                            formSubmitted="true"
                            formName="myForm">
                 <location>
                   <breadCrumbs data:rendered="renderLocation@data:browseData">
                     <contents data:childData="locationData@data:browseData">
                       <link data:text="text" data:destination="destination"/>
                     </contents>
                   </breadCrumbs>
                 </location>
                 <contentLink>
                   <link data:text="destinationText@data:browseData"
                          data:destination="destination@data:browseData"
                          data:rendered="renderContentLink@data:browseData"/>
                 </contentLink>
                 <categories>
                   <bulletedList data:rendered="renderCategories@data:browseData">
                     <contents data:childData="categoriesData@data:browseData">
                       <link data:text="text" data:destination="destination"/>
                     </contents>
                   </bulletedList>
                 </categories>
                 <items>
                   <bulletedList data:rendered="renderItems@data:browseData">
                     <contents data:childData="itemsData@data:browseData">
                       <link data:text="text" data:destination="destination"/>
                     </contents>
                   </bulletedList>
                 </items>
               </browseMenu>

              </contents>
           </form>

         </contents>

         <!-- Data -->
         <provider>

           <data name="data:browseData">
             <method class="oracle.cabo.doc.demo.DataTrees" method="getBrowseNodeDataObject"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       destinationText="More Information"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         destinationText="More Information"
                         description="Instructions: buy, buy, buy!"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="browse">
     <method class="oracle.cabo.doc.demo.DataTrees" method="browseEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

BrowseMenuUtils

BrowseMenuUtilsis a utility class which contains a method to set up a BrowseMenuBeanto comply to BLAF, with breadCrumbs for the location element, a bulletedList of links for the items, and so on. In Java you might write code looking something like:

// create the browse menu
BrowseMenuBean browseMenu = new BrowseMenuBean();

// give it page-wide unique id - sent as value of 'source' parameter
browseMenu.setID("myBrowseMenu");

// not using form submission
browseMenu.setFormSubmitted(false);

// add the "default" containers
BrowseMenuUtils.configureBrowseMenu(NAMESPACEURI,  LOCALNAME, browseMenu);

Where NAMESPACEURIand LOCALNAMEare the namespace and name of the DataObject, most likely the BrowseNodeDataObject, to which the data is bound.

In uiXML this functionality can be accessed with two additional attributes. The "defaultContents"attribute indicates that the BrowseMenu should use the BLAF defaults, in other words BrowseMenuUtils.configureBrowseMenushould be called. The "source"attribute is the colon-separated namespace and name to pass to the BrowseMenuUtils.configureBrowseMenumethod.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui">

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->
           <form name="myForm">
             <contents>

               <browseMenu id="myBrowseMenu"
                            formSubmitted="true"
                            defaultContents="true"
                            source="data:browseData"/>

             </contents>
           </form>
         </contents>

         <!-- Data -->
         <provider>

           <data name="data:browseData">
             <method class="oracle.cabo.doc.demo.DataTrees" method="getBrowseNodeDataObject"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       destinationText="More Information"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         destinationText="More Information"
                         description="Instructions: buy, buy, buy!"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"/>
                   <nodes text="Nonfiction"
                           destination="http://www.oracle.com"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="browse">
     <method class="oracle.cabo.doc.demo.DataTrees" method="browseEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

Note that you can ask for the defaults and then override just the parts that need changing. For example let's say you wanted to display items in a table and you wanted to change the text of the headers above the categories and items, but otherwise you wanted to use the defaults. You would set the "defaultContents"and the "source"attributes as shown above, but you would also set the values you wanted to change. In this case you would set the "categoryTitle"and "itemTitle"attributes and set the "items"child with the data appropriately bound. Let's look at an example.

<ctrl:page xmlns="http://xmlns.oracle.com/uix/ui"
  xmlns:ctrl="http://xmlns.oracle.com/uix/controller"
  xmlns:data="http://xmlns.oracle.com/uix/ui">

 <ctrl:content xmlns:ui="http://xmlns.oracle.com/uix/ui">
   <body>
     <contents>

       <dataScope xmlns="http://xmlns.oracle.com/uix/ui">
         <contents>

           <!-- UIX Components -->
           <form name="myForm">
             <contents>

               <browseMenu id="myBrowseMenu"
                            formSubmitted="true"
                            defaultContents="true"
                            source="data:browseData"
                            categoryTitle="Have Subcategories"
                            itemTitle="No Subcategories">
                  <items>
                   <table data:tableData="itemsData@data:browseData"
                           data:rendered="renderItems@data:browseData">
                     <contents>
                       <button data:text="text" data:destination="destination"/>
                       <text data:text="definition"/>
                     </contents>
                   </table>
                 </items>
               </browseMenu>
             </contents>
           </form>
         </contents>

         <!-- Data -->
         <provider>

           <data name="data:browseData">
             <method class="oracle.cabo.doc.demo.DataTrees" method="getBrowseNodeDataObject"/>
           </data>

           <data name="data:Nodes">
             <inline>
               <nodes text="Shop"
                       destination="http://www.oracle.com"
                       destinationText="More Information"
                       expandable="expanded">
                 <nodes text="Books"
                         destination="http://www.oracle.com"
                         destinationText="More Information"
                         description="Instructions: buy, buy, buy!"
                         expandable="expanded">
                   <nodes text="Sale"
                           destination="http://www.oracle.com"
                           expandable="expanded">
                     <nodes text="Paperbacks"
                             destination="http://www.oracle.com"
                             definition="The madness of 1000 years"/>
                   </nodes>
                   <nodes text="Fiction"
                           destination="http://www.oracle.com"
                           definition="Fiction is fantasy"/>
                   <nodes text="nonfiction"
                           destination="http://www.oracle.com"
                           definition="nonfiction is true"/>
                 </nodes>
                 <nodes text="Hardware"
                         expandable="expanded" >
                   <nodes text="Desktops"
                           destination="http://www.oracle.com"
                           definition="Desktops aren't portable"/>
                   <nodes text="Notebooks"
                           destination="http://www.oracle.com"
                           definition="NoteBooks fit in your lap"/>
                 </nodes>
               </nodes>
             </inline>
           </data>
         </provider>
       </dataScope>
     </contents>
   </body>
 </ctrl:content>

 <!-- UIX Controller -->
 <ctrl:handlers xmlns="http://xmlns.oracle.com/uix/controller">

   <event name="browse">
     <method class="oracle.cabo.doc.demo.DataTrees" method="browseEventHandler"/>
   </event>

 </ctrl:handlers>

</ctrl:page>

Notice that we added key-value pairs to the DataObjects that were not expected by the BrowseNodeDataObjectand used these values in the table.

The HGridBean

The HGridBeanprovides yet another way to view tree-structured data. This bean is the union of the TreeBeanand the TableBean; it implements (and extends) the functionality of the TreeBeanwhile imitating the format of a TableBean. In addition to the expand/collapse functionality of the TreeBean, the HGrid supports a zoom in/out feature which allows users to focus in on (or out of) a subtree. One important difference between the HGrid and the Tree is that although the Tree supports multiple roots, the HGrid only supports a single root. It is recommended that you read about Tables before continuing with the HGrid.

An example HGrid is presented in Figure 15-5.

Figure 15-5: An HGrid

An HGrid

The parts of the HGrid shown in Figure 15-5 are explained in the list below. The numbers of the list correspond to the numbers called out in the illustration.

  1. Breadcrumbs
  2. Focus icon
  3. Expand node arrow
  4. Collapse node arrow
  5. Focus column
  6. Object hierarchy column

In this example, the object hierarchy column (6) displays the tree nodes. Clicking the arrows (3 and 4) in this column will expand or collapse the corresponding tree node. The entire tree is rooted at the node "All Colors," but this HGrid is focused on a subtree rooted at the node "Primary Colors." Clicking on the focus icons (2) in the focus column (5) allows a user to continue zooming into subtrees. The breadcrumbs area (1) shows all the parent nodes above the current focus root; clicking on these links allows a user to zoom out to that parent level. The "Expand All" and "Collapse All" links (below the control bar) allow a user to expand or collapse all the tree nodes below the current focus root.

HGrid Named Children

uiXML Key UIConstant Description
nodeStamp NODE_STAMP_CHILD This child allows the header of the object-hierarchy column to be customized. It can also be used as a stamp to customize the object-hierarchy column itself.
columnHeaderStamp COLUMN_HEADER_STAMP_CHILD This is the child used to stamp out all of the user-defined column headers.
tableSelection TABLE_SELECTION_CHILD This is the child used to implement selection in the HGrid.

HGrid Attributes

uiXML Key UIConstant Type Description
id ID_ATTR String A page-wide unique id.
treeData TREE_DATA_ATTR DataObject This is the root of the tree being displayed by the HGrid.
proxy PROXY_ATTR HGridDataProxy The proxy keeps track of expand/collapse/focus state of the HGrid by setting up the expand, collapse and focus destinations.
columnHeaderData COLUMN_HEADER_DATA_ATTR DataObjectList The data to use when stamping out the columnHeaderStamp child.
formSubmitted FORM_SUBMITTED_ATTR Boolean Whether or not to use form submission. Form submission is not the default, thus if form submission is desired then this attribute must be explicitly set to true.

The above tables list some of the important named children and attributes of the HGridBean. For an exhaustive list of these HGrid properties see the hGridUIX element documentation (or the HGridBeanJavaDoc).

The following is an example of a simple HGrid; it displays a tree with a root node called Primary Colors. The data provider part looks familiar; it is written just like it was for a Tree. The HGrid displayed is not interactive (just like a Tree without a proxy).

<dataScope>
 <contents>
  <hGrid id="hg1" data:treeData="nodes@treeData"/>
 </contents>
 <provider>
  <data name="treeData">
   <inline>
    <nodes text="Primary Colors" expandable="expanded">
     <nodes text="Red"/>
     <nodes text="Green" expandable="expanded">
      <nodes text="Light"/>
      <nodes text="Dark"/>
     </nodes>
     <nodes text="Blue"/>
    </nodes>
   </inline>
  </data>
 </provider>
</dataScope>

The above simple example doesn't demonstrate the advantage of an HGrid over a Tree. The impressive visual effect of an HGrid is demonstrated when its Table formatting properties are used, as in the following example:

<dataScope>
 <contents>
  <hGrid id="hg1" data:treeData="nodes@treeData">
   <tableSelection>
    <multipleSelection text="Select and ...">
     <contents>
      <button text="Copy"/>
     </contents>
    </multipleSelection>
   </tableSelection>
   <columnHeaderData>
    <col text="Red Code"/>
    <col text="Green Code"/>
    <col text="Blue Code"/>
   </columnHeaderData>
   <columnHeaderStamp>
    <text data:text="text"/>
   </columnHeaderStamp>
   <columnFormats>
    <col columnDataFormat="numberFormat"/>
    <col columnDataFormat="numberFormat"/>
    <col columnDataFormat="numberFormat"/>
   </columnFormats>
   <contents>
    <text data:text="r"/>
    <text data:text="g"/>
    <text data:text="b"/>
   </contents>
  </hGrid>
 </contents>
 <provider>
  <data name="treeData">
   <inline>
    <nodes text="Primary Colors" expandable="expanded">
     <nodes text="Red" r="Any" g="00" b="00" />
     <nodes text="Green" r="00" g="Any" b="00" expandable="expanded">
      <nodes text="Light" r="00" g="FF" b="00" />
      <nodes text="Dark" r="00" g="88" b="00" />
     </nodes>
     <nodes text="Blue" r="00" g="00" b="Any"/>
    </nodes>
   </inline>
  </data>
 </provider>
</dataScope>

In the above example, the HGrid column headers are set using columnHeaderDataand columnHeaderStamp, column formats are set using columnFormatsand selection is set using tableSelectionand implemented by MultipleSelectionBean. Please refer to the Table chapter for detailed descriptions of these formatting options. The Table chapter also describes other formatting options such as column banding and grid customization which are also pertinent to the HGrid; however, the HGrid does not support any of the row customizations supported by the Table. In addition the HGrid does not support table navigation or detail-disclosure.

NodeStamp

The nodeStampchild of the HGrid allows the object-hierarchy column to be customized. It is possible to customize both the header and the data of this column. Note that the HGrid picks a default column header for the object hierarchy column; this header defaults to Name. This is easily customized by using a ColumnBeanas the nodeStampof the HGrid, as in the following example:

<hGrid ... >
 <nodeStamp>
  <column>
   <columnHeader>
     Color
   </columnHeader>
  </column>
 </nodeStamp>
 ...
</hGrid>

The following example makes use of the nodeStampto stamp out a custom element in the object hierarchy column:

<hGrid ... >
 <nodeStamp>
  <column>
    ...
   <contents>
    <flowLayout>
     <contents>
      <messagePrompt messageType="info"/>
      <text data:text="text"/>
     </contents>
    </flowLayout>
   </contents>
  </column>
 </nodeStamp>
 ...
</hgrid>

HGridDataProxy

Until now, all the example HGrids have been static (non-interactive). In order to make the HGrid interactive an HGridDataProxymust be used (the concept of a proxy was introduced in a previous section describing the TreeBean). The proxy is responsible for handling the expand, collapse, focus and breadcrumb links of the HGrid. In order to animate the HGrid, the proxy needs to maintain the HGrid state across requests. oracle.cabo.ui.data.tree.ClientStateHGridDataProxyis an instance of such a proxy that maintains the state on the client side by encoding the URL. Here is an example of creating a ClientStateHGridDataProxyin a UIX Controller event handler, and storing the proxy on the EventResult(event handlers are described in the UIX Controller chapter):

package oracle.cabo.doc.demo;
public class HGridDemo
{
  public static EventResult doHGridEvent(BajaContext bc, Page page,
                                         PageEvent event)
  {
    HGridDataProxy hGridProxy = new ClientStateHGridDataProxy();
    EventResult result = new EventResult(page);
    result.setProperty("hGridProxy", hGridProxy);
    return result;
  }
}

In order for the above code to be called, the UIX file needs to register the above method as the default event handler, as in the following code snippet:

<handlers>
 <event name="*">
  <method class="oracle.cabo.doc.demo.HGridDemo"
     method="doHGridEvent"/>
 </event>
</handlers>

Finally, the proxy created in the event handler and stored on the EventResultmust be data bound to the proxyattribute of the HGrid. The following is an example of this process (note that the XML namespace prefix datais bound to the UIX Components namespace http://xmlns.oracle.com/uix/ui, and ctrlis bound to the UIX Controller namespace http://xmlns.oracle.com/uix/controller):

<hGrid id="hg1" data:treeData="nodes@treeData"
   data:proxy="hGridProxy@ctrl:eventResult">

Now the expand/collapse/focus links on the HGrid come alive! However, there is some more work that needs to be done before we can play with it. The ClientStateHGridDataProxygenerates certain UIX Controller events that must be handled on the server side. In addition, four event parameters may be generated; the following table summarizes these event parameters:

Event Parameter
Description
uiXML UIConstant
source SOURCE_PARAM The ID of the HGrid that generated this event
state STATE_PARAM The current expand/collapse state of the HGrid
root ROOT_PARAM Identifies the current focus root of the HGrid
node NODE_PARAM Identifies a tree node that must be expanded/collapsed

The following table describes the events triggered by the ClientStateHGridDataProxy, and lists the event parameters accompanying each event:

Event
Event Parameters
Description
uiXML UIConstant source state root node
focus FOCUS_EVENT X X X
Change the focus of the HGrid
expand EXPAND_EVENT X X X X A tree node must be expanded/collapsed
expandAll EXPAND_ALL_EVENT X X X
Recursively expand all the tree nodes beneath the current focus root
collapseAll COLLAPSE_ALL_EVENT X X X
Recursively collapse all the tree nodes beneath the current focus root

Each of these four events needs to be handled on the server. A ClientStateHGridDataProxyneeds to be created in each case; it is just a question of which constructor to call. The following code is used to handle each of the HGrid events (for more information about the constructors, see the ClientStateHGridDataProxyJavaDoc):

public static EventResult doHGridEvent(BajaContext bc, Page page,
                                       PageEvent event)
{
  HGridDataProxy hGridProxy;

  if (event!=null)
  {
    String state = event.getParameter(UIConstants.STATE_PARAM);
    String root = event.getParameter(UIConstants.ROOT_PARAM);
    String node = event.getParameter(UIConstants.NODE_PARAM);

    String eventName = event.getName();
    if (eventName.equals(UIConstants.COLLAPSE_ALL_EVENT))
    {
      hGridProxy = new ClientStateHGridDataProxy(state, root, false);
    }
    else if (eventName.equals(UIConstants.EXPAND_ALL_EVENT))
    {
      hGridProxy = new ClientStateHGridDataProxy(state, root, true);
    }
    else if (eventName.equals(UIConstants.FOCUS_EVENT))
    {
      hGridProxy = new ClientStateHGridDataProxy(state, root);
    }
    else // eventName.equals(UIConstants.EXPAND_EVENT)
    {
      hGridProxy = new ClientStateHGridDataProxy(state, root, node);
    }
  }
  else // there is no event. This is the initial state.
  {
    hGridProxy = new ClientStateHGridDataProxy();
  }

  // create an EventResult such that the current page is rendered again, in
  // response to the event
  EventResult result = new EventResult(page);
  // set the HGrid proxy as a property on the EventResult
  result.setProperty("hGridProxy", hGridProxy);
  return result;
}

The HGrid has an expand/collapse-all feature that is useful most of the time; however, in some cases the number of elements in a subtree can be huge - performing an expand-all on such a subtree would lead to undesirable results. Therefore, the ClientStateHGridDataProxyexports a way to disable expand/collapse-all for a given node. It recognizes the key ClientStateHGridDataProxy.EXPAND_ALL_KEY(or expandAllin uiXML). If the value of this key is Boolean.FALSE(or falsein uiXML) then no expand/collapse-all links are generated for that tree node.

<data name="treeData">
<inline>
 <nodes text="All Colors" expandAll="false" expandable="collapsed">
   ...  <!-- lets say there are tons and tons of subnodes -->
 </nodes>
</inline>
</data>

It is possible to create an HGrid that is initially focused on some subnode (including a leaf node), by using the ClientStateHGridDataProxy(int[] focusPath)constructor. The array of ints is a path to the subnode that is the focus. Each element is a (zero based) child index of the next node, on the path from root to focus node. The first element is a child index of the root node; it produces the next node, A, on the path. The next element is a child index of node A, and it produces node B, and so on. For example, to focus in on the 3rd child of the 1st child of the root use:

// Starting from the root, follow the first child (ie: index zero)
// and then follow the 3rd child (ie: index 2)
int[] focusPath = {0, 2};
hGridProxy = new ClientStateHGridDataProxy(focusPath);

In some cases the tree displayed by the HGrid is small enough that the focusing capability is unnecessary. The focus column (and the breadcrumbs) may be turned off by calling setBreadCrumbsEnabled(false)on the ClientStateHGridDataProxyinstance. Note that this can only be done if the HGrid is focused on the root (the default focus). If the HGrid is focused on some subnode, the breadcrumbs should not be disabled, as the user would have no way of focusing out (in fact, an exception will be thrown if the breadcrumbs are disabled in this case).

Please see the Table chapter for detailed descriptions on how to retrieve data from the HGrid, as the HGrid uses the same mechanisms. This includes using form submitted mode, and retrieving selection data on both the client and server sides.

Conclusion

This chapter discussed tree-structured data and looked at ways of creating such trees in UIX. It also introduced the TreeBean, BrowseMenuBeanand HGridBeanand discussed how these are simply alternate ways to view tree-structured data. Finally, it told how to use these beans and the UIX Controller to provide interactivity.