/* JLabel.java --
   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

import gnu.classpath.NotImplementedException;

import java.awt.Component;
import java.awt.Font;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleExtendedComponent;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleText;
import javax.swing.plaf.LabelUI;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;

/**
 * A component that displays a static text message and/or an icon.
 */
public class JLabel extends JComponent implements Accessible, SwingConstants
{

  /**
   * Provides the accessibility features for the <code>JLabel</code>
   * component.
   */
  protected class AccessibleJLabel
    extends JComponent.AccessibleJComponent
    implements AccessibleText, AccessibleExtendedComponent
  {
    
    /**
     * Returns the accessible name.
     * 
     * @return The accessible name.
     */
    public String getAccessibleName()
    {
      if (accessibleName != null)
        return accessibleName;
      if (text != null)
        return text;
      else
        return super.getAccessibleName();
    }
    
    /**
     * Returns the accessible role for the <code>JLabel</code> component.
     *
     * @return {@link AccessibleRole#LABEL}.
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.LABEL;
    }
    
    /**
     * Returns the selected text. This is null since JLabels
     * are not selectable.
     *
     * @return <code>null</code> because JLabels cannot have selected text
     */
    public String getSelectedText()
    {
      // We return null here since JLabel's text is not selectable.
      return null;
    }

    /**
     * Returns the start index of the selected text.
     *
     * @return the start index of the selected text
     */
    public int getSelectionStart()
    {
      // JLabel don't have selected text, so we return -1 here.
      return -1;
    }

    /**
     * Returns the end index of the selected text.
     *
     * @return the end index of the selected text
     */
    public int getSelectionEnd()
    {
      // JLabel don't have selected text, so we return -1 here.
      return -1;
    }

    /**
     * Returns an {@link AttributeSet} that reflects the text attributes of
     * the specified character. We return an empty
     * <code>AttributeSet</code> here, because JLabels don't support text
     * attributes (at least not yet).
     *
     * @param index the index of the character
     *
     * @return an {@link AttributeSet} that reflects the text attributes of
     *         the specified character
     */
    public AttributeSet getCharacterAttribute(int index)
    {
      // FIXME: Return null here for simple labels, and query the HTML
      // view for HTML labels.
      return new SimpleAttributeSet();
    }

    /**
     * Returns the character, word or sentence at the specified index. The
     * <code>part</code> parameter determines what is returned, the character,
     * word or sentence after the index.
     *
     * @param part one of {@link AccessibleText#CHARACTER},
     *             {@link AccessibleText#WORD} or
     *             {@link AccessibleText#SENTENCE}, specifying what is returned
     * @param index the index
     *
     * @return the character, word or sentence after <code>index</code>
     */
    public String getAtIndex(int part, int index)
    {
      String result = "";
      int startIndex = -1;
      int endIndex = -1;
      switch(part)
        {
        case AccessibleText.CHARACTER:
          result = String.valueOf(text.charAt(index));
          break;
        case AccessibleText.WORD:
          startIndex = text.lastIndexOf(' ', index);
          endIndex = text.indexOf(' ', startIndex + 1);
          if (endIndex == -1)
            endIndex = startIndex + 1;
          result = text.substring(startIndex + 1, endIndex);
          break;
        case AccessibleText.SENTENCE:
        default:
          startIndex = text.lastIndexOf('.', index);
          endIndex = text.indexOf('.', startIndex + 1);
          if (endIndex == -1)
            endIndex = startIndex + 1;
          result = text.substring(startIndex + 1, endIndex);
          break;
        }
      return result;
    }

    /**
     * Returns the character, word or sentence after the specified index. The
     * <code>part</code> parameter determines what is returned, the character,
     * word or sentence after the index.
     *
     * @param part one of {@link AccessibleText#CHARACTER},
     *             {@link AccessibleText#WORD} or
     *             {@link AccessibleText#SENTENCE}, specifying what is returned
     * @param index the index
     *
     * @return the character, word or sentence after <code>index</code>
     */
    public String getAfterIndex(int part, int index)
    {
      String result = "";
      int startIndex = -1;
      int endIndex = -1;
      switch(part)
        {
        case AccessibleText.CHARACTER:
          result = String.valueOf(text.charAt(index + 1));
          break;
        case AccessibleText.WORD:
          startIndex = text.indexOf(' ', index);
          endIndex = text.indexOf(' ', startIndex + 1);
          if (endIndex == -1)
            endIndex = startIndex + 1;
          result = text.substring(startIndex + 1, endIndex);
          break;
        case AccessibleText.SENTENCE:
        default:
          startIndex = text.indexOf('.', index);
          endIndex = text.indexOf('.', startIndex + 1);
          if (endIndex == -1)
            endIndex = startIndex + 1;
          result = text.substring(startIndex + 1, endIndex);
          break;
        }
      return result;
    }

    /**
     * Returns the character, word or sentence before the specified index. The
     * <code>part</code> parameter determines what is returned, the character,
     * word or sentence before the index.
     *
     * @param part one of {@link AccessibleText#CHARACTER},
     *             {@link AccessibleText#WORD} or
     *             {@link AccessibleText#SENTENCE}, specifying what is returned
     * @param index the index
     *
     * @return the character, word or sentence before <code>index</code>
     */
    public String getBeforeIndex(int part, int index)
    {
      String result = "";
      int startIndex = -1;
      int endIndex = -1;
      switch(part)
        {
        case AccessibleText.CHARACTER:
          result = String.valueOf(text.charAt(index - 1));
          break;
        case AccessibleText.WORD:
          endIndex = text.lastIndexOf(' ', index);
          if (endIndex == -1)
            endIndex = 0;
          startIndex = text.lastIndexOf(' ', endIndex - 1);
          result = text.substring(startIndex + 1, endIndex);
          break;
        case AccessibleText.SENTENCE:
        default:
          endIndex = text.lastIndexOf('.', index);
          if (endIndex == -1)
            endIndex = 0;
          startIndex = text.lastIndexOf('.', endIndex - 1);
          result = text.substring(startIndex + 1, endIndex);
          break;
        }
      return result;
    }

    /**
     * Returns the caret position. This method returns -1 because JLabel don't
     * have a caret.
     *
     * @return the caret position
     */
    public int getCaretPosition()
    {
      return -1;
    }

    /**
     * Returns the number of characters that are displayed by the JLabel.
     *
     * @return the number of characters that are displayed by the JLabel
     */
    public int getCharCount()
    {
      // FIXME: Query HTML view for HTML labels.
      return text.length();
    }

    /**
     * Returns the bounding box of the character at the specified index.
     *
     * @param index the index of the character that we return the
     *        bounds for
     *
     * @return the bounding box of the character at the specified index
     */
    public Rectangle getCharacterBounds(int index)
      throws NotImplementedException
    {
      // FIXME: Implement this correctly.
      return new Rectangle();
    }

    /**
     * Returns the index of the character that is located at the specified
     * point.
     *
     * @param point the location that we lookup the character for
     *
     * @return the index of the character that is located at the specified
     *         point
     */
    public int getIndexAtPoint(Point point)
      throws NotImplementedException
    {
      // FIXME: Implement this correctly.
      return 0;
    }
  }

