<?xml version="1.0" encoding="UTF-8"?>
<section id="albumView">
	<title>Album View</title>
	<para>
	      <property>Album</property> view allows you to observe album items as thumbnails, 
	      scale the size of the thumbnails with the slider control, as well as to switch to slideshow mode.
	      By clicking on an image in the <property>Album</property> view the <property>Image</property> View is opened.
	</para>
	
	<figure>
	      <title>Album view</title>
	      <mediaobject>
	            <imageobject>
	                  <imagedata fileref="images/albumView.png"/>
	            </imageobject>
	      </mediaobject>
	</figure>
      <section>
		<title>Image Size Control with &lt;rich:inputNumberSlider&gt;</title>
            <para>
                  The <emphasis role="bold"><property>&lt;rich:inputNumberSlider/&gt;</property></emphasis> component in the Photo Album Demo is used as a control that helps a user to change photos size while previewing an album. 
                  A handler position on the slider track corresponds to a particular value of an image size. 
                  The component is included into the page with the help of <emphasis role="bold"><property>&lt;ui:include/&gt;</property></emphasis>:
            </para>
                  <programlisting role="XML"><![CDATA[...
<ui:include src="src/main/webapp/includes/image/inputNumberSlider.xhtml"/>
...]]></programlisting> 
            
            <para>
                  Now let's have a look at <code>src/main/webapp/includes/image/inputNumberSlider.xhtml</code> file:
            </para>
                  <programlisting role="XML"><![CDATA[...
<ui:composition ...>
      <div>
            <rich:inputNumberSlider value="#{imageSizeHelper.value}"
                        minValue="80" 
                        maxValue="200" 
                        step="40"
                        enableManualInput="false"
                        showArrows="false"
                        showBoundaryValues="true"
                        showInput="false">
                  <a4j:support event="onchange" reRender="userAlbumImages"/>
            </rich:inputNumberSlider>
      </div>
</ui:composition>
...]]></programlisting> 
              <para>
                    There is special Enumeration type that contains four predefined values for image size. Each type has a set of image related attributes such as CSS class for new photo size, postfix for a new file name, image background.
                    The <code>setValue</code> method of the <code>ImageSizeHelper.java</code> class is triggered on each slider's position change. This method sets one of four predefined values for image size and corresponds to slider&apos;s position.  
              </para>
	      <programlisting role="JAVA"><![CDATA[public void setValue(int value) {
            currentDimension = ImageDimension.getInstance(value);
            this.value = currentDimension.getX();
}]]></programlisting> 
	      
	      <para>
	            And here is the <code>ImageDimension.java</code> class:
	      </para>
                 
                  <programlisting role="JAVA"><![CDATA[...
 public enum ImageDimension {

	SIZE_80(80), SIZE_120(120), SIZE_160(160), SIZE_200(200), SIZE_MEDIUM(600), ORIGINAL(0);

	final static String CSS_CLASS = "preview_box_photo_";
	final static String FILE_POSTFIX = "_small";
	final static String IMAGE_BG = "/img/shell/frame_photo_%1$d.png";
	final static String IMAGE_BG_STYLE = "width: %1$dpx; height: %1$dpx";
	
	int x;
	String bgStyle;
	String cssClass;
	String imageBgSrc;
	String filePostfix;

	private ImageDimension(int x) {
		this.x = x;
		this.bgStyle = String.format(IMAGE_BG_STYLE, x + 20);
		cssClass = CSS_CLASS + x;
		imageBgSrc = String.format(IMAGE_BG, (x == 160) ? 200 : x);
		if(x == 600){
			filePostfix = "_medium";
		}else if(x == 0){
			filePostfix = "";
		}else{
			filePostfix = FILE_POSTFIX + x;
		}
	}
      ...]]></programlisting>
                  	      	      
	      <para>
	          After the <emphasis role="bold"><property>&lt;a4j:support&gt;</property></emphasis> finished its job user photos 
                        (more exactly, the <emphasis role="bold"><property>h:panelGroup</property></emphasis> with <code>userAlbumImages</code> id  that contains user photos) 
                        are rendered correspondingly to the new  value. Here is <code>web/src/main/webapp/includes/image/imageList.xhtml</code>:
                  </para>
                  <programlisting role="XML"><![CDATA[...
<h:panelGroup id="userAlbumImages">		
	<a4j:repeat id="imageList" value="#{model.images}" var="image" rows="20">
		<h:panelGroup layout="block" styleClass="#{imageSizeHelper.currentDimension.cssClass}">
			<h:graphicImage styleClass="pr_photo_bg" style="#{imageSizeHelper.currentDimension.imageBgStyle}" value="#{imageSizeHelper.currentDimension.imageBg}" />
			<h:panelGrid cellpadding="0">
				<h:panelGroup>
					<a4j:commandLink
							actionListener="#{controller.showImage(image)}"
							reRender="mainArea, treePanel">					
								<a4j:mediaOutput id="img"  element="img" 
									createContent="#{imageLoader.paintImage}" 
									style="border : 1px solid #FFFFFF;"
									value="#{fileManager.transformPath(image.fullPath, imageSizeHelper.currentDimension.filePostfix)}">
									<f:param value="#{imageSizeHelper.currentDimension.x}" name="x" />
									<rich:dragSupport rendered="#{controller.isUserImage(image)}" reRender="mainArea, treePanel" id="dragSource" dragIndicator="dragIndicator"
                                dragType="image" dragValue="#{image}">
                                <rich:dndParam id="dragParam" name="label" value="#{image.name}" />
                            </rich:dragSupport>
							</a4j:mediaOutput>
					</a4j:commandLink>
					<br/>
				</h:panelGroup>
				<ui:include src="/includes/contextMenu/CMForImage.xhtml" >
					<ui:param name="image" value="#{image}" />
					<ui:param name="mediaOutput" value="#{rich:clientId('img')}"/>
				</ui:include>
				
			</h:panelGrid>				
			<h:panelGroup layout="block" styleClass="photo_name">#{image.name}</h:panelGroup>		
			<h:panelGroup layout="block" styleClass="photo_data">
				<h:outputText value="#{image.created}">
					<f:convertDateTime />
				</h:outputText>
			</h:panelGroup>		
		</h:panelGroup>
	</a4j:repeat>
	</h:panelGroup>		
...]]></programlisting>
              
              <para>
                    When the <emphasis role="bold"><property>&lt;rich:inputNumberSlider&gt;</property></emphasis> is rendered, initially its default value for image size is 120 px.  
              </para>
                  
                  <figure>
                        <title>Image size control</title>
                        <mediaobject>
                              <imageobject>
                                    <imagedata fileref="images/image_size.png"/>
                              </imageobject>
                        </mediaobject>
                  </figure>
	      <para>
	            Visit 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/inputNumberSlider.jsf?c=inputNumberSlider">InputNumberSlider</ulink> page for the <emphasis role="bold"><property>&lt;rich:inputNumberSlider&gt;</property></emphasis> component;
	                  </para>     
	            </listitem>
	            
	            <listitem>
	                  <para>
	                        <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support">AjaxSupport</ulink> for the <emphasis role="bold"><property>&lt;a4j:support&gt;</property></emphasis> component.
	                  </para>     
	            </listitem>
	            
	            	            
	      </itemizedlist>   
            
            </section>
            
           
            
            <section id="slideshow">
            <title>Slideshow</title>
            
                  <para>The slideshow feature in the Photo Album Demo can be enabled by clicking on <emphasis role="bold">&quot;Start Slideshow&quot;</emphasis> link from two different places in the application: 
                  1) from user&apos;s album preview (<code>/web/src/main/webapp/image/albumInfo.xhtml</code>) and 2) from a particular photo preview (<code>src/main/webapp/image/imageInfo.xhtml</code>). 
                  Both of  two mentioned XHTML files include slideshow with the help of Facelets &lt;<emphasis role="bold"><property>ui:include</property></emphasis> tag 
                  (for more information about &lt;<emphasis role="bold"><property>ui:include</property></emphasis> see Facelets Reference Guide — 
                  <ulink url="http://www.jsftoolbox.com/documentation/facelets/01-Introduction/index.jsf">http://www.jsftoolbox.com/documentation/facelets/01-Introduction/index.jsf</ulink>).
            </para>
            <para>
                  The components that implement the slideshow functionality are:
            </para>
                  <itemizedlist>
                        <listitem><para><emphasis role="bold"><property>&lt;rich:modalPanel&gt;</property></emphasis> located in  <code>web/src/main/webapp/includes/image/slideshow.xhtml</code> that is hidden by default as the  attribute <code>showWhenRendered=&quot;#{slideshow.active}&quot;</code> and the active property of  <code>SlideshowManager.java</code> is set to &quot;false&quot; by default.</para></listitem>
                        <listitem><para><emphasis role="bold"><property>&lt;a4j:poll&gt;</property></emphasis> located in  <code>includes/misc/slideShowPooler.xhtml</code> which is also inactive due to the mentioned active property ( <code>active=#{slideshow.active}</code>)</para></listitem>
                  </itemizedlist>
                  
             <para>
                   
                   After activation, <emphasis role="bold"><property>&lt;a4j:poll&gt;</property></emphasis> will send asynchronous requests to the server with some certain interval, as the result of these requests modal panel will display the next image in the row.
             </para>     
                  
<para>
      Now let&apos;s have a look at the details of the slideshow implementation.
</para>
                  
                  <para>
                        The <code>startSlideshow()</code> method of <code>SlideshowManager.java</code> is invoked when no photo is selected in the current image list. The method iterates over all photos of a particular album starting from the first one in the list. Look at the <code>SlideshowManager.java</code> listing below:                        
                  </para>
                  
<programlisting role="JAVA"><![CDATA[...
  ...
public void startSlideshow(){
      active = true;
      this.slideshowIndex = 0;
      if(model.getImages() == null || model.getImages().size() < 1){
            stopSlideshow();
            Events.instance().raiseEvent(Constants.ADD_ERROR_EVENT, "No images for slideshow!");
            return;
      }
      this.selectedImage = model.getImages().get(this.slideshowIndex);
      this.selectedImage.getAlbum().visitImage(selectedImage, true);
}
...]]></programlisting> 
  <para>
        The second variation of the <code>startSlideshow()</code> method is activated when a link to slide-show is clicked from a particular photo preview. This method iterates over the rest of photos starting from the current selected one:        
        
  </para>          
  <programlisting role="JAVA"><![CDATA[...
 public void startSlideshow(Image selectedImage){
      active = true;
      if(model.getImages() == null || model.getImages().size() < 1){
            stopSlideshow();
            Events.instance().raiseEvent(Constants.ADD_ERROR_EVENT, "No images for slideshow!");
            return;
      }
      this.slideshowIndex = model.getImages().indexOf(selectedImage);
      this.selectedImage = selectedImage;
      this.selectedImage.getAlbum().visitImage(selectedImage, true);
}
...]]></programlisting>           
            
            <para>
                  Both variants of <code>startSlideshow()</code> method set the <code>active</code> property to &quot;true&quot; as a result the poller is activated and modal panel becomes visible.                   
                 
            </para>
                  <para>
                        The slideshow modal panel is kept in the <code>web/src/main/webapp/includes/image/slideshow.xhtml</code> file and referred from the corresponding pages with the help of &lt;ui:include&gt; Facelets tag: 
                  </para>
                  <programlisting role="XML"><![CDATA[...
<ui:include src="/includes/image/slideshow.xhtml"/>
...]]></programlisting> 
                  <para>
                        Have a look at <code>web/src/main/webapp/includes/image/slideshow.xhtml</code> file: 
                  </para>
                  <programlisting role="XML"><![CDATA[...
<ui:composition xmlns="http://www.w3.org/1999/xhtml"...>

      <rich:modalPanel showWhenRendered="#{slideshow.active}"

                  domElementAttachment="parent" 

                  id="slideShowModalPanel" 

                  width="650"

                  onshow="showPictureEffect();"

                  height="650">

            <f:facet name="controls">

                  <h:panelGroup>

                        <h:graphicImage value="/img/modal/close.png" style="cursor:pointer" id="hidelink">

                              <a4j:support event="onclick" actionListener="#{slideshow.stopSlideshow}" reRender="slideShowForm, mainArea, tree" />

                        </h:graphicImage>

                  </h:panelGroup>

            </f:facet>

            ...      

      </rich:modalPanel>

</ui:composition>

...]]></programlisting> 
                  <para>
                        
                        This is the source code of  <code>includes/misc/slideShowPooler.xhtml</code>:     
                  </para>
                  
                  <programlisting role="XML"><![CDATA[...
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:richx="http://richfaces.org/richx">
      <a4j:form id="slideShowForm">
            <a4j:poll reRender="slideshowImage"
                              actionListener="#{slideshow.showNextImage()}"
                              interval="#{slideshow.interval}"
                              enabled="#{slideshow.active}"
                              onsubmit="hidePictureEffect()"
                              oncomplete="showPictureEffect();"/>
      </a4j:form>
</ui:composition>
...]]></programlisting> 
                  
                  <para>
                        The slideshow poller sends the request for the next image (<code>showNextImage()</code> method) each four seconds. 
                        The interval is defined in the interval property of the <code>SlideshowManager.java</code> and refers to a <code>INITIAL.DELAY</code> constant (<code>constants.java</code>). 
                  </para>
                  <para>
                        The described above example implements a modal panel with photos that rotate them in the order they are stored in an album. 
                  </para>
                  <figure>
                        <title>Image size control</title>
                        <mediaobject>
                              <imageobject>
                                    <imagedata fileref="images/slide_show.png"/>
                              </imageobject>
                        </mediaobject>
                  </figure>
               
               <para>
                     To stop the slide-show user clicks <emphasis role="bold">Close window</emphasis> button on the slide-show panel and <code>stopSlideshow()</code> method is invoked. 
               </para>
<programlisting role="XML"><![CDATA[...
@Observer("stopSlideshow")
      public void stopSlideshow(){
            active = false;
            this.selectedImage = null;
            this.slideshowIndex = 0;
      }
      ...]]></programlisting> 
                  
                  <para>
                        The <code>active</code> field is set to &quot;false&quot; again, consequently the poller becomes inactive and the modal panel becomes invisible too.
                  </para>
            </section>
                  <para>
                        Visit 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/modalPanel.jsf?c=modalPanel">ModalPanel</ulink> page for the <emphasis role="bold"><property>&lt;rich:modalPanel&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/effect.jsf?c=effect">Effect</ulink> for the <emphasis role="bold"><property>&lt;rich:effect&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/mediaOutput.jsf?c=mediaOutput">MediaOutput</ulink> for the <emphasis role="bold"><property>&lt;a4j:mediaOutput&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support">AjaxSupport</ulink> for the <emphasis role="bold"><property>&lt;a4j:support&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/commandLink.jsf?c=commandLink">CommandLink</ulink> for the <emphasis role="bold"><property>&lt;a4j:commandLink&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/form.jsf?c=form">AjaxForm</ulink> for the <emphasis role="bold"><property>&lt;a4j:form&gt;</property></emphasis> component;
                              </para>     
                        </listitem>
                        
                        <listitem>
                              <para>
                                    <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/poll.jsf?c=poll">Poll</ulink> for the <emphasis role="bold"><property>&lt;a4j:poll&gt;</property></emphasis> component.
                              </para>     
                        </listitem>
                       </itemizedlist>
            
</section>
