<?xml version="1.0" encoding="UTF-8"?>
<section id="navigationTree" xreflabel="navigationTree">
	<?dbhtml filename="navigationPanel.html"?>
            <title>Navigation tree</title>
        		<para>
                        The <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> component takes one of the main places  
                        in the <property>Photo Album</property> and is tightly bound with the application logic. 
						It helps to represent 
                        and implement inherently the &quot;Shelves - Albums&quot; 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.   
                  </para>
                  <para>
                        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.
                  </para>
            <section>
                  <title>Navigation tree for a guest</title>
      
                  <!--para>
                        The <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> component is designed for 
                        hierarchical data presentation and is used  to build a tree structure. 
                        The component also supports built-in drag-and-drop functionality.
                  </para-->
                  <para>
                  	Navigation tree for a guest is represented as a simple 
                  	<emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> component.
                  </para>
                  <para>
                  		There are several ways to implement the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> on a page. 
                        In the current application the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> is designed  
                        using a model tag <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis>.
                  </para>
                  <para>
                  		The <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component 
                        has a <emphasis><property>&quot;nodes&quot;</property></emphasis> attribute that accepts
                        a collection of elements, so <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis>
                        iterates over the collection and renders a hierarchical tree structure on a page. 
                  </para>      
                  <para>
                  	According to the &quot;Shelves - Albums&quot; hierarchy we need two nested
                  	<emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> components.
                  	The first one iterates over the Shelves collection 
                  	that is returned from the <code>getPredefinedShelves()</code> method of <code>ShelfManager.java</code> class:
                  </para>
                  <programlisting role="JAVA"><![CDATA[...
public List<Shelf> getPredefinedShelves() {
        if (shelves == null) {
            shelves = shelfAction.getPredefinedShelves();
        }
        return shelves;
    }
} 
...]]></programlisting>
				<para>
					The second <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component
					iterates over the Albums collection of the current Shelf which is available via 
					<emphasis><property>&quot;var&quot;</property></emphasis> attribute.
					The  <emphasis><property>&quot;var&quot;</property></emphasis> 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 <code>src/main/webapp/includes/index/tree.xhtml</code> file: 
				</para>
                  <!-- 
                        The <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component accepts 
                        a collection of elements, which are allowed to include lists, arrays, maps, XML NodeList or NamedNodeMap, and iterate over it. 
                        The <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component repeats a hierarchical tree structure on a <code>xhtml</code> or <code>jsp</code> page in a component tree and can be nested without any limitations. 
                        The code snippet below schematically shows the idea of how a tree can be built on a page with the help of adaptors:
                 
                  
                  
                  <programlisting role="XML"><![CDATA[<rich:tree>
      <rich:treeNodesAdaptor>
            <rich:treeNode />

            <rich:treeNodesAdaptor>
                  <rich:treeNode />
                  
                  <rich:treeNodesAdaptor>
                        <rich:treeNode />
                         ...
                  </rich:treeNodesAdaptor>
            </rich:treeNodesAdaptor>
      </rich:treeNodesAdaptor>
</rich:tree>]]></programlisting>
                  
                  <para>
                        When using <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component 
                        there is no need to specify 
                        the <emphasis><property>&quot;value&quot;</property></emphasis> and 
                        <emphasis><property>&quot;var&quot;</property></emphasis> attributes 
                        for the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis>. 
                        The values for nodes to render are passed directly into the corresponding adaptor 
                        and the component performs all the necessary iterative work 
                        (vizit the <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/treeNodesAdaptor.jsf?c=treeNodesAdaptor">&lt;rich:treeNodesAdaptor&gt; page</ulink> on the RichFacesLiveDemo for more details).
                  </para>
                  
                  <para>
                        Implementation of the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> in the application 
                        is very similar to the model shown above. 
                        The top <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> 
                        in the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> in the Photo Album 
                        application is responsible for shelves rendering. 
                        Its <emphasis><property>&quot;nodes&quot;</property></emphasis> attribute refers 
                        to <emphasis><property>getShelves()</property></emphasis> method of the <code>ShelfManager</code> class 
                        and gets the collection of shelves associated with the current user including all shared shelves in the system.
                        Take a look at this method:
                  </para-->
                 
                  <!-- para>
                        When the <emphasis><property>&quot;nodes&quot;</property></emphasis> attribute of the <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis>, which is responsible for shelves rendering, receives the collection of shelves, 
                        the iteration process switches to the nested <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis>, which is responsible for albums. 
                        The &quot;albums&quot; <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> <emphasis><property>&quot;nodes&quot;</property></emphasis> attribute refers in its turn to the <code>albums</code> field of the <code>Shelf</code> class 
                        and takes a collection of all albums associated with the current shelf. 
                        The &quot;albums&quot; <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> renders all albums that belong to the current iterating shelf and then switches back to the &quot;shelf&quot; <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> to render and iterate the next shelf in the shelves collection received earlier. 
                        Here is how it looks in the <code>webapp/includes/index/tree.xhtml</code> file:  
                  </para-->
                  
                  <programlisting role="XML"><![CDATA[...
<rich:tree adviseNodeOpened="#{treeManager.adviseNodeSelected}"
            adviseNodeSelected="#{treeManager.adviseNodeSelected}"
            ajaxSubmitSelection="false" id="PreDefinedTree"
            treeNodeVar="treeNode" switchType="client"
            iconCollapsed="/img/shell/tree_icon_plus.png"
            iconExpanded="/img/shell/tree_icon_minus.png"
            showConnectingLines="false">
      <rich:treeNodesAdaptor nodes="#{shelfManager.getPredefinedShelves()}" var="shelf">
            <rich:treeNode style="cursor:pointer" reRender="treePanel,mainArea" selectedClass="tree-selected-node">
                  <f:facet name="icon">
                        <h:graphicImage style="border: none" value="/img/shell/tree_icon_shelf.png">
                              <a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showShelf(shelf)}" similarityGroupingId="sel" />
                        </h:graphicImage>
                  </f:facet>
                  <a4j:outputPanel  >
                        <h:outputText style="cursor:pointer" value="#{shelf.name}" />
                        <h:outputText value=" :: " />
                        <strong>#{shelf.unvisitedImages.size()}</strong> new
                        <a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showShelf(shelf)}" similarityGroupingId="sel" />
                  </a4j:outputPanel>
            </rich:treeNode>
            
            <rich:treeNodesAdaptor var="album" nodes="#{shelf.albums}">
                  <rich:treeNode style="cursor:pointer" reRender="treePanel,mainArea" selectedClass="tree-selected-node" icon="img/shell/tree_icon_album.png">
                        <f:facet name="iconLeaf">
                              <h:graphicImage style="border: none" value="img/shell/tree_icon_album.png">
                                    <a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showAlbum(album)}" similarityGroupingId="sel" />
                              </h:graphicImage>
                        </f:facet>
                        <a4j:outputPanel>
                              <h:outputText style="cursor:pointer" value="#{album.name}" />
                              <h:outputText value=" :: " />
                              <strong>#{album.unvisitedImages.size()}</strong> new
                              <a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showAlbum(album)}" similarityGroupingId="sel" />
                        </a4j:outputPanel>
                  </rich:treeNode>
            </rich:treeNodesAdaptor>
      </rich:treeNodesAdaptor>
