[richfaces-svn-commits] JBoss Rich Faces SVN: r13740 - trunk/docs/realworld_app_guide/en/src/main/docbook/modules.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Tue Apr 21 11:39:27 EDT 2009


Author: atsebro
Date: 2009-04-21 11:39:27 -0400 (Tue, 21 Apr 2009)
New Revision: 13740

Modified:
   trunk/docs/realworld_app_guide/en/src/main/docbook/modules/hiw.xml
Log:
RF-5768: Real World Demo Application Tutorial Update for 3.3.1 release 

Modified: trunk/docs/realworld_app_guide/en/src/main/docbook/modules/hiw.xml
===================================================================
--- trunk/docs/realworld_app_guide/en/src/main/docbook/modules/hiw.xml	2009-04-21 15:36:50 UTC (rev 13739)
+++ trunk/docs/realworld_app_guide/en/src/main/docbook/modules/hiw.xml	2009-04-21 15:39:27 UTC (rev 13740)
@@ -408,5 +408,394 @@
             
       </section>
       
+      <section>
+            <title>Slide show</title>
+            
+            <para>The slide-show feature in the Photo Album Demo can be enabled by clicking &quot;Start Slideshow&quot; link from two different places in the application: 
+                  1) from user'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  <code>startSlideshow()</code> method of <code>SlideshowManager.java</code> has two implementations. 
+                  The first implementation is designed to activate the slide-show from an album preview (<code>/image/albumInfo.xhtml</code>) 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 implementation 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 implementations of <code>startSlideshow()</code> method set active property to true. 
+                  This <code>true</code> makes two important slide-show parts (slide-show modal panel and slide-show poller) render. 
+            </para>
+            <para>
+                  The slide-show 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 <emphasis role="bold"><property>&lt;ui:include&gt;</property></emphasis> 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>
+                  The modal panel is always rendered on the page in a hidden state. 
+                  Activating the slide-show renders the main area, so the slide-show modal panel appears in the closest to an observer layer.
+            </para>
+
+            <programlisting role="XML"><![CDATA[...
+<a4j:commandLink styleClass="slideshow-link"
+                        actionListener="#{slideshow.startSlideshow()}" 
+                        reRender="slideShowForm, mainArea">	
+	...
+</a4j:commandLink>
+...]]></programlisting>
+            <para>
+                  Slide-show poller is enabled if the slide-show is  activated:
+            </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 slide-show 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>). 
+                  When the <emphasis role="bold"><property>&lt;a4j:poll&gt;</property></emphasis> component receives a new image it renders the slideShowImage area (<code>/web/src/main/webapp/image/slideshow.xhtml</code>):
+            </para>
+            <programlisting role="XML"><![CDATA[...
+<h:panelGroup id="slideshowImage">	
+      <a4j:mediaOutput id="imgSlideShow" 
+                  element="img"
+                  styleClass="main-image"
+                  createContent="#{imageLoader.paintImage}"
+                  style="opacity: 0.1"
+                  value="#{slideshow.selectedImage != null? fileManager.transformPath(slideshow.selectedImage.path, '_medium'):null}">
+            <rich:toolTip followMouse="true" 
+                        direction="top-right"
+                        showDelay="500" 
+                        styleClass="tooltip">
+                  <span style="white-space: nowrap"> #{slideshow.selectedImage.description} </span>
+            </rich:toolTip>
+      </a4j:mediaOutput>
+</h:panelGroup>
+...]]></programlisting>
+            
+            <para>
+                  The <emphasis role="bold"><property>a4j:mediaOtuput</property></emphasis> component has a value attribute that takes a path to photos as a value and renders photos with the help of a <emphasis><property>createContent</property></emphasis> attribute. The showNextImage works cyclically. 
+            </para>
+            
+            <para>
+                  There is <emphasis role="bold"><property>rich:effect</property></emphasis> that makes rendering process look more effective (<code>web/src/main/webapp/includes/image/slideshow.xhtml</code>):
+            </para>
+            <programlisting role="XML"><![CDATA[...
+<rich:effect name="hidePictureEffect" type="Opacity" params="duration:0.4, from:1.0, to:0.0" for="imgSlideShow" />
+<rich:effect name="showPictureEffect" type="Opacity" params="duration:0.4, from:0.1, to:1.0" for="imgSlideShow" />
+...]]></programlisting>
+            
+            <para>
+                  The described above implements a modal panel with photos that change each other in order they store in an album.       
+            </para>
+            <figure>
+                  <title>Slide show</title>
+                  <mediaobject>
+                        <imageobject>
+                              <imagedata fileref="images/slide_show.png"/>
+                        </imageobject>
+                  </mediaobject>
+            </figure>
+            
+            <para>
+                  To quit the slide-show user clicks &quot;Close window&quot; button on the slide-show panel and <code>stopSlideshow()</code> method is activated. 
+            </para>
+            <programlisting role="JAVA"><![CDATA[...
+ at Observer("stopSlideshow")
+      public void stopSlideshow(){
+            active = false;
+            this.selectedImage = null;
+            this.slideshowIndex = 0;
+      }
+...]]></programlisting>
+            
+      </section>
       