  private static final long serialVersionUID = 5496508283662221534L;

  static final String LABEL_PROPERTY = "labeledBy";

  /**
   * The Component the label will give focus to when its mnemonic is
   * activated.
   */
  protected Component labelFor;

  /** The label's text. */
  transient String text;

  /** Where the label will be positioned horizontally. */
  private transient int horizontalAlignment = LEADING;

  /** Where the label text will be placed horizontally relative to the icon. */
  private transient int horizontalTextPosition = TRAILING;

  /** Where the label will be positioned vertically. */
  private transient int verticalAlignment = CENTER;

  /** Where the label text will be place vertically relative to the icon. */
  private transient int verticalTextPosition = CENTER;

  /** The icon painted when the label is enabled. */
  private transient Icon icon;

  /** The icon painted when the label is disabled. */
  private transient Icon disabledIcon;

  /** The label's mnemnonic key. */
  private transient int displayedMnemonic = KeyEvent.VK_UNDEFINED;

  /** The index of the mnemonic character in the text. */
  private transient int displayedMnemonicIndex = -1;

  /** The gap between the icon and the text. */
  private transient int iconTextGap = 4;

  /**
   * Creates a new vertically centered, horizontally on the leading edge
   * JLabel object with text and no icon.
   */
  public JLabel()
  {
    this("", null, LEADING);
  }

