View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.element;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
20  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
21  import org.kuali.rice.krad.datadictionary.parse.BeanTags;
22  import org.kuali.rice.krad.datadictionary.validator.ErrorReport;
23  import org.kuali.rice.krad.datadictionary.validator.Validator;
24  import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
25  import org.kuali.rice.krad.uif.component.Component;
26  import org.kuali.rice.krad.uif.util.ComponentFactory;
27  import org.kuali.rice.krad.uif.view.View;
28  
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  /**
33   * Content element that renders a HTML <code>&lt;IMG&gt;</code> tag
34   *
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  @BeanTags({@BeanTag(name = "image-bean", parent = "Uif-Image"),
38          @BeanTag(name = "helpImage-bean", parent = "Uif-HelpImage"),
39          @BeanTag(name = "quickLookupImage-bean", parent = "Uif-QuickLookupImage"),
40          @BeanTag(name = "directInquiryImage-bean", parent = "Uif-DirectInquiryImage")})
41  public class Image extends ContentElementBase {
42      private static final long serialVersionUID = -3911849875276940507L;
43  
44      private String source;
45      private String altText;
46      private String height;
47      private String width;
48  
49      private boolean captionHeaderPlacementAboveImage;
50  
51      private String captionHeaderText;
52      private Header captionHeader;
53  
54      private String cutlineText;
55      private Message cutlineMessage;
56  
57      public Image() {
58          super();
59  
60          altText = "";
61      }
62  
63      /**
64       * The following initialization is performed:
65       *
66       * <ul>
67       * <li>Initializes the cutline message and caption header components if necessary</li>
68       * </ul>
69       *
70       * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View,
71       *      java.lang.Object)
72       */
73      @Override
74      public void performInitialization(View view, Object model) {
75          super.performInitialization(view, model);
76  
77          if ((StringUtils.isNotBlank(captionHeaderText) || (getPropertyExpression("captionHeaderText") != null)) && (
78                  captionHeader == null)) {
79              captionHeader = ComponentFactory.getImageCaptionHeader();
80              view.assignComponentIds(captionHeader);
81          }
82  
83          if ((StringUtils.isNotBlank(cutlineText) || (getPropertyExpression("cutlineText") != null)) && (cutlineMessage
84                  == null)) {
85              cutlineMessage = ComponentFactory.getImageCutlineMessage();
86              view.assignComponentIds(cutlineMessage);
87          }
88      }
89  
90      /**
91       * Performs the following steps
92       *
93       * <ul>
94       * <li>Set the caption header text on the caption header</li>
95       * <li>Set the cutline text on the cutline message</li>
96       * </ul>
97       *
98       * @see Component#performFinalize(org.kuali.rice.krad.uif.view.View, java.lang.Object,
99       * org.kuali.rice.krad.uif.component.Component)
100      */
101     @Override
102     public void performApplyModel(View view, Object model, Component parent) {
103         super.performApplyModel(view, model, parent);
104 
105         if (StringUtils.isNotBlank(captionHeaderText)) {
106             captionHeader.setHeaderText(captionHeaderText);
107         }
108 
109         if (StringUtils.isNotBlank(cutlineText)) {
110             cutlineMessage.setMessageText(cutlineText);
111         }
112     }
113 
114     /**
115      * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle()
116      */
117     @Override
118     public List<Component> getComponentsForLifecycle() {
119         List<Component> components = super.getComponentsForLifecycle();
120 
121         components.add(captionHeader);
122         components.add(cutlineMessage);
123 
124         return components;
125     }
126 
127     /**
128      * returns the URL of this image
129      *
130      * @return the URL of this image.
131      */
132     @BeanTagAttribute(name="source")
133     public String getSource() {
134         return this.source;
135     }
136 
137     /**
138      * Sets the URL of this image
139      *
140      * @param source the URL of this image
141      */
142     public void setSource(String source) {
143         this.source = source;
144     }
145 
146     /**
147      * Provides alternate information for the image element
148      *
149      * <p>The altText property specifies an alternate text for an image. It is displayed by the browser
150      * if the image cannot be displayed.  This is especially important for accessibility, because screen
151      * readers can't understand images, but rather will read aloud the alternative text assigned to them.
152      * <br>
153      * Some best practices:
154      * <ul>
155      * <li>spacer images, bullets, and icons should have the altText set to null or the empty string. This
156      * will prevent screen readers from announcing it.</li>
157      * <li>Make the altText message as short and succinct as possible</li>
158      * <li>Describe the content of the image and nothing more</li>
159      * </ul>
160      * </p>
161      *
162      * @return alternative information about this image
163      */
164     @BeanTagAttribute(name="altText")
165     public String getAltText() {
166         return this.altText;
167     }
168 
169     /**
170      * Sets the alternate text property for this image
171      *
172      * @param altText the alternative information about the image
173      */
174     public void setAltText(String altText) {
175         this.altText = altText;
176     }
177 
178     /**
179      * Returns the height style attribute of this image
180      *
181      * <p>
182      * The default unit of measure is pixels.<br>
183      * It is good practice to specify both the height and width attributes for an image.
184      * If these attributes are set, the space required for the image is reserved when the page is loaded.
185      * However, without these attributes, the browser does not know the size of the image. The effect will
186      * be that the page layout will change while the images load.
187      * </p>
188      *
189      * @return the height style attribute of this image
190      */
191     @BeanTagAttribute(name="height")
192     public String getHeight() {
193         return this.height;
194     }
195 
196     /**
197      * Sets the height style attribute of the image.
198      *
199      * @param height the height of the image
200      */
201     public void setHeight(String height) {
202         this.height = height;
203     }
204 
205     /**
206      * Returns the width style attribute of the image
207      *
208      * <p>
209      * The default unit of measure is pixels.<br>
210      * It is good practice to specify both the height and width attributes for an image.
211      * If these attributes are set, the space required for the image is reserved when the page is loaded.
212      * However, without these attributes, the browser does not know the size of the image. The effect will
213      * be that the page layout will change while the images load.
214      * <p>
215      *
216      * @return the width of this image
217      */
218     @BeanTagAttribute(name="width")
219     public String getWidth() {
220         return width;
221     }
222 
223     /**
224      * Sets the width style attribute of the image
225      *
226      * @param width the width of this image
227      */
228     public void setWidth(String width) {
229         this.width = width;
230     }
231 
232     /**
233      * Retrieves the caption text for this image
234      *
235      * <p>
236      * The caption text is a headline for the picture. It may be displayed either above or below the picture.
237      * </p>
238      *
239      * @return the caption
240      */
241     @BeanTagAttribute(name="captionHeaderText")
242     public String getCaptionHeaderText() {
243         return captionHeaderText;
244     }
245 
246     /**
247      * Sets the text displayed as of the caption for the picture
248      *
249      * @param captionHeaderText the caption text
250      */
251     public void setCaptionHeaderText(String captionHeaderText) {
252         this.captionHeaderText = captionHeaderText;
253     }
254 
255     /**
256      * Retrieves the {@link Header} component used to display the caption for this image
257      *
258      * @return Header component which wraps the caption text.
259      */
260     @BeanTagAttribute(name="captionHeader",type= BeanTagAttribute.AttributeType.SINGLEBEAN)
261     public Header getCaptionHeader() {
262         return captionHeader;
263     }
264 
265     /**
266      * Sets the Header used to display the caption for this image
267      *
268      * @param captionHeader header component which wraps the caption text
269      */
270     public void setCaptionHeader(Header captionHeader) {
271         this.captionHeader = captionHeader;
272     }
273 
274     /**
275      * Retrieves the cutline text for this image
276      *
277      * <p>
278      * The cutline text give more detailed information about the picture. Generally it describes
279      * the who, what, where, when of this image.
280      * </p>
281      *
282      * @return the cutline text.
283      */
284     @BeanTagAttribute(name="cutlineText")
285     public String getCutlineText() {
286         return cutlineText;
287     }
288 
289     /**
290      * Sets the cutline text that describes this image
291      *
292      * @param cutlineText the cutline text that describes this image
293      */
294     public void setCutlineText(String cutlineText) {
295         this.cutlineText = cutlineText;
296     }
297 
298     /**
299      * Gets the {@link Message} component used to display the cutline.
300      *
301      * <p>
302      * Wrapping the cutline text with a Message component allows styling of the cutline text.
303      * </p>
304      *
305      * @return Message component wrapping the cutline
306      */
307     @BeanTagAttribute(name="cutlineMessage",type= BeanTagAttribute.AttributeType.SINGLEBEAN)
308     public Message getCutlineMessage() {
309         return cutlineMessage;
310     }
311 
312     /**
313      * Sets the Message component used to display the cutline for this image
314      *
315      * @param cutlineMessage Message
316      */
317     public void setCutlineMessage(Message cutlineMessage) {
318         this.cutlineMessage = cutlineMessage;
319     }
320 
321     /**
322      * Specifies whether the image caption is to be displayed above or below the image
323      *
324      * @return true if the caption is to be displayed above the image. false if displayed below the image.
325      */
326     @BeanTagAttribute(name="captionHeaderPlacmentAboveImage")
327     public boolean isCaptionHeaderPlacementAboveImage() {
328         return captionHeaderPlacementAboveImage;
329     }
330 
331     /**
332      * Sets whether the image caption is to be displayed above or below the image
333      *
334      * @param captionHeaderPlacementAboveImage true displays above image, false displays below image
335      */
336     public void setCaptionHeaderPlacementAboveImage(boolean captionHeaderPlacementAboveImage) {
337         this.captionHeaderPlacementAboveImage = captionHeaderPlacementAboveImage;
338     }
339 
340     /**
341      * @see org.kuali.rice.krad.uif.component.Component#completeValidation
342      */
343     @Override
344     public void completeValidation(ValidationTrace tracer){
345         tracer.addBean(this);
346 
347         // Checks that a source is set
348         if(getSource()==null){
349             if(!Validator.checkExpressions(this, "source")){
350                 String currentValues [] = {"source ="+getSource()};
351                 tracer.createError("Source must be set",currentValues);
352             }
353         }
354 
355         // Checks that alt text is set
356         if(getAltText().compareTo("")==0){
357             if(Validator.checkExpressions(this, "altText")){
358                 String currentValues [] = {"altText ="+getAltText()};
359                 tracer.createWarning("Alt text should be set, violates accessibility standards if not set",currentValues);
360             }
361         }
362 
363         super.completeValidation(tracer.getCopy());
364     }
365 
366     /**
367      * @see org.kuali.rice.krad.uif.component.ComponentBase#copy()
368      */
369     @Override
370     protected <T> void copyProperties(T component) {
371         super.copyProperties(component);
372         Image imageCopy = (Image) component;
373         imageCopy.setAltText(this.altText);
374 
375         if (this.captionHeader != null) {
376             imageCopy.setCaptionHeader((Header)this.captionHeader.copy());
377         }
378 
379         imageCopy.setCaptionHeaderPlacementAboveImage(this.captionHeaderPlacementAboveImage);
380         imageCopy.setCaptionHeaderText(this.captionHeaderText);
381 
382         if (this.cutlineMessage != null) {
383             imageCopy.setCutlineMessage((Message)this.cutlineMessage.copy());
384         }
385 
386         imageCopy.setCutlineText(this.cutlineText);
387         imageCopy.setHeight(this.height);
388         imageCopy.setSource(this.source);
389         imageCopy.setWidth(this.width);
390     }
391 }