</rich:tree>
...]]></programlisting>

                  <para>
                        The image below shows how the navigation tree for a guest is rendered on the page.        
                  </para>
                  
                  <figure>
                        <title>Shelves and albums nodes rendered with the help of the &lt;rich:treeNodesAdaptor&gt;</title>
                        <mediaobject>
                              <imageobject>
                                    <imagedata fileref="images/tree.png"/>
                              </imageobject>
                        </mediaobject>
                  </figure>              
                  
</section>
            
            <section>
                  <title>Navigation tree for a registered user</title>
                  <para>
                  	As it was mentioned before a navigation tree for a registered user has
                  	two main features: drag-and-drop and context menu. Context menu is described 
                  	in the <link linkend="contextMenu">&quot;Context menu&quot;</link> chapter.
                  </para>
                  <para>
                        Drag-and-drop feature supported in the Photo Album application is not so complicated 
                        as it may seem from the first view. 
                        In this application we can mark out two types of drag-and-drop: 
                        one type takes place only inside the tree (between tree nodes) 
                        and another one - between the watching area and the tree. 
                        The difference is not considerable enough to describe two types separately, 
                        but also not at all insignificant to be omitted here.
                  </para>
                  
                  <para>
                        The tree related components 
                        (<emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> and <emphasis role="bold"><property>&lt;rich:treeNode&gt;</property></emphasis>) 
                        have their own attributes that provide drag-and-drop functionality. 
                        These attributes can be divided into two groups: 
                        those  which provide drag (dragValue, dragListener, dragIndicator, dragType attributes) 
                        and those which provide drop operations (dropValue, dropListener, acceptedTypes, typeMapping).      
                  </para>
                  <note>
                        <title>
                              Note:
                        </title>
                        <para>
                              Due to &quot;Shelves - Albums - Photos&quot; hierarchy we can say that photos could be moved between albums, 
                              albums could be moved between shelves. 
                              To avoid a mishmash, it's not allowed to place photos directly in shelves as well as nesting shelves 
                              inside shelves or albums inside albums.
                        </para>
                  </note>
                  <para>
                  	Let&apos;s explore how drag-and-drop works for albums.
                  </para>
                  <para>
                        All albums, that are represented as TreeNodes, must be marked somehow for dragging.
                        For this purpose we use previously mentioned 
                        <emphasis><property>&quot;dragValue&quot;</property></emphasis>,
                        <emphasis><property>&quot;dragType&quot;</property></emphasis>
                        attributes. Let's have a look at the <code>src/main/webapp/includes/index/tree.xhtml</code> file: 
                  </para>
                  <programlisting role="XML"><![CDATA[<rich:treeNodesAdaptor var="album" nodes="#{shelf.albums}">
      <rich:treeNode style="cursor:pointer" 
                        reRender="mainArea, treePanel" 
                        dragType="album" 
                        dragValue="#{album}" 
                        dropValue="#{album}" 
                        acceptedTypes="image" 
                        selectedClass="tree-selected-node" 
                        icon="img/shell/tree_icon_album.png">
            ...
            <rich:dndParam name="label" type="drag" value="#{album.name}" />
            ...
      </rich:treeNode>
</rich:treeNodesAdaptor>
]]></programlisting>
              <para>
                    To provide drop functionality for the marked albums, we should mark Shelves as drop zones in the application code too. 
                    For this purpose we add the <emphasis><property>&quot;dropValue&quot;</property></emphasis> and
                    <emphasis><property>&quot;acceptedTypes&quot;</property></emphasis> attributes to the &quot;Shelf&quot; node in the same <code>src/main/webapp/includes/index/tree.xhtml</code> file:
              </para>
                  <programlisting role="XML"><![CDATA[<rich:treeNodesAdaptor nodes="#{shelfManager.getUserShelves()}" var="shelf">
      <rich:treeNode style="cursor:pointer" acceptedTypes="album" dropValue="#{shelf}" reRender="mainArea, treePanel" selectedClass="tree-selected-node">
            ...
      </rich:treeNode>
</rich:treeNodeAdaptor>]]></programlisting>
              <para>
                    The <emphasis><property>&quot;acceptedTypes&quot;</property></emphasis> attribute tells the &quot;Shelf&quot; node 
                    what types of dragged zones (albums in this case) it can accept.
                    We have specified &quot;Album&quot; node 
                    <emphasis><property>&quot;dragType&quot;</property></emphasis> as &quot;album&quot;,
                    so the &quot;Shelf&quot; node can accept it.
              </para>
              <para>
                    Finally in order to process drop on the server side we need to specify a listener for the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> in the <emphasis><property>&quot;dropListener&quot;</property></emphasis>
                    attribute (<code>src/main/webapp/includes/index/tree.xhtml</code> file):  
              </para>
                  <programlisting role="XML"><![CDATA[<rich:tree adviseNodeOpened="#{treeManager.adviseNodeSelected}"
                  adviseNodeSelected="#{treeManager.adviseNodeSelected}"
                  ajaxSubmitSelection="false" dragIndicator="dragIndicator" 
                  treeNodeVar="treeNode" switchType="client"
                  iconCollapsed="/img/shell/tree_icon_plus.png"
                  iconExpanded="/img/shell/tree_icon_minus.png"
                  dropListener="#{dndManager.processDrop}"
                  showConnectingLines="false">
            ...
</tree>]]></programlisting>
              <para>
                    The code for 	the <emphasis role="bold"><property>&lt;rich:dragIndicator&gt;</property></emphasis> looks like the following:
              </para>    
                  <programlisting role="XML"><![CDATA[<rich:dragIndicator id="dragIndicator" />]]></programlisting>   
                  
                  
              <para>
                    The <code>processDrop()</code> method of <code>DnDManager.java</code> class is shown in the listing below: 
              </para>
                  <programlisting role="JAVA"><![CDATA[...
public void processDrop(DropEvent dropEvent) {
      Dropzone dropzone = (Dropzone) dropEvent.getComponent();
      Object dragValue = dropEvent.getDragValue();
      Object dropValue = dropzone.getDropValue();
      if(dragValue instanceof Image){
            if(!((Album)dropValue).getOwner().getLogin().equals(user.getLogin())){
                  Events.instance().raiseEvent(Constants.ADD_ERROR_EVENT, Constants.DND_PHOTO_ERROR);
                  return;
            }
            handleImage((Image)dragValue, (Album)dropValue);	
      }else if(dragValue instanceof Album){
            if(!((Shelf)dropValue).getOwner().getLogin().equals(user.getLogin())){
                  Events.instance().raiseEvent(Constants.ADD_ERROR_EVENT, Constants.DND_ALBUM_ERROR);
                  return;
            }
            handleAlbum((Album)dragValue, (Shelf)dropValue);
      }
}
...]]></programlisting>
			<para>
				Here is	the whole example of the &quot;Navigation tree for a registered user&quot;:
			</para>
                  <programlisting role="XML"><![CDATA[<h:panelGroup id="tree" rendered="#{identity.hasRole('admin')}" layout="block">
		<a4j:commandLink actionListener="#{controller.selectShelves()}" reRender="mainArea, treePanel"><h2><h:outputText  value="My shelves:"/></h2></a4j:commandLink><br/>
	<rich:dragIndicator
			id="dragIndicator" />
		<rich:tree 
			adviseNodeOpened="#{treeManager.adviseNodeSelected}"
			adviseNodeSelected="#{treeManager.adviseNodeSelected}"
			ajaxSubmitSelection="false" dragIndicator="dragIndicator" 
			treeNodeVar="treeNode" switchType="client"
			iconCollapsed="/img/shell/tree_icon_plus.png"
			iconExpanded="/img/shell/tree_icon_minus.png"
			dropListener="#{dndManager.processDrop}"
			showConnectingLines="false">
			 
				<f:facet name="icon">
					<h:graphicImage style="border: none" value="/img/shell/tree_icon_shelf.png">
							<a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showShelf(shelf)}" similarityGroupingId="sel" />
					</h:graphicImage>
				</f:facet>
    			<ui:include src="/includes/contextMenu/CMForShelf.xhtml" >
					<ui:param name="shelf" value="#{shelf}" />
				</ui:include>
				<a4j:outputPanel>
					<h:outputText style="cursor:pointer" value="#{shelf.name}" />
					<h:outputText value=" :: " />
					<strong>#{shelf.unvisitedImages.size()}</strong> new
					<a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showShelf(shelf)}" similarityGroupingId="sel" />
				</a4j:outputPanel>
				</rich:treeNode>

				<rich:treeNodesAdaptor var="album"
					nodes="#{shelf.albums}">
					<rich:treeNode style="cursor:pointer" reRender="mainArea, treePanel" dragType="album"
						dragValue="#{album}" dropValue="#{album}"
						acceptedTypes="image"
						selectedClass="tree-selected-node"
						icon="img/shell/tree_icon_album.png">
						<f:facet name="iconLeaf">
							<h:graphicImage style="border: none" value="img/shell/tree_icon_album.png">
									<a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showAlbum(album)}" similarityGroupingId="sel" />
							</h:graphicImage>
						</f:facet>
						<ui:include src="/includes/contextMenu/CMForAlbum.xhtml" >
						<ui:param name="album" value="#{album}" />
						</ui:include>
						<rich:dndParam name="label" type="drag" value="#{album.name}" />
						<a4j:outputPanel >
							<h:outputText style="cursor:pointer" value="#{album.name}" />
							<h:outputText value=" :: " />
								<strong>#{album.unvisitedImages.size()}</strong> new
						<a4j:support reRender="treePanel, mainArea" event="onclick" actionListener="#{controller.showAlbum(album)}" similarityGroupingId="sel" />
						</a4j:outputPanel>
				</rich:treeNode>

				</rich:treeNodesAdaptor>
			</rich:treeNodesAdaptor>

		</rich:tree>
		</h:panelGroup>]]></programlisting>       
              <para>
                    The image below shows how the described above drag-and-drop features are rendered in the Photo Album.  
              </para>
                  <figure>
                        <title>Dragging the &quot;Flora&quot; album from &quot;Sport&quot; shelf into the &quot;Nature&quot; (left) and the tree after drag-and-drop (right).</title>
                        <mediaobject>
                              <imageobject>
                                    <imagedata fileref="images/dnd.png"/>
                              </imageobject>
                        </mediaobject>
                  </figure>
                  <para>
                        Vizit following pages at RichFaces Live Demo for more information, examples and sources on the components used in the application and described in this chapter:
                  </para>
                  
                  <itemizedlist>
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/tree.jsf?c=tree">Tree</ulink> for the <emphasis role="bold"><property>&lt;rich:tree&gt;</property></emphasis> component;
                               </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/treeNodesAdaptor.jsf?c=treeNodesAdaptor">TreeNodesAdaptor</ulink> for the <emphasis role="bold"><property>&lt;rich:treeNodesAdaptor&gt;</property></emphasis> component; 
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/dragSupport.jsf?c=dragIndicator">DragIndicator</ulink> for the <emphasis role="bold"><property>&lt;rich:dragIndicator&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/dragSupport.jsf?c=dndParam">DragDropParameter</ulink> for the <emphasis role="bold"><property>&lt;rich:dndParam&gt;</property></emphasis> component.
                              </para>     
                        </listitem>
                        
                  </itemizedlist>   
                        
                  
            </section>
</section>
      