  /**
   * Creates a new vertically and horizontally centered
   * JLabel object with no text and the given icon.
   *
   * @param image The icon to use with the label.
   */
  public JLabel(Icon image)
  {
    this("", image, CENTER);
  }

  /**
   * Creates a new vertically centered JLabel object with no text and the
   * given icon and horizontal alignment. By default, the text is TRAILING
   * the image.
   *
   * @param image The icon to use with the label.
   * @param horizontalAlignment The horizontal alignment of the label.
   */
  public JLabel(Icon image, int horizontalAlignment)
  {
    this("", image, horizontalAlignment);
  }

  /**
   * Creates a new horizontally leading and vertically centered JLabel 
   * object with no icon and the given text.
   *
   * @param text The text to use with the label.
   */
  public JLabel(String text)
  {
    this(text, null, LEADING);
  }

  /**
   * Creates a new vertically centered JLabel object with no icon and the
   * given text and horizontal alignment.
   *
   * @param text The text to use with the label.
   * @param horizontalAlignment The horizontal alignment of the label.
   */
  public JLabel(String text, int horizontalAlignment)
  {
    this(text, null, horizontalAlignment);
  }

  /**
   * Creates a new vertically centered JLabel object with the given text,
   * icon, and horizontal alignment.
   *
   * @param text The text to use with the label.
   * @param icon The icon to use with the label.
   * @param horizontalAlignment The horizontal alignment of the label.
   */
  public JLabel(String text, Icon icon, int horizontalAlignment)
  {
    this.text = text;
    this.icon = icon;
    this.horizontalAlignment = horizontalAlignment;
    setAlignmentX(0.0F);
    setInheritsPopupMenu(true);
    updateUI();
  }

  /**
   * Returns the label's UI delegate.
   *
   * @return The label's UI delegate.
   */
  public LabelUI getUI()
  {
    return (LabelUI) ui;
  }

  /**
   * Sets the label's UI delegate.
   *
   * @param ui The label's UI delegate (<code>null</code> not permitted).
   */
  public void setUI(LabelUI ui)
  {
    super.setUI(ui);
  }

  /**
   * Resets the label's UI delegate to the default UI for the current look and 
   * feel.
   */
  public void updateUI()
  {
    setUI((LabelUI) UIManager.getUI(this));
  }

  /**
   * Returns a name to identify which look and feel class will be
   * the UI delegate for this label.
   *
   * @return <code>"LabelUI"</code>
   */
  public String getUIClassID()
  {
    return "LabelUI";
  }

