## Navigation tree with public album groups.

The <rich:tree> component takes one of the main places in the Photo Album and is tightly bounded with the application logic. It helps to represent and implement inherently the "Album Groups - Albums" hierarchy. Shelf is the highest possible level in the tree hierarchy, that is used to group thematic albums and may contain as many albums as needed.

There are two types of navigation tree in the application: for a registered user and for a guest. The difference between them is that the first one has a context menu and drag-and-drop possibility.

### Navigation tree for a guest

Navigation tree for a guest is represented as a simple <rich:tree> component.

There are several ways to implement the <rich:tree> on a page. In the current application the <rich:tree> is designed using a model tag <rich:treeNodesAdaptor>.

The <rich:treeModelAdaptor> component has a "nodes" attribute that accepts a collection of elements, so <rich:treeModelAdaptor> iterates over the collection and renders a hierarchical tree structure on a page.

According to the "Album Groups - Albums" hierarchy we need two nested <rich:treeModelAdaptor> components. The first one iterates over the AlbumGroups collection that is returned from the `getPredefinedShelves()` method of `ShelfManager.java` class:

                    public List<Shelf> getPredefinedShelves() {
                        if (shelves == null) {
                            shelves = shelfAction.getPredefinedShelves();
                        }
                        return shelves;
                    }

The second <rich:treeModelAdaptor> component iterates over the Albums collection of the current Album Group which is available via "var" attribute of <rich:tree>. The "var" attribute is used to get access to the data object of the current collection element Album Group, so it is possible to output any necessary data. Let's see the `src/main/webapp/includes/index/tree.xhtml` file:

                <rich:tree ajaxSubmitSelection="false" id="PreDefinedTree" var="treeNode" toggleType="client">
                  <rich:treeModelAdaptor nodes="#{'#{'}shelfManager.predefinedShelves}">
                    <rich:treeNode style="cursor:pointer" selectedClass="tree-selected-node"
                        iconCollapsed="resources/img/shell/tree_icon_shelf.png" iconExpanded="resources/img/shell/tree_icon_shelf.png">
                      <a4j:outputPanel layout="block" style="cursor:pointer;width:200px; overflow-x:hidden;">
                        <h:outputText value="#{'#{'}treeNode.name}" />
                        <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" value=" #{'#{'}messages['delimiter']} " />
                        <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" styleClass="bold"
                            value="#{'#{'}fn:length(treeNode.unvisitedImages)}" />
                        <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" value=" #{'#{'}messages['new']}" />
                        <a4j:ajax render="treePanel, mainArea" event="click" listener="#{'#{'}controller.showShelf(treeNode)}" />

                        <rich:tooltip direction="topRight" showDelay="1000">
                          <span style="white-space: nowrap">#{'#{'}treeNode.name}</span>
                        </rich:tooltip>

                      </a4j:outputPanel>
                    </rich:treeNode>

                    <rich:treeModelAdaptor var="album" nodes="#{'#{'}treeNode.albums}">
                      <rich:treeNode style="cursor:pointer" selectedClass="tree-selected-node"
                          iconLeaf="resources/img/shell/tree_icon_album.png">
                        <a4j:outputPanel layout="block" style="cursor:pointer;width:200px; overflow-x:hidden;">
                          <h:outputText value="#{'#{'}treeNode.name}" />
                            <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" value=" #{'#{'}messages['delimiter']} " />
                          <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" styleClass="bold"
                              value="#{'#{'}fn:length(treeNode.unvisitedImages)}" />
                          <h:outputText rendered="#{'#{'}fn:length(treeNode.unvisitedImages) > 0}" value=" #{'#{'}messages['new']}" />
                          <a4j:ajax render="treePanel, mainArea" event="click" listener="#{'#{'}controller.showAlbum(treeNode)}" />

                          <rich:tooltip direction="topRight" showDelay="1000">
                            <span style="white-space: nowrap">#{'#{'}treeNode.name}</span>
                          </rich:tooltip>

                        </a4j:outputPanel>
                      </rich:treeNode>

                    </rich:treeModelAdaptor>
                  </rich:treeModelAdaptor>

                </rich:tree>

The image below shows how the navigation tree for a guest is rendered on the page.

Album Groups and albums nodes rendered with the help of the <rich:treeNodesAdaptor>