/* * Copyright 2008 Eckhart Arnold (eckhart_arnold@hotmail.com). * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package de.eckhartarnold.client; import java.lang.String; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.safehtml.shared.OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml; /** * Displays the image caption of the currently * displayed slide of a {@link Slideshow}. * * <p>The caption may contain * simple text or HTML code. */ public class Caption extends Composite implements SlideshowListener, ResizeListener { public static final int NO_SPACING = 0, TOP_SPACING = 1, BOTTOM_SPACING = 2; private Slideshow slideshow; private SafeHtml[] captions; private SafeHtml[] stuffings; private HTML htmlLabel; private int fontSize; private int current = -1; private OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml spacer, emptySpacer; private int spacing = -1; /** * Creates a new <code>Caption</code> object. The <code>captions</code> * parameter must contain the caption strings for the images of the * <code>slideshow</code> in the same order as the images in the slide show. * * @param slideshow the <code>Slideshow</code> for which the captions are * to be displayed * @param captions an array of safe HTML strings that contains the HTML formatted * captions. The length of the array must be the same as * number of images in the slide show. */ public Caption(Slideshow slideshow, SafeHtml[] captions) { assert slideshow.size() == captions.length; this.slideshow = slideshow; this.captions = captions; htmlLabel = new HTML(); htmlLabel.setStyleName("caption"); fontSize = 9; htmlLabel.addStyleDependentName(fontSize+"px"); setupSpacers(); setSpacing(BOTTOM_SPACING); initWidget(htmlLabel); onResized(); slideshow.addSlideshowListener(this); } /** * Copy constructor for cloning captions. Cloning captions is used by * {@link CaptionOverlay} in order to imitate shadowed text, which * unfortunately some browsers do not support natively. */ public Caption(Caption other) { this.slideshow = other.slideshow; this.captions = other.captions; this.stuffings = other.stuffings; this.fontSize = other.fontSize; this.current = other.current; this.spacing = other.spacing; this.spacer = other.spacer; this.emptySpacer = other.emptySpacer; htmlLabel = new HTML(); htmlLabel.setStyleName("caption"); htmlLabel.addStyleDependentName(fontSize+"px"); initWidget(htmlLabel); htmlLabel.setHTML(getText()); onResized(); slideshow.addSlideshowListener(this); } // /** // * Clones the <code>Caption</code> object. Cloning captions is used by // * {@link CaptionOverlay} in order to imitate shadowed text, which // * unfortunately most browsers do not support natively. // */ // public Caption clone() { // Caption copy = new Caption(slideshow, captions); // copy.fontSize = fontSize; // copy.htmlLabel.setHTML(getText()); // return copy; // } /** * Returns the font size of the caption. * * @return font size in pixel */ public int getFontSize() { return fontSize; } /** * Returns the spacing property, which can be either NO_SPACING, * TOP_SPACING or BOTTOM_SPACING depending on whether spacings * is used and whether it is tuned for captions appearing above or below * the slides. */ public int getSpacing() { return spacing; } /** * Returns the current Text the caption displays. * * @return the HTML formatted Text of the caption */ public SafeHtml getText() { if (current == -1) return (spacing == NO_SPACING) ? emptySpacer : spacer; else { SafeHtmlBuilder builder = new SafeHtmlBuilder(); if (spacing == BOTTOM_SPACING) { builder.append(stuffings[current]); builder.append(captions[current]); return builder.toSafeHtml(); } else if (spacing == TOP_SPACING) { builder.append(captions[current]); builder.append(stuffings[current]); return builder.toSafeHtml(); } else { return captions[current]; } } } /** * Returns true, if the caption is empty (at the moment). */ public boolean isEmpty() { SafeHtml text = getText(); return text.equals(spacer) || text.equals(emptySpacer); } /* (non-Javadoc) * @see de.eckhartarnold.client.SlideshowListener#onFade() */ public void onFade() { current = -1; htmlLabel.setHTML(getText()); } /* (non-Javadoc) * @see de.eckhartarnold.client.SlideshowListener#onShow() */ public void onShow(int slideNr) { current = slideNr; htmlLabel.setHTML(getText()); } /* (non-Javadoc) * @see de.eckhartarnold.client.SlideshowListener#onStart() */ public void onStart() { } /* (non-Javadoc) * @see de.eckhartarnold.client.SlideshowListener#onStop() */ public void onStop() { } /* (non-Javadoc) * @see de.eckhartarnold.client.ResizeListener#onResized() */ public void onResized() { int w = slideshow.getImagePanel().getOffsetWidth(); int h = Toolbox.getOffsetHeight(slideshow.getImagePanel()); if (w < h) h = w; h /= 32; int[] steps = { 9, 10, 12, 14, 18, 24, 32, 40, 48, 64 }; int i = 0; while (h > steps[i] && i < steps.length) i++; htmlLabel.removeStyleDependentName(fontSize+"px"); fontSize = steps[i]; htmlLabel.addStyleDependentName(fontSize+"px"); } /* (non-Javadoc) * @see de.eckhartarnold.client.ResizeListener#prepareResized() */ public void prepareResized() { } /** * Sets the spacing property. Spacers ("<br /> ") are used to make * sure that every caption has the same height, in case different captions * contain different numbers of line breaks. They will be added either * before the caption text (BOTTOM_SPACING) or after the caption text * (TOP_SPACING) or not at all (NO_SPACING). * * @param TOP_SPACING, BOTTOM_SPACING or NO_SPCAING depending on the type * of spacing to be used. */ public void setSpacing(int spacing) { assert spacing == BOTTOM_SPACING || spacing == TOP_SPACING || spacing == NO_SPACING; this.spacing = spacing; htmlLabel.setHTML(getText()); } /** * Initializes the fields <code>stuffings, spacer, emptySpacer</code> * with spacers (concatenations of "<br /> "). To be called by * the constructor. */ private void setupSpacers() { int[] lineBreaks = new int[captions.length]; int maxLineBreaks = 0; for (int k = 0; k < captions.length; k++) { String cap = captions[k].asString(); int i = 0, count = 0; while (i < cap.length() && i >= 0) { i = cap.indexOf("<br", i); if (i >= 0) { count++; i++; } } lineBreaks[k] = count; if (count > maxLineBreaks) maxLineBreaks = count; } String[] brCascade = new String[maxLineBreaks+1]; brCascade[0] = ""; for (int k = 1; k < brCascade.length; k++) brCascade[k] = brCascade[k-1] + "<br /> "; spacer = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml( brCascade[brCascade.length-1]); emptySpacer = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml(""); stuffings = new SafeHtml[captions.length]; for (int k = 0; k < captions.length; k++) { stuffings[k] = new OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml( brCascade[maxLineBreaks-lineBreaks[k]]); } } }