  /**
   * Returns a string describing the attributes for the <code>JLabel</code>
   * component, for use in debugging.  The return value is guaranteed to be 
   * non-<code>null</code>, but the format of the string may vary between
   * implementations.
   *
   * @return A string describing the attributes of the <code>JLabel</code>.
   */
  protected String paramString()
  {
    StringBuffer sb = new StringBuffer(super.paramString());
    sb.append(",defaultIcon=");
    if (icon != null)
      sb.append(icon);
    sb.append(",disabledIcon=");
    if (disabledIcon != null)
      sb.append(disabledIcon);
    sb.append(",horizontalAlignment=");
    sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString(
        horizontalAlignment));
    sb.append(",horizontalTextPosition=");
    sb.append(SwingUtilities.convertHorizontalAlignmentCodeToString(
        horizontalTextPosition));
    sb.append(",iconTextGap=").append(iconTextGap);
    sb.append(",labelFor=");
    if (labelFor != null)
      sb.append(labelFor);
    sb.append(",text=");
    if (text != null)
      sb.append(text);
    sb.append(",verticalAlignment=");
    sb.append(SwingUtilities.convertVerticalAlignmentCodeToString(
        verticalAlignment));
    sb.append(",verticalTextPosition=");
    sb.append(SwingUtilities.convertVerticalAlignmentCodeToString(
        verticalTextPosition));
    return sb.toString();
  }

  /**
   * Returns the text displayed by the label.
   *
   * @return The label text (possibly <code>null</code>).
   * 
   * @see #setText(String)
   */
  public String getText()
  {
    return text;
  }

  /**
   * Sets the text for the label and sends a {@link PropertyChangeEvent} (with
   * the name 'text') to all registered listeners.  This method will also 
   * update the <code>displayedMnemonicIndex</code>, if necessary.
   *
   * @param newText The text (<code>null</code> permitted).
   * 
   * @see #getText()
   * @see #getDisplayedMnemonicIndex()
   */
  public void setText(String newText)
  {
    if (text == null && newText == null)
      return;
    if (text != null && text.equals(newText))
      return;

    String oldText = text;
    text = newText;
    firePropertyChange("text", oldText, newText);

    if (text != null)
      setDisplayedMnemonicIndex(text.toUpperCase().indexOf(displayedMnemonic));
    else
      setDisplayedMnemonicIndex(-1);
    revalidate();
    repaint();
  }

  /**
   * Returns the active icon. The active icon is painted when the label is 
   * enabled.
   *
   * @return The active icon.
   * 
   * @see #setIcon(Icon)
   * @see #getDisabledIcon()
   */
  public Icon getIcon()
  {
    return icon;
  }

  /**
   * Sets the icon for the label (this is a bound property with the name 
   * 'icon'). This icon will be displayed when the label is enabled.
   *
   * @param newIcon The icon (<code>null</code> permitted).
   * 
   * @see #getIcon()
   * @see #setDisabledIcon(Icon)
   */
  public void setIcon(Icon newIcon)
  {
    if (icon != newIcon)
      {
        Icon oldIcon = icon;
        icon = newIcon;
        firePropertyChange("icon", oldIcon, newIcon);
        repaint();
      }
  }

  /**
   * Returns the disabled icon. The disabled icon is painted when the label is 
   * disabled. If the disabled icon is <code>null</code> and the active icon
   * is an {@link ImageIcon}, this method returns a grayed version of the icon. 
   * The grayed version of the icon becomes the <code>disabledIcon</code>.
   *
   * @return The disabled icon.
   * 
   * @see #setDisabledIcon(Icon)
   */
  public Icon getDisabledIcon()
  {
    if (disabledIcon == null && icon instanceof ImageIcon)
      disabledIcon = new ImageIcon(
          GrayFilter.createDisabledImage(((ImageIcon) icon).getImage()));

    return disabledIcon;
  }

  /**
   * Sets the icon displayed when the label is disabled (this is a bound
   * property with the name 'disabledIcon').
   *
   * @param newIcon The disabled icon (<code>null</code> permitted).
   * 
   * @see #getDisabledIcon()
   */
  public void setDisabledIcon(Icon newIcon)
  {
    if (disabledIcon != newIcon)
      {
        Icon oldIcon = disabledIcon;
        disabledIcon = newIcon;
        firePropertyChange("disabledIcon", oldIcon, newIcon);
      }
  }

  /**
   * Sets the keycode that will be the label's mnemonic (this is a bound
   * property with the name 'displayedMnemonic').  If the label is used as a 
   * label for another component, the label will give focus to that component 
   * when the mnemonic is activated.
   *
   * @param mnemonic The keycode to use for the mnemonic.
   * 
   * @see #getDisplayedMnemonic()
   */
  public void setDisplayedMnemonic(int mnemonic)
  {
    if (displayedMnemonic != mnemonic)
      {
        int old = displayedMnemonic;
        displayedMnemonic = mnemonic;
        firePropertyChange("displayedMnemonic", old, displayedMnemonic);
        if (text != null)
          setDisplayedMnemonicIndex(text.toUpperCase().indexOf(mnemonic));
      }
  }

  /**
   * Sets the character that will be the label's mnemonic. If the
   * label is used as a label for another component, the label will give
   * focus to that component when the mnemonic is activated via the keyboard.
   *
   * @param mnemonic The character to use for the mnemonic (this will be
   *     converted to the equivalent upper case character).
   *     
   * @see #getDisplayedMnemonic()
   */
  public void setDisplayedMnemonic(char mnemonic)
  {
    setDisplayedMnemonic((int) Character.toUpperCase(mnemonic));
  }

  /**
   * Returns the keycode that is used for the label's mnemonic.
   *
   * @return The keycode that is used for the label's mnemonic.
   * 
   * @see #setDisplayedMnemonic(int)
   */
  public int getDisplayedMnemonic()
  {
    return displayedMnemonic;
  }

  /**
   * Sets the index of the character in the text that will be underlined to
   * indicate that it is the mnemonic character for the label.  You only need
   * to call this method if you wish to override the automatically calculated
   * character index.  For instance, for a label "Find Next" with the mnemonic
   * character 'n', you might wish to underline the second occurrence of 'n'
   * rather than the first (which is the default).
   * <br><br>
   * Note that this method does not validate the character at the specified 
   * index to ensure that it matches the key code returned by
   * {@link #getDisplayedMnemonic()}.
   *
   * @param newIndex The index of the character to underline.
   *
   * @throws IllegalArgumentException If index less than -1 or index is greater
   *         than or equal to the label length.
   *         
   * @see #getDisplayedMnemonicIndex()
   * @since 1.4
   */
  public void setDisplayedMnemonicIndex(int newIndex)
    throws IllegalArgumentException
  {
    int maxValid = -1;
    if (text != null)
      maxValid = text.length() - 1;
    if (newIndex < -1 || newIndex > maxValid)
      throw new IllegalArgumentException();

    if (newIndex != displayedMnemonicIndex)
      {
        int oldIndex = displayedMnemonicIndex;
        displayedMnemonicIndex = newIndex;
        firePropertyChange("displayedMnemonicIndex", oldIndex, newIndex);
      }
  }

  /**
   * Returns the index of the character in the label's text that will be
   * underlined (to indicate that it is the mnemonic character), or -1 if no
   * character is to be underlined.
   *
   * @return The index of the character that will be underlined.
   * 
   * @see #setDisplayedMnemonicIndex(int)
   * @since 1.4
   */
  public int getDisplayedMnemonicIndex()
  {
    return displayedMnemonicIndex;
  }

  /**
   * Checks the specified key to ensure that it is valid as a horizontal 
   * alignment, throwing an {@link IllegalArgumentException} if the key is
   * invalid.  Valid keys are {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 
   * {@link #LEADING} and {@link #TRAILING}.
   *
   * @param key The key to check.
   * @param message The message of the exception to be thrown if the key is
   *        invalid.
   *
   * @return The key if it is valid.
   *
   * @throws IllegalArgumentException If the key is invalid.
   */
  protected int checkHorizontalKey(int key, String message)
  {
    if (key != LEFT && key != CENTER && key != RIGHT && key != LEADING
        && key != TRAILING)
      throw new IllegalArgumentException(message);
    else
      return key;
  }

  /**
   * Checks the specified key to ensure that it is valid as a vertical 
   * alignment, throwing an {@link IllegalArgumentException} if the key is
   * invalid.  Valid keys are {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}.
   *
   * @param key The key to check.
   * @param message The message of the exception to be thrown if the key is
   *        invalid.
   *
   * @return The key if it is valid.
   *
   * @throws IllegalArgumentException If the key is invalid.
   */
  protected int checkVerticalKey(int key, String message)
  {
    if (key != TOP && key != BOTTOM && key != CENTER)
      throw new IllegalArgumentException(message);
    else
      return key;
  }

  /**
   * Returns the gap between the icon and the text.
   *
   * @return The gap between the icon and the text.
   * 
   * @see #setIconTextGap(int)
   */
  public int getIconTextGap()
  {
    return iconTextGap;
  }

  /**
   * Sets the gap between the icon and the text, in the case that both are 
   * visible (this is a bound property with the name 'iconTextGap'). 
   *
   * @param newGap The gap (in pixels).
   * 
   * @see #getIconTextGap()
   */
  public void setIconTextGap(int newGap)
  {
    if (iconTextGap != newGap)
      {
	firePropertyChange("iconTextGap", iconTextGap, newGap);
	iconTextGap = newGap;
      }
  }

  /**
   * Returns the vertical alignment of the label (one of
   * {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}).  The default value
   * depends on the installed look and feel, but is usually {@link #CENTER}.
   *
   * @return The vertical alignment.
   * 
   * @see #setVerticalAlignment(int)
   */
  public int getVerticalAlignment()
  {
    return verticalAlignment;
  }

  /**
   * Sets the vertical alignment for the label (this is a bound property with
   * the name 'verticalAlignment').  The vertical alignment determines where 
   * the label (icon and text) will be placed vertically within the component 
   * bounds.  Valid alignment codes are {@link #TOP}, {@link #CENTER} and 
   * {@link #BOTTOM}.
   *
   * @param alignment The vertical alignment of the label.
   * 
   * @throws IllegalArgumentException if <code>alignment</code> is not one of 
   *     the specified values.
   *     
   * @see #getVerticalAlignment()
   */
  public void setVerticalAlignment(int alignment)
  {
    if (alignment == verticalAlignment)
      return;

    int oldAlignment = verticalAlignment;
    verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
    firePropertyChange("verticalAlignment", oldAlignment, verticalAlignment);
  }

  /**
   * Returns the horizontal alignment of the label (one of {@link #LEFT}, 
   * {@link #CENTER}, {@link #RIGHT}, {@link #LEADING} and {@link #TRAILING}).
   * The default value depends on the installed look and feel, but is usually 
   * {@link #LEFT}.
   *
   * @return The horizontal alignment.
   * 
   * @see #setHorizontalAlignment(int)
   */
  public int getHorizontalAlignment()
  {
    return horizontalAlignment;
  }

  /**
   * Sets the horizontal alignment for the label (this is a bound property with
   * the name 'horizontalAlignment').  The horizontal alignment determines where 
   * the label (icon and text) will be placed horizontally within the 
   * component bounds.  Valid alignment codes are {@link #LEFT}, 
   * {@link #CENTER}, {@link #RIGHT}, {@link #LEADING} and {@link #TRAILING}.
   *
   * @param alignment The horizontal alignment of the label.
   * 
   * @throws IllegalArgumentException if <code>alignment</code> is not one of 
   *     the specified values.
   *     
   * @see #getHorizontalAlignment()
   */
  public void setHorizontalAlignment(int alignment)
  {
    if (horizontalAlignment == alignment)
      return;
    
    int oldAlignment = horizontalAlignment;
    horizontalAlignment = checkHorizontalKey(alignment, "horizontalAlignment");
    firePropertyChange("horizontalAlignment", oldAlignment,
                       horizontalAlignment);
  }

  /**
   * Returns the vertical position of the label's text relative to the icon. 
   * This will be one of {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}.
   * 
   * @return The vertical position of the label's text relative to the icon.
   * 
   * @see #setVerticalTextPosition(int)
   */
  public int getVerticalTextPosition()
  {
    return verticalTextPosition;
  }

  /**
   * Sets the vertical position of the label's text relative to the icon (this
   * is a bound property with the name 'verticalTextPosition').  Valid 
   * positions are {@link #TOP}, {@link #CENTER} and {@link #BOTTOM}.
   *
   * @param textPosition The vertical text position.
   * 
   * @throws IllegalArgumentException if <code>textPosition</code> is not one
   *     of the specified values.
   */
  public void setVerticalTextPosition(int textPosition)
  {
    if (textPosition != verticalTextPosition)
      {
        int oldPos = verticalTextPosition;
        verticalTextPosition = checkVerticalKey(textPosition,
	                                            "verticalTextPosition");
        firePropertyChange("verticalTextPosition", oldPos, 
                           verticalTextPosition);
      }
  }

  /**
   * Returns the horizontal position of the label's text relative to the icon. 
   * This will be one of {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 
   * {@link #LEADING} and {@link #TRAILING}.
   * 
   * @return The horizontal position of the label's text relative to the icon.
   * 
   * @see #setHorizontalTextPosition(int)
   */
  public int getHorizontalTextPosition()
  {
    return horizontalTextPosition;
  }

  /**
   * Sets the horizontal position of the label's text relative to the icon (this
   * is a bound property with the name 'horizontalTextPosition').  Valid 
   * positions are {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, 
   * {@link #LEADING} and {@link #TRAILING}.
   *
   * @param textPosition The horizontal text position.
   * 
   * @throws IllegalArgumentException if <code>textPosition</code> is not one
   *     of the specified values.
   */
  public void setHorizontalTextPosition(int textPosition)
  {
    if (textPosition != horizontalTextPosition)
      {
        int oldPos = horizontalTextPosition;
        horizontalTextPosition = checkHorizontalKey(textPosition,
                                                    "horizontalTextPosition");
        firePropertyChange("horizontalTextPosition", oldPos, 
                           horizontalTextPosition);
      }
  }

  /**
   * Returns false if the current icon image (current icon will depend on 
   * whether the label is enabled) is not equal to the passed in image.
   *
   * @param img The image to check.
   * @param infoflags The bitwise inclusive OR of ABORT, ALLBITS, ERROR,
   *        FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, and WIDTH
   * @param x The x position
   * @param y The y position
   * @param w The width
   * @param h The height
   *
   * @return Whether the current icon image is equal to the image given.
   */
  public boolean imageUpdate(Image img, int infoflags, int x, int y, int w,
                             int h)
  {
    Icon currIcon = isEnabled() ? icon : disabledIcon;

    // XXX: Is this the correct way to check for image equality?
    if (currIcon != null && currIcon instanceof ImageIcon)
      return (((ImageIcon) currIcon).getImage() == img);

    return false;
  }

  /**
   * Returns the component that this <code>JLabel</code> is providing the label
   * for.  This component will typically receive the focus when the label's 
   * mnemonic key is activated via the keyboard.
   *
   * @return The component (possibly <code>null</code>).
   */
  public Component getLabelFor()
  {
    return labelFor;
  }

  /**
   * Sets the component that this <code>JLabel</code> is providing the label
   * for (this is a bound property with the name 'labelFor').  This component
   * will typically receive the focus when the label's mnemonic key is 
   * activated via the keyboard.
   *
   * @param c  the component (<code>null</code> permitted).
   * 
   * @see #getLabelFor()
   */
  public void setLabelFor(Component c)
  {
    if (c != labelFor)
      {
        Component oldLabelFor = labelFor;
        labelFor = c;
        firePropertyChange("labelFor", oldLabelFor, labelFor);

        // We put the label into the client properties for the labeled
        // component so that it can be read by the AccessibleJComponent.
        // The other option would be to reserve a default visible field
        // in JComponent, but since this is relatively seldomly used, it
        // would be unnecessary waste of memory to do so.
        if (oldLabelFor instanceof JComponent)
          {
            ((JComponent) oldLabelFor).putClientProperty(LABEL_PROPERTY, null);
          }

        if (labelFor instanceof JComponent)
          {
            ((JComponent) labelFor).putClientProperty(LABEL_PROPERTY, this);
          }

      }
  }

  /**
   * Sets the font for the label (this a bound property with the name 'font').
   *
   * @param f The font (<code>null</code> permitted).
   */
  public void setFont(Font f)
  {
    super.setFont(f);
    repaint();
  }

  /**
   * Returns the object that provides accessibility features for this
   * <code>JLabel</code> component.
   *
   * @return The accessible context (an instance of {@link AccessibleJLabel}).
   */
  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      accessibleContext = new AccessibleJLabel();
    return accessibleContext;
  }
}
