/* * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package com.arsdigita.bebop; import com.arsdigita.bebop.event.PrintEvent; import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.util.Assert; import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.xml.Element; /** * A text label. The label can be used to generate either some static, fixed * text or a new text string for every request. To set a new text string for * each request, use the {@link * #setLabel(String,PageState)} method. * * @author David Lutterkort * @version $Id: Label.java 287 2005-02-22 00:29:02Z sskracic $ */ public class Label extends BlockStylable implements Cloneable { private static final String NO_LABEL = ""; public static final String BOLD = "b"; public static final String ITALIC = "i"; // the default label private GlobalizedMessage m_label; // a requestlocal set of labels (to avoid printlisteners) private RequestLocal m_requestLabel = new RequestLocal(); private String m_fontWeight; private boolean m_escaping; private PrintListener m_printListener; /** * Creates a new * Label with empty text. */ public Label() { this(NO_LABEL); } /** * Creates a new * Label with the specified text. * * @param label the text to display * * @deprecated refactor to use Label(GlobalizedMessage label) instad */ public Label(String label) { this(label, true); } /** * Creates a new Label with the specified text and * output escaping turned on if * escaping is * true. * * The setting foroutput escaping affects how markup in the * label is handled. For example: * * @param label the text to display * @param true if output escaping will be in effect; * false if output escaping will be disabled * * @deprecated refactor to Label(GlobalizedMessage label, boolean escaping) * instead */ public Label(String label, boolean escaping) { setLabel(label); setOutputEscaping(escaping); } /** *

Creates a new label with the specified text.

* * @param label the text to display */ public Label(GlobalizedMessage label) { this(label, true); } /** * Creates a new label with the specified text as GlobalizedMessage * and fontweight. * * @param label The text to display as GlobalizedMessage * @param fontWeight The fontWeight e.g., Label.BOLD. Whether it has any * effect depends on the theme! Take it just as a hint. */ public Label(GlobalizedMessage label, String fontWeight) { this(label, true); m_fontWeight = fontWeight; } /** *

Creates a new label with the specified text as GlobalizedMessage * and output escaping turned on if * escaping is * true.

* * @param label the text to display as GlobalizedMessage * @param escaping Whether or not to perform output escaping */ public Label(GlobalizedMessage label, boolean escaping) { setLabel(label); setOutputEscaping(escaping); } /** * Creates a new Label that uses the print listener to * generate output. * * @param l the print listener used to produce output */ public Label(PrintListener l) { this(); addPrintListener(l); } /** * Creates a new label with the specified text and fontweight. * * @param label The text to display * @param fontWeight The fontWeight e.g., Label.BOLD * * @deprecated without direct replacement. Refactor to use * Label(GlobalizedMEssage) instead and modify the theme to * use proper text marking. (Or use setFontWeight separately. */ public Label(String label, String fontWeight) { this(label, true); m_fontWeight = fontWeight; } /** * . * Although it is not recommended, this method may be overridden to * dynamically generate the text of the label. Overriding code may need the * page state.

If possible, derived classes should override * {@link #getLabel()} instead, which is called from this method. As long as * we don't have a static method to obtain ApplicationContext, this is a way * to get the RequestContext (that is, to determine the locale). When * ApplicationContext gets available, that will become the suggested way for * overriding code to get context. * * @param state the current page state * @return the string produced for this label */ public String getLabel(PageState state) { return (String) getGlobalizedMessage(state).localize(state.getRequest()); } /** * . * * This method may be overridden to dynamically generate the default text of * the label. * * @return the string produced for this label. * * @deprecated Use {@link #getGlobalizedMessage()} */ public String getLabel() { return getGlobalizedMessage().getKey(); } /** *

This should really be getLabel(), but since it was marked STABLE I * can't change its return type.

* * @return the default label to display. */ public GlobalizedMessage getGlobalizedMessage() { return getGlobalizedMessage(null); } /** *

This should really be getLabel(), but since it was marked STABLE I * can't change its return type.

* * @param the current PageState * @return the label to display for this request, or if state is null, the * default label */ public GlobalizedMessage getGlobalizedMessage(PageState state) { if (state != null) { GlobalizedMessage dynlabel = (GlobalizedMessage) m_requestLabel.get(state); if (dynlabel != null) { return dynlabel; } } return m_label; } /** * Sets new default text for this Label. * * @param label The new label text; will be used as a key into the current * ResourceBundle if possible, or displayed literally. * @deprecated refactor to use * @see setLabel(GlobalizedMessage) instead! */ public void setLabel(String label) { setLabel(label, null); } /** * Sets new request-specific text for this Label to use on this request. If * state is null, then sets the default text instead. * * @param label The new label text; will be used as a key into the current * ResourceBundle if possible, or displayed literally. * @param state the page state * @pre state == null implies !isLocked() * @deprecated refactor to use * @see setLabel(GlobalizedMessage, PageState) instead! */ public void setLabel(String label, PageState state) { if (label == null || label.length() == 0) { label = " "; } setLabel(new GlobalizedMessage(label), state); } /** * Sets the text for this label using a GlobalizedMessage. * * @param label The GlobalizedMessage containing the label text or the * lookup key to use in the ResourceBundle * @param state the current page state; if null, sets the default text for * all requests. * @pre state == null implies !isLocked() */ public void setLabel(GlobalizedMessage label, PageState state) { if (state == null) { Assert.isUnlocked(this); m_label = label; } else { m_requestLabel.set(state, label); } } /** * Sets the default text for this Label. * * @param label The GlobalizedMessage containing the label text or the * lookup key to use in the ResourceBundle */ public void setLabel(GlobalizedMessage label) { setLabel(label, null); } public final boolean getOutputEscaping() { return m_escaping; } /** * Controls whether output is escaped during transformation, by default * true. If true, it will be printed literally, and the user will see * <b>. When false, the browser will interpret as a bold tag. */ public final void setOutputEscaping(boolean escaping) { m_escaping = escaping; } public final String getFontWeight() { return m_fontWeight; } public void setFontWeight(String fontWeight) { Assert.isUnlocked(this); m_fontWeight = fontWeight; } /** * Adds a print listener. Only one print listener can be set for a label, * since the * PrintListener is expected to modify the target of the * PrintEvent. * * @param listener the print listener * @throws IlegalArgumentException if listener is null. * @throws IllegalStateException if a print listener has previously been * added. * @pre listener != null */ public void addPrintListener(PrintListener listener) throws IllegalStateException, IllegalArgumentException { if (listener == null) { throw new IllegalArgumentException("Argument listener can not be null"); } if (m_printListener != null) { throw new IllegalStateException("Too many listeners. Can only have one"); } m_printListener = listener; } /** * Removes a previously added print listener. If * listener is not the listener that was added with {@link #addPrintListener * addPrintListener}, an IllegalArgumentException will be thrown. * * @param listener the listener that was added with * addPrintListener * @throws IllegalArgumentException if listener is not the * currently registered print listener or is null. * @pre listener != null */ public void removePrintListener(PrintListener listener) throws IllegalArgumentException { if (listener == null) { throw new IllegalArgumentException("listener can not be null"); } if (listener != m_printListener) { throw new IllegalArgumentException("listener is not registered with this widget"); } m_printListener = null; } public void generateXML(PageState state, Element parent) { if (!isVisible(state)) { return; } Label target = firePrintEvent(state); Element label = parent.newChildElement("bebop:label", BEBOP_XML_NS); target.exportAttributes(label); String weight = target.getFontWeight(); if (weight != null && weight.length() > 0) { label.addAttribute("weight", weight); } if (!target.m_escaping) { label.addAttribute("escape", "yes"); } else { label.addAttribute("escape", "no"); } String key = getGlobalizedMessage().getKey().substring(getGlobalizedMessage().getKey().lastIndexOf(".") + 1); // This if clause is needed to prevent printing of keys if the GlobalizedMessage was created from a String by this class if(!key.equals(target.getLabel(state))) { label.addAttribute("key", key); } /* * This may break with normal JDOM. We may need to have a node * for the case where there is no weight. The problem comes in that * setText *may* kill the other content in the node. It will kill the * other text, so it may be a good idea anyways. */ label.setText(target.getLabel(state)); } protected Label firePrintEvent(PageState state) { Label l = this; if (m_printListener != null) { try { l = (Label) this.clone(); m_printListener.prepare(new PrintEvent(this, state, l)); } catch (CloneNotSupportedException e) { throw new RuntimeException( "Couldn't clone Label for PrintListener. " + "This probably indicates a serious programming error: " + e.getMessage()); } } return l; } }