001/**
002 * Copyright 2005-2015 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.uif.element;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krad.datadictionary.parse.BeanTag;
020import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
021import org.kuali.rice.krad.datadictionary.parse.BeanTags;
022import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
023import org.kuali.rice.krad.datadictionary.validator.Validator;
024import org.kuali.rice.krad.uif.component.Component;
025import org.kuali.rice.krad.uif.util.ComponentFactory;
026import org.kuali.rice.krad.uif.util.LifecycleElement;
027
028/**
029 * Content element that renders a HTML <code>&lt;IMG&gt;</code> tag
030 *
031 * @author Kuali Rice Team (rice.collab@kuali.org)
032 */
033@BeanTag(name = "image", parent = "Uif-Image")
034public class Image extends ContentElementBase {
035    private static final long serialVersionUID = -3911849875276940507L;
036
037    private String source;
038    private String altText;
039    private String height;
040    private String width;
041
042    private boolean captionHeaderPlacementAboveImage;
043
044    private String captionHeaderText;
045    private Header captionHeader;
046
047    private String cutlineText;
048    private Message cutlineMessage;
049
050    public Image() {
051        super();
052
053        altText = "";
054    }
055
056    /**
057     * The following initialization is performed:
058     *
059     * <ul>
060     * <li>Initializes the cutline message and caption header components if necessary</li>
061     * </ul>
062     *
063     * {@inheritDoc}
064     */
065    @Override
066    public void performInitialization(Object model) {
067        super.performInitialization(model);
068
069        if ((StringUtils.isNotBlank(captionHeaderText) || (getPropertyExpression("captionHeaderText") != null)) && (
070                captionHeader == null)) {
071            captionHeader = ComponentFactory.getImageCaptionHeader();
072        }
073
074        if ((StringUtils.isNotBlank(cutlineText) || (getPropertyExpression("cutlineText") != null)) && (cutlineMessage
075                == null)) {
076            cutlineMessage = ComponentFactory.getImageCutlineMessage();
077        }
078    }
079
080    /**
081     * Performs the following steps
082     *
083     * <ul>
084     * <li>Set the caption header text on the caption header</li>
085     * <li>Set the cutline text on the cutline message</li>
086     * </ul>
087     *
088     * {@inheritDoc}
089     */
090    @Override
091    public void performApplyModel(Object model, LifecycleElement parent) {
092        super.performApplyModel(model, parent);
093
094        if (StringUtils.isNotBlank(captionHeaderText)) {
095            captionHeader.setHeaderText(captionHeaderText);
096        }
097
098        if (StringUtils.isNotBlank(cutlineText)) {
099            cutlineMessage.setMessageText(cutlineText);
100        }
101    }
102
103    /**
104     * returns the URL of this image
105     *
106     * @return the URL of this image.
107     */
108    @BeanTagAttribute
109    public String getSource() {
110        return this.source;
111    }
112
113    /**
114     * Sets the URL of this image
115     *
116     * @param source the URL of this image
117     */
118    public void setSource(String source) {
119        this.source = source;
120    }
121
122    /**
123     * Provides alternate information for the image element
124     *
125     * <p>The altText property specifies an alternate text for an image. It is displayed by the browser
126     * if the image cannot be displayed.  This is especially important for accessibility, because screen
127     * readers can't understand images, but rather will read aloud the alternative text assigned to them.
128     * <br>
129     * Some best practices:
130     * <ul>
131     * <li>spacer images, bullets, and icons should have the altText set to null or the empty string. This
132     * will prevent screen readers from announcing it.</li>
133     * <li>Make the altText message as short and succinct as possible</li>
134     * <li>Describe the content of the image and nothing more</li>
135     * </ul>
136     * </p>
137     *
138     * @return alternative information about this image
139     */
140    @BeanTagAttribute
141    public String getAltText() {
142        return this.altText;
143    }
144
145    /**
146     * Sets the alternate text property for this image
147     *
148     * @param altText the alternative information about the image
149     */
150    public void setAltText(String altText) {
151        this.altText = altText;
152    }
153
154    /**
155     * Returns the height style attribute of this image
156     *
157     * <p>
158     * The default unit of measure is pixels.<br>
159     * It is good practice to specify both the height and width attributes for an image.
160     * If these attributes are set, the space required for the image is reserved when the page is loaded.
161     * However, without these attributes, the browser does not know the size of the image. The effect will
162     * be that the page layout will change while the images load.
163     * </p>
164     *
165     * @return the height style attribute of this image
166     */
167    @BeanTagAttribute
168    public String getHeight() {
169        return this.height;
170    }
171
172    /**
173     * Sets the height style attribute of the image.
174     *
175     * @param height the height of the image
176     */
177    public void setHeight(String height) {
178        this.height = height;
179    }
180
181    /**
182     * Returns the width style attribute of the image
183     *
184     * <p>
185     * The default unit of measure is pixels.<br>
186     * It is good practice to specify both the height and width attributes for an image.
187     * If these attributes are set, the space required for the image is reserved when the page is loaded.
188     * However, without these attributes, the browser does not know the size of the image. The effect will
189     * be that the page layout will change while the images load.
190     * <p>
191     *
192     * @return the width of this image
193     */
194    @BeanTagAttribute
195    public String getWidth() {
196        return width;
197    }
198
199    /**
200     * Sets the width style attribute of the image
201     *
202     * @param width the width of this image
203     */
204    public void setWidth(String width) {
205        this.width = width;
206    }
207
208    /**
209     * Retrieves the caption text for this image
210     *
211     * <p>
212     * The caption text is a headline for the picture. It may be displayed either above or below the picture.
213     * </p>
214     *
215     * @return the caption
216     */
217    @BeanTagAttribute
218    public String getCaptionHeaderText() {
219        return captionHeaderText;
220    }
221
222    /**
223     * Sets the text displayed as of the caption for the picture
224     *
225     * @param captionHeaderText the caption text
226     */
227    public void setCaptionHeaderText(String captionHeaderText) {
228        this.captionHeaderText = captionHeaderText;
229    }
230
231    /**
232     * Retrieves the {@link Header} component used to display the caption for this image
233     *
234     * @return Header component which wraps the caption text.
235     */
236    @BeanTagAttribute
237    public Header getCaptionHeader() {
238        return captionHeader;
239    }
240
241    /**
242     * Sets the Header used to display the caption for this image
243     *
244     * @param captionHeader header component which wraps the caption text
245     */
246    public void setCaptionHeader(Header captionHeader) {
247        this.captionHeader = captionHeader;
248    }
249
250    /**
251     * Retrieves the cutline text for this image
252     *
253     * <p>
254     * The cutline text give more detailed information about the picture. Generally it describes
255     * the who, what, where, when of this image.
256     * </p>
257     *
258     * @return the cutline text.
259     */
260    @BeanTagAttribute
261    public String getCutlineText() {
262        return cutlineText;
263    }
264
265    /**
266     * Sets the cutline text that describes this image
267     *
268     * @param cutlineText the cutline text that describes this image
269     */
270    public void setCutlineText(String cutlineText) {
271        this.cutlineText = cutlineText;
272    }
273
274    /**
275     * Gets the {@link Message} component used to display the cutline.
276     *
277     * <p>
278     * Wrapping the cutline text with a Message component allows styling of the cutline text.
279     * </p>
280     *
281     * @return Message component wrapping the cutline
282     */
283    @BeanTagAttribute
284    public Message getCutlineMessage() {
285        return cutlineMessage;
286    }
287
288    /**
289     * Sets the Message component used to display the cutline for this image
290     *
291     * @param cutlineMessage Message
292     */
293    public void setCutlineMessage(Message cutlineMessage) {
294        this.cutlineMessage = cutlineMessage;
295    }
296
297    /**
298     * Specifies whether the image caption is to be displayed above or below the image
299     *
300     * @return true if the caption is to be displayed above the image. false if displayed below the image.
301     */
302    @BeanTagAttribute
303    public boolean isCaptionHeaderPlacementAboveImage() {
304        return captionHeaderPlacementAboveImage;
305    }
306
307    /**
308     * Sets whether the image caption is to be displayed above or below the image
309     *
310     * @param captionHeaderPlacementAboveImage true displays above image, false displays below image
311     */
312    public void setCaptionHeaderPlacementAboveImage(boolean captionHeaderPlacementAboveImage) {
313        this.captionHeaderPlacementAboveImage = captionHeaderPlacementAboveImage;
314    }
315
316    /**
317     * {@inheritDoc}
318     */
319    @Override
320    public void completeValidation(ValidationTrace tracer){
321        tracer.addBean(this);
322
323        // Checks that a source is set
324        if(getSource()==null){
325            if(!Validator.checkExpressions(this, "source")){
326                String currentValues [] = {"source ="+getSource()};
327                tracer.createError("Source must be set",currentValues);
328            }
329        }
330
331        // Checks that alt text is set
332        if(getAltText().compareTo("")==0){
333            if(Validator.checkExpressions(this, "altText")){
334                String currentValues [] = {"altText ="+getAltText()};
335                tracer.createWarning("Alt text should be set, violates accessibility standards if not set",currentValues);
336            }
337        }
338
339        super.completeValidation(tracer.getCopy());
340    }
341}