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><IMG></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 }