## Navigation tree with pre-defined shelves.

The <r: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 "Shelves - 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 <r:tree> component.

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

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

According to the "Shelves - Albums" hierarchy we need two nested <r:treeModelAdaptor> components. The first one iterates over the Shelves 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 <r:treeModelAdaptor> component iterates over the Albums collection of the current Shelf which is available via "var" attribute of <r:tree>. The "var" attribute is used to get access to the data object of the current collection element Shelf, so it is possible to output any necessary data. Let's see the `src/main/webapp/includes/index/tree.xhtml` file:

                  <r:tree ajaxSubmitSelection="false" id="PreDefinedTree" var="treeNode" toggleType="client">
                    <r:treeModelAdaptor nodes="#{'#{'}shelfManager.predefinedShelves}">
                        <r:treeNode style="cursor:pointer" selectedClass="tree-selected-node"
                            iconCollapsed="img/shell/tree_icon_shelf.png" iconExpanded="img/shell/tree_icon_shelf.png">
                            <r: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']}" />
                                <r:ajax render="treePanel, mainArea" event="click" listener="#{'#{'}controller.showShelf(treeNode)}" />

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

                            </r:outputPanel>
                        </r:treeNode>

                        <r:treeModelAdaptor var="album" nodes="#{'#{'}treeNode.albums}">
                            <r:treeNode style="cursor:pointer" selectedClass="tree-selected-node"
                                iconLeaf="img/shell/tree_icon_album.png">
                                <r: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']}" />
                                    <r:ajax render="treePanel, mainArea" event="click" listener="#{'#{'}controller.showAlbum(treeNode)}" />

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

                                </r:outputPanel>
                            </r:treeNode>

                        </r:treeModelAdaptor>
                    </r:treeModelAdaptor>

                </r:tree>

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

Shelves and albums nodes rendered with the help of the <r:treeNodesAdaptor>