+      <section>
+            <title>Image Size control</title>
+            
+            <section>
+                  <title>Building the control with &lt;rich:inputNumberSlider&gt;</title>
+            <para>
+                  The <emphasis role="bold"><property>rich:inputNumberSlider</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 image size. 
+                  The component is included into the page with the help of <emphasis role="bold"><property>ui:include</property></emphasis>:
+            </para>
+                  <programlisting role="XML"><![CDATA[...
+<ui:include src="/includes/misc/inputNumberSlider.xhtml"/>
+...]]></programlisting> 
+            
+            <para>
+                  Now let's have a look at <code>src/main/webapp/includes/misc/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>
+                    On each slider position change the <emphasis role="bold"><property>a4j:support</property></emphasis> component invokes an Ajax request that passes a new set value into the <code>ImageSizeHelper.java</code> class. 
+                    This class saves new photo dimensions, processes and assigns new values to photo related attributes (a CSS class for new photo size, postfix for a new file name, image background):
+              </para>
+                  <programlisting role="JAVA"><![CDATA[...
+ public static enum ImageDimension {
+                  
+      SIZE_80(80), SIZE_120(120), SIZE_160(160), SIZE_200(200);
+                  
+      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);
+            filePostfix = FILE_POSTFIX + x;
+      }
+      ...]]></programlisting>
+                  
+                  <para>
+                        After the <code>ImageSizeHelper.java</code> is worked out  the <emphasis role="bold"><property>a4j:support</property></emphasis> component renders user photos 
+                        (more exactly, the <emphasis role="bold"><property>h:panelGroup</property></emphasis> with <code>userAlbumImages</code> id  that contains user photos) 
+                        correspondingly to a new set 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, tree">					
+                                    <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, tree" id="dragSource" dragIndicator="dragIndicator"
+                                                            dragType="image" dragValue="#{image}">
+                                                <rich:dndParam id="dragParam" name="label" value="#{image.name}" />
+                                          </rich:dragSupport>
+                                          <ui:include src="/includes/contextMenu/CMForImage.xhtml" >
+                                                <ui:param name="image" value="#{image}" />
+                                          </ui:include>
+                                    </a4j:mediaOutput>
+                              </a4j:commandLink>
+                              <br/>
+                        </h:panelGroup>
+                  </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&lt;</property></emphasis> is rendered at first 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>
+            
+            </section>
+            
+            <section>
+                  <title>Links in Photo Album Demo. Using the &lt;a4j:commandLink&gt;</title>
+                  <para>
+                        The main difference between <emphasis role="bold"><property>&lt;h:commandLink&gt;</property></emphasis> component is a) Ajax request that is generated on a click and b) dynamic rerendering of the page after a response comes back. 
+                        It's not necessary to plug any support into the component, as Ajax support is already built-in. 
+                  </para>
+                  <para>
+                        The <emphasis role="bold"><property>&lt;a4j:commandLink&gt;</property></emphasis> component is used widely in the application. 
+                        In the following example clicking on the &lt;Edit&gt; link will rerender the main ares (watching area) of the application and open an album edit form. 
+                        Each album has its owner and only owner can edit the album contents. 
+                        The link &lt;Edit&gt; will be rendered only if the current logged-in user is the owner of this album: the <emphasis><property>&quot;rendered&quot;</property></emphasis> attribute refers to the owner id and compares it with the  current user id:
+                  </para>
+                  <programlisting role="XML"><![CDATA[...
+<a4j:commandLink rendered="#{model.selectedAlbum.owner.id == user.id}"
+            value="#{messages['album.edit']} "
+            actionListener="#{controller.startEditAlbum(model.selectedAlbum)}"
+            reRender="mainArea">
+</a4j:commandLink>
+...]]></programlisting>
+                  <para>
+                        The <emphasis><property>&lt;value&gt;</property></emphasis> attribute (text that will appear on the link) is picked up from the <code>messages_en.properties</code> file. 
+                        Such property files are very useful e.g. for multi language applications. 
+                        Each property is saved in the format &quot;name—value&quot;. 
+                        Let's have a look  at this file in the JBDS:
+                  </para>
+                  <figure>
+                        <title>Image size control</title>
+                        <mediaobject>
+                              <imageobject>
+                                    <imagedata fileref="images/messages_en_property.png"/>
+                              </imageobject>
+                        </mediaobject>
+                  </figure>
+            </section>
+            
+         <section>
+               <title>Error Reports in the Real World Demo</title>
+               <para>The main page of the application <code>web/src/main/webapp/index.xhtml</code> includes <code>web/src/main/webapp/includes/misc/errorPanel.xhtml</code>. 
+                     The error panel itself is always rendered but hidden if no error appears. The listing below shows the part of <code>errorPanel.xhtml</code> page: 
+               </para>
+               <programlisting role="XML"><![CDATA[...
+<a4j:outputPanel id="errors" ajaxRendered="true">
+      <h:panelGroup rendered="#{errorHandlerBean.errorExist}">
+            <rich:modalPanel id="errorPanel" 
+                        showWhenRendered="true" 
+                        minWidth="300" 
+                        minHeight="200" 
+                        autosized="true">
+                  ...
+            </rich:modalPanel>
+      </h:panelGroup>
+</a4j:outputPanel>
+...]]></programlisting>
+               <para>
+                     Error checking happens each time the Ajax request is invoked by user activity. 
+                     The <emphasis role="bold"><property>rich:modalPanel</property></emphasis> which wrapped with <emphasis role="bold"><property>&lt;h:panelGroup&gt;</property></emphasis> is rendered in case an error occurs, 
+                     its <emphasis><property>&quot;rendered&quot;</property></emphasis> attribute is binded  with <code>isErrorExist</code> boolean method of <code>errorHandlerBean</code> class.
+               </para>
+               <programlisting role="XML"><![CDATA[...
+package org.richfaces.realworld.ui;
+...
+ at Name("errorHandlerBean")
+ at Scope(ScopeType.EVENT)
+ at AutoCreate
+public class ErrorHandlerBean {
+      private List<String> errors = new ArrayList<String>();
+
+      public List<String> getErrors() {
+            return errors;
+      }
+	
+      public boolean isErrorExist(){
+            return errors.size() > 0 ;
+      }
+	
+      @Observer(Constants.ADD_ERROR_EVENT)
+      public void addToErrors(String e){
+            errors.add(e);
+      }
+}
+...]]></programlisting>
+               
+         <para>
+               The <code>addToErrors</code> method is annotated with <code>@Observer</code> annotation which observes all methods in the application with <code>ADD_ERROR_EVENT</code> annotation.
+         </para>
+         
+         </section>
+            
+                        
+                        
+      </section>
+      
+      
 </chapter>




More information about the richfaces-svn-commits mailing list