/* BasicLabelUI.java
 Copyright (C) 2002, 2004, 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.plaf.basic;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LabelUI;
import javax.swing.text.View;

/**
 * This is the Basic Look and Feel class for the JLabel.  One BasicLabelUI
 * object is used to paint all JLabels that utilize the Basic Look and Feel.
 */
public class BasicLabelUI extends LabelUI implements PropertyChangeListener
{
  /** The labelUI that is shared by all labels. */
  protected static BasicLabelUI labelUI;

  /**
   * These fields hold the rectangles for the whole label,
   * the icon and the text.
   */
  private Rectangle vr;
  private Rectangle ir;
  private Rectangle tr;

  /**
   * Creates a new BasicLabelUI object.
   */
  public BasicLabelUI()
  {
    super();
    vr = new Rectangle();
    ir = new Rectangle();
    tr = new Rectangle();
  }

  /**
   * Creates and returns a UI for the label. Since one UI is shared by  all
   * labels, this means creating only if necessary and returning the  shared
   * UI.
   *
   * @param c The {@link JComponent} that a UI is being created for.
   *
   * @return A label UI for the Basic Look and Feel.
   */
  public static ComponentUI createUI(JComponent c)
  {
    if (labelUI == null)
      labelUI = new BasicLabelUI();
    return labelUI;
  }

  /**
   * Returns the preferred size of this component as calculated by the
   * {@link #layoutCL(JLabel, FontMetrics, String, Icon, Rectangle, Rectangle, 
   * Rectangle)} method.
   *
   * @param c This {@link JComponent} to get a preferred size for.
   *
   * @return The preferred size.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    JLabel lab = (JLabel) c;
    Insets insets = lab.getInsets();
    FontMetrics fm = lab.getFontMetrics(lab.getFont());
    layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr);
    Rectangle cr = SwingUtilities.computeUnion(tr.x, tr.y, tr.width, tr.height,
                                               ir);
    return new Dimension(insets.left + cr.width + insets.right, insets.top
        + cr.height + insets.bottom);

  }

  /**
   * This method returns the minimum size of the {@link JComponent} given. If
   * this method returns null, then it is up to the Layout Manager to give
   * this component a minimum size.
   *
   * @param c The {@link JComponent} to get a minimum size for.
   *
   * @return The minimum size.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the maximum size of the {@link JComponent} given. If
   * this method returns null, then it is up to the Layout Manager to give
   * this component a maximum size.
   *
   * @param c The {@link JComponent} to get a maximum size for.
   *
   * @return The maximum size.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * The method that paints the label according to its current state.
   * 
   * @param g The {@link Graphics} object to paint with.
   * @param c The {@link JComponent} to paint.
   */
  public void paint(Graphics g, JComponent c)
  {
    JLabel b = (JLabel) c;
    FontMetrics fm = g.getFontMetrics();
    vr = SwingUtilities.calculateInnerArea(c, vr);

    if (vr.width < 0)
      vr.width = 0;
    if (vr.height < 0)
      vr.height = 0;

    Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();

    String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr);

    if (icon != null)
      icon.paintIcon(b, g, ir.x, ir.y);        

    Object htmlRenderer = b.getClientProperty(BasicHTML.propertyKey);
    if (htmlRenderer == null)
      {
        if (text != null && !text.equals(""))
          {
            if (b.isEnabled())
              paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent());
            else
              paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent());
          }
      }
    else
      {
        ((View) htmlRenderer).paint(g, tr);
      }
  }

  /**
   * This method is simply calls SwingUtilities's layoutCompoundLabel.
   * 
   * @param label The label to lay out.
   * @param fontMetrics The FontMetrics for the font used.
   * @param text The text to paint.
   * @param icon The icon to draw.
   * @param viewR The entire viewable rectangle.
   * @param iconR The icon bounds rectangle.
   * @param textR The text bounds rectangle.
   * 
   * @return A possibly clipped version of the text.
   */
  protected String layoutCL(JLabel label, FontMetrics fontMetrics, String text,
      Icon icon, Rectangle viewR, Rectangle iconR, Rectangle textR)
  {
    return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon,
        label.getVerticalAlignment(), label.getHorizontalAlignment(), label
            .getVerticalTextPosition(), label.getHorizontalTextPosition(),
        viewR, iconR, textR, label.getIconTextGap());
  }

  /**
   * Paints the text if the label is disabled. By default, this paints the
   * clipped text returned by layoutCompoundLabel using the
   * background.brighter() color. It also paints the same text using the
   * background.darker() color one pixel to the right and one pixel down.
   *
   * @param l The {@link JLabel} being painted.
   * @param g The {@link Graphics} object to paint with.
   * @param s The String to paint.
   * @param textX The x coordinate of the start of the baseline.
   * @param textY The y coordinate of the start of the baseline.
   */
  protected void paintDisabledText(JLabel l, Graphics g, String s, int textX,
      int textY)
  {
    Color saved_color = g.getColor();

    g.setColor(l.getBackground().brighter());

    int mnemIndex = l.getDisplayedMnemonicIndex();

    if (mnemIndex != -1)
      BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
          textY);
    else
      g.drawString(s, textX, textY);

    g.setColor(l.getBackground().darker());
    if (mnemIndex != -1)
      BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX + 1,
          textY + 1);
    else
      g.drawString(s, textX + 1, textY + 1);

    g.setColor(saved_color);
  }

  /**
   * Paints the text if the label is enabled. The text is painted using the
   * foreground color.
   *
   * @param l The {@link JLabel} being painted.
   * @param g The {@link Graphics} object to paint with.
   * @param s The String to paint.
   * @param textX The x coordinate of the start of the baseline.
   * @param textY The y coordinate of the start of the baseline.
   */
  protected void paintEnabledText(JLabel l, Graphics g, String s, int textX,
      int textY)
  {
    Color saved_color = g.getColor();
    g.setColor(l.getForeground());

    int mnemIndex = l.getDisplayedMnemonicIndex();

    if (mnemIndex != -1)
      BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
          textY);
    else
      g.drawString(s, textX, textY);

    g.setColor(saved_color);
  }

  /**
   * This method installs the UI for the given {@link JComponent}.  This
   * method will install the component, defaults, listeners,  and keyboard
   * actions.
   *
   * @param c The {@link JComponent} that this UI is being installed on.
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);
    if (c instanceof JLabel)
    {
      JLabel l = (JLabel) c;

      installComponents(l);
      installDefaults(l);
      installListeners(l);
      installKeyboardActions(l);
    }
  }

  /**
   * This method uninstalls the UI for the given {@link JComponent}. This
   * method will uninstall the component, defaults, listeners,  and keyboard
   * actions.
   *
   * @param c The {@link JComponent} that this UI is being installed on.
   */
  public void uninstallUI(JComponent c)
  {
    super.uninstallUI(c);
    if (c instanceof JLabel)
    {
      JLabel l = (JLabel) c;

      uninstallKeyboardActions(l);
      uninstallListeners(l);
      uninstallDefaults(l);
      uninstallComponents(l);
    }
  }

  /**
   * This method installs the components for this {@link JLabel}.
   *
   * @param c The {@link JLabel} to install components for.
   */
  protected void installComponents(JLabel c)
  {
    BasicHTML.updateRenderer(c, c.getText());
  }

  /**
   * This method uninstalls the components for this {@link JLabel}.
   *
   * @param c The {@link JLabel} to uninstall components for.
   */
  protected void uninstallComponents(JLabel c)
  {
    c.putClientProperty(BasicHTML.propertyKey, null);
    c.putClientProperty(BasicHTML.documentBaseKey, null);
  }

  /**
   * This method installs the defaults that are defined in  the Basic look and
   * feel for this {@link JLabel}.
   *
   * @param c The {@link JLabel} to install defaults for.
   */
  protected void installDefaults(JLabel c)
  {
    LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground",
                                     "Label.font");
    //XXX: There are properties we don't use called disabledForeground
    //and disabledShadow.
  }

  /**
   * This method uninstalls the defaults that are defined in the Basic look
   * and feel for this {@link JLabel}.
   *
   * @param c The {@link JLabel} to uninstall defaults for.
   */
  protected void uninstallDefaults(JLabel c)
  {
    c.setForeground(null);
    c.setBackground(null);
    c.setFont(null);
  }

  /**
   * Installs the keyboard actions for the given {@link JLabel}.
   *
   * @param l The {@link JLabel} to install keyboard actions for.
   */
  protected void installKeyboardActions(JLabel l)
  {
    Component c = l.getLabelFor();
    if (c != null)
      {
        int mnemonic = l.getDisplayedMnemonic();
        if (mnemonic > 0)
          {
            // add a keystroke for the given mnemonic mapping to 'press';
            InputMap keyMap = new InputMap();
            keyMap.put(KeyStroke.getKeyStroke(mnemonic, KeyEvent.VK_ALT), 
                "press");
            SwingUtilities.replaceUIInputMap(l, 
                JComponent.WHEN_IN_FOCUSED_WINDOW, keyMap);
            
            // add an action to focus the component when 'press' happens
            ActionMap map = new ActionMap();
            map.put("press", new AbstractAction() {
              public void actionPerformed(ActionEvent event)
              {
                JLabel label = (JLabel) event.getSource();
                Component c = label.getLabelFor();
                if (c != null)
                  c.requestFocus();
              }
            });
            SwingUtilities.replaceUIActionMap(l, map);
          }
      }   
  }

  /**
   * This method uninstalls the keyboard actions for the given {@link JLabel}.
   *
   * @param l The {@link JLabel} to uninstall keyboard actions for.
   */
  protected void uninstallKeyboardActions(JLabel l)
  {
    SwingUtilities.replaceUIActionMap(l, null);
    SwingUtilities.replaceUIInputMap(l, JComponent.WHEN_IN_FOCUSED_WINDOW, 
                                     null);
  }

  /**
   * This method installs the listeners for the  given {@link JLabel}. The UI
   * delegate only listens to  the label.
   *
   * @param c The {@link JLabel} to install listeners for.
   */
  protected void installListeners(JLabel c)
  {
    c.addPropertyChangeListener(this);
  }

  /**
   * This method uninstalls the listeners for the given {@link JLabel}. The UI
   * delegate only listens to the label.
   *
   * @param c The {@link JLabel} to uninstall listeners for.
   */
  protected void uninstallListeners(JLabel c)
  {
    c.removePropertyChangeListener(this);
  }

  /**
   * This method is called whenever any JLabel's that use this UI has one of
   * their properties change.
   *
   * @param e The {@link PropertyChangeEvent} that describes the change.
   */
  public void propertyChange(PropertyChangeEvent e)
  {
    if (e.getPropertyName().equals("text"))
      {
        String text = (String) e.getNewValue();
        JLabel l = (JLabel) e.getSource();
        BasicHTML.updateRenderer(l, text);
      }
    else if (e.getPropertyName().equals("displayedMnemonic"))
      {
        // update the key to action mapping
        JLabel label = (JLabel) e.getSource();
        if (label.getLabelFor() != null)
          {
            int oldMnemonic = ((Integer) e.getOldValue()).intValue();
            int newMnemonic = ((Integer) e.getNewValue()).intValue();
            InputMap keyMap = label.getInputMap(
                JComponent.WHEN_IN_FOCUSED_WINDOW);
            keyMap.put(KeyStroke.getKeyStroke(oldMnemonic, 
                KeyEvent.ALT_DOWN_MASK), null);
            keyMap.put(KeyStroke.getKeyStroke(newMnemonic, 
                KeyEvent.ALT_DOWN_MASK), "press");
          }
      }
    else if (e.getPropertyName().equals("labelFor"))
      {
        JLabel label = (JLabel) e.getSource();
        InputMap keyMap = label.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        int mnemonic = label.getDisplayedMnemonic();
        if (mnemonic > 0)
          keyMap.put(KeyStroke.getKeyStroke(mnemonic, KeyEvent.ALT_DOWN_MASK), 
              "press");       
      }
  }
}
