/* MetalBorders.java
   Copyright (C) 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.plaf.metal;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicBorders;
import javax.swing.text.JTextComponent;


/**
 * A factory class that creates borders for the different Swing components.
 *
 * @author Roman Kennke (roman@kennke.org)
 */
public class MetalBorders
{

  /** The shared instance for getButtonBorder(). */
  private static Border buttonBorder;

  /** The shared instance for getToggleButtonBorder(). */
  private static Border toggleButtonBorder;

  /** The shared instance for getDesktopIconBorder(). */
  private static Border desktopIconBorder;

  /** The shared instance for getRolloverButtonBorder(). */
  private static Border toolbarButtonBorder;

  /** The shared instance for getTextFieldBorder(). */
  private static Border textFieldBorder;

  /** The shared instance for getTextBorder(). */
  private static Border textBorder;

  /** The shared instance for getRolloverBorder(). */
  private static Border rolloverBorder;

  /**
   * A MarginBorder that gets shared by multiple components.
   * Created on demand by the private helper function {@link
   * #getMarginBorder()}.
   */
  private static BasicBorders.MarginBorder marginBorder;

  /**
   * <p>A border used for {@link JButton} components.</p>
   * 
   * <p>This {@link Border} implementation can handle only instances of
   * {@link AbstractButton} and their subclasses.</p>
   * 
   * <p>If the Metal Look and Feel's current theme is 'Ocean' the border
   * will be painted with a special highlight when the mouse cursor if
   * over the button (ie. the property <code>rollover</code> of the
   * button's model is <code>true</code>) and is not a <b>direct</b>
   * child of a {@link JToolBar}.</p> 
   */
  public static class ButtonBorder extends AbstractBorder implements UIResource
  {
    /** The borders insets. */
    protected static Insets borderInsets = new Insets(3, 3, 3, 3);

    /**
     * Creates a new instance of <code>ButtonBorder</code>.
     */
    public ButtonBorder()
    {
      // Nothing to do here.
    }

    /**
     * Paints the button border.
     *
     * @param c the component for which we paint the border
     * @param g the Graphics context to use
     * @param x the X coordinate of the upper left corner of c
     * @param y the Y coordinate of the upper left corner of c
     * @param w the width of c
     * @param h the height of c
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
                            int h)
    {
      // With the OceanTheme the button border is painted entirely different.
      // However, I couldn't figure out how this is determined besides checking
      // for instanceof OceanTheme. The button painting is definitely not
      // influenced by a UI default property and it is definitely performed
      // by the same Border class.
      if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
        paintOceanButtonBorder(c, g, x, y, w, h);
      else
        paintDefaultButtonBorder(c, g, x, y, w, h);
    }

    /**
     * Paints the button border for the DefaultMetalTheme.
     *
     * @param c the component (button)
     * @param g the graphics object to use
     * @param x the upper left corner of the component, X coordinate
     * @param y the upper left corner of the component, Y coordinate
     * @param w the width of the component
     * @param h the height of the component
     */
    private void paintDefaultButtonBorder(Component c, Graphics g, int x,
                                          int y, int w, int h)
    {
      ButtonModel bmodel = null;

      // The RI will fail with a ClassCastException in such a situation.
      // This code tries to be more helpful.
      if (c instanceof AbstractButton)
        bmodel = ((AbstractButton) c).getModel();
      else
        throw new IllegalStateException("A ButtonBorder is supposed to work "
                                        + "only with AbstractButton and"
                                        + "subclasses.");

      Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
      Color shadow = MetalLookAndFeel.getControlShadow();
      Color light = MetalLookAndFeel.getControlHighlight();
      Color middle = MetalLookAndFeel.getControl();

      if (c.isEnabled())
        {
          // draw dark border
          g.setColor(darkShadow);
          g.drawRect(x, y, w - 2, h - 2);

          // If the button is the default button, we paint a special border,
          // regardless of the pressed state.
          if (c instanceof JButton && ((JButton) c).isDefaultButton())
            {
              g.drawRect(x + 1, y + 1, w - 4, h - 4);
              // Draw white highlight.
              g.setColor(light);
              g.drawLine(x + 2, y + 2, x + w - 4, y + 2);
              g.drawLine(x + 2, y + 2, x + 2, y + h - 4);
              g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
              g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1);
              // Draw crossing pixels.
              g.setColor(middle);
              g.fillRect(x + w - 2, y + 2, 1, 1);
              g.fillRect(x + 2, y + h - 2, 1, 1);
            }
          else
            {
              // The normal border. This is used when the button is not
              // pressed or the button is not armed.
              if (! (bmodel.isPressed() && bmodel.isArmed()))
                {
                  // draw light border
                  g.setColor(light);
                  g.drawRect(x + 1, y + 1, w - 2, h - 2);

                  // draw crossing pixels of both borders
                  g.setColor(middle);
                  g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
                  g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
                }
              // The pressed border. This border is painted only when
              // the button is both pressed and armed.
              else
                {
                  // draw light border
                  g.setColor(light);
                  g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
                  g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);

                  // draw shadow border
                  g.setColor(middle);
                  g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
                  g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
 
                  // draw crossing pixels of both borders
                  g.setColor(shadow);
                  g.drawRect(x + 1, y + h - 2, 0, 0);
                  g.drawRect(x + w - 2, y + 1, 0, 0);
                }
            }
        }
      else 
        {
          // draw disabled border
          g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
          g.drawRect(x, y, w - 2, h - 2);          
        }
    }

    /**
     * Paints the button border for the OceanTheme.
     *
     * @param c the button
     * @param g the graphics context
     * @param x the X coordinate of the upper left corner of the painting rect
     * @param y the Y coordinate of the upper left corner of the painting rect
     * @param w the width of the painting rect
     * @param h the height of the painting rect
     */
    private void paintOceanButtonBorder(Component c, Graphics g, int x,
                                        int y, int w, int h)
    {
      ButtonModel bmodel = null;
      
      // The RI will fail with a ClassCastException in such a situation.
      // This code tries to be more helpful.
      if (c instanceof AbstractButton)
        bmodel = ((AbstractButton) c).getModel();
      else
        throw new IllegalStateException("A ButtonBorder is supposed to work "
                                        + "only with AbstractButton and"
                                        + "subclasses.");

      Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
      Color shadow = MetalLookAndFeel.getControlShadow();
      Color light = MetalLookAndFeel.getControlHighlight();
      Color middle = MetalLookAndFeel.getControl();

      if (c.isEnabled())
        {
          // Paint the pressed border if the button is pressed, or if
          // the button is the default button. In the OceanTheme, the default
          // button has the same border as a pressed button.
          if (bmodel.isPressed() || ((c instanceof JButton)
                                     && ((JButton) c).isDefaultButton()))
            {
              // Draw fat border.
              g.setColor(darkShadow);
              g.drawRect(x, y, w - 1, h - 1);
              g.drawRect(x + 1, y + 1, w - 3, h - 3);
            }
          else if (bmodel.isRollover() && !(c.getParent() instanceof JToolBar))
            {
              // Paint a bigger border when the mouse is over the button but
              // only if it is *not* part of a JToolBar.
              g.setColor(shadow);
              g.drawRect(x, y, w - 1, h - 1);
              g.drawRect(x + 2, y + 2, w - 5, h - 5);
              g.setColor(darkShadow);
              g.drawRect(x + 1, y + 1, w - 3, h - 3);
            }
          else
            {
              g.setColor(darkShadow);
              g.drawRect(x, y, w - 1, h - 1);
            }
        }
      else 
        {
          // draw disabled border
          g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
          g.drawRect(x, y, w - 2, h - 2);          
        }
    }

    /**
     * Returns the insets of the <code>ButtonBorder</code>.
     *
     * @param c the component for which the border is used (ignored).
     *
     * @return The insets of the <code>ButtonBorder</code>.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }

    /**
     * Returns the insets of the <code>ButtonBorder</code> in the specified 
     * <code>newInsets</code> object.
     *
     * @param c the component for which the border is used (ignored).
     * @param newInsets the insets object where to put the values (
     *                  <code>null</code> not permitted).
     *
     * @return The <code>newInsets</code> reference.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      newInsets.bottom = borderInsets.bottom;
      newInsets.left = borderInsets.left;
      newInsets.right = borderInsets.right;
      newInsets.top = borderInsets.top;
      return newInsets;
    }
  }

  /**
   * A border used when painting {@link JInternalFrame} instances.
   */
  static class DesktopIconBorder extends AbstractBorder
    implements UIResource
  {
    /**
     * Creates a new border instance.
     */
    public DesktopIconBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      if (newInsets == null)
        newInsets = new Insets(3, 3, 2, 3);
      else
        {
          newInsets.top = 3;
          newInsets.left = 3;
          newInsets.bottom = 2;
          newInsets.right = 3;
        }
      return newInsets;  
    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {
      g.setColor(MetalLookAndFeel.getControlDarkShadow());      
      g.drawRect(x, y, w - 1, h - 1); 
    }
    
  }

  /**
   * A simple 3D border.
   */
  public static class Flush3DBorder extends AbstractBorder
    implements UIResource
  {
    private static final Insets borderInsets = new Insets(2, 2, 2, 2);
    
    /**
     * Creates a new border instance.
     */
    public Flush3DBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @param newInsets  an existing insets instance, that will be populated
     *                   with the border insets and returned as the result
     *                   (<code>null</code> not permitted).
     *                   
     * @return The <code>newInsets</code> reference.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      newInsets.top = borderInsets.top;
      newInsets.left = borderInsets.left;
      newInsets.bottom = borderInsets.bottom;
      newInsets.right = borderInsets.right;
      return newInsets;  
    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component (ignored).
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {              
      Color savedColor = g.getColor();
      g.setColor(MetalLookAndFeel.getControlDarkShadow());
      g.drawRect(x, y, w - 2, h - 2);
      g.setColor(MetalLookAndFeel.getControlHighlight());
      g.drawRect(x + 1, y + 1, w - 2, h - 2);
      g.setColor(MetalLookAndFeel.getControl());
      g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
      g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
      g.setColor(savedColor);
    }
    
  }
    
  /**
   * A border used for a {@link JInternalFrame} when it is being used as a 
   * palette.
   * 
   * @since 1.3
   */
  public static class PaletteBorder extends AbstractBorder
    implements UIResource
  {
    private static final Insets borderInsets = new Insets(1, 1, 1, 1);

    /**
     * Creates a new <code>PaletteBorder</code>.
     */
    public PaletteBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }

    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @param newInsets  an existing insets instance, that will be populated
     *                   with the border insets and returned as the result
     *                   (<code>null</code> not permitted).
     *                   
     * @return The <code>newInsets</code> reference.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {        
      newInsets.top = borderInsets.top;
      newInsets.left = borderInsets.left;
      newInsets.bottom = borderInsets.bottom;
      newInsets.right = borderInsets.right;
      return newInsets;  
    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component (ignored).
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
            int h)
    {
      Color savedColor = g.getColor();
      
      // draw the outline
      g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
      g.drawRect(x, y, w - 1, h - 1);
      
      // put a dot in each corner
      g.setColor(MetalLookAndFeel.getControl());
      g.fillRect(x, y, 1, 1);
      g.fillRect(x + w - 1, y, 1, 1);
      g.fillRect(x + w - 1, y + h - 1, 1, 1);
      g.fillRect(x, y + h - 1, 1, 1);      
      g.setColor(savedColor);
    }

  }
    
  /**
   * A border used for the {@link JTextField} component.
   */
  public static class TextFieldBorder extends Flush3DBorder
    implements UIResource
  {
    /**
     * Creates a new border instance.
     */
    public TextFieldBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component (ignored).
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {
      boolean enabledTextBorder;
      if (c instanceof JTextComponent)
        {
          JTextComponent tc = (JTextComponent) c;
          enabledTextBorder = tc.isEnabled() && tc.isEditable();
        }
      else
        enabledTextBorder = false;

      if (enabledTextBorder)
        super.paintBorder(c, g, x, y, w, h);
      else
        {
          Color savedColor = g.getColor();
          g.setColor(MetalLookAndFeel.getControlShadow());
          g.drawRect(x, y, w - 1, h - 1);
          g.setColor(savedColor);
        }
    }
    
  }

  /**
   * A border used for the {@link JInternalFrame} component.
   */
  public static class InternalFrameBorder extends AbstractBorder
    implements UIResource
  {
    private static final Insets borderInsets = new Insets(5, 5, 5, 5);

    /**
     * Creates a new border instance.
     */
    public InternalFrameBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @param newInsets  an existing insets instance, that will be populated
     *                   with the border insets and returned as the result
     *                   (<code>null</code> not permitted).
     *                   
     * @return The <code>newInsets</code> reference.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      newInsets.top = borderInsets.top;
      newInsets.left = borderInsets.left;
      newInsets.bottom = borderInsets.bottom;
      newInsets.right = borderInsets.right;
      return newInsets;  
    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {
        
      JInternalFrame f = (JInternalFrame) c;
      if (f.isSelected())
        g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
      else
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
      
      // fill the border background
      g.fillRect(x, y, w, 5);
      g.fillRect(x, y, 5, h);
      g.fillRect(x + w - 5, y, 5, h);
      g.fillRect(x, y + h - 5, w, 5);
      
      // draw a dot in each corner
      g.setColor(MetalLookAndFeel.getControl());
      g.fillRect(x, y, 1, 1);
      g.fillRect(x + w - 1, y, 1, 1);
      g.fillRect(x + w - 1, y + h - 1, 1, 1);
      g.fillRect(x, y + h - 1, 1, 1);
      
      // draw the lines
      g.setColor(MetalLookAndFeel.getBlack());
      g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
      g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
      g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
      g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
      
      // draw the line highlights
      if (f.isSelected())
        g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
      else 
        g.setColor(MetalLookAndFeel.getControlShadow());
      g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
      g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
      g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
      g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
    }
    
  }

  /**
   * A border used for {@link JInternalFrame} components that are
   * presented as dialogs (by the {@link JOptionPane} class).
   */
  public static class OptionDialogBorder extends AbstractBorder
    implements UIResource
  {
      
    /**
     * Creates a new border instance.
     */
    public OptionDialogBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      if (newInsets == null)
        newInsets = new Insets(3, 3, 3, 3);
      else
        {
          newInsets.top = 3;
          newInsets.left = 3;
          newInsets.bottom = 3;
          newInsets.right = 3;
        }
      return newInsets;  
    }
        
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {
        
      JInternalFrame f = (JInternalFrame) c;
      g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
      if (f.getContentPane() instanceof JOptionPane)
        {
          JOptionPane pane = (JOptionPane) f.getContentPane();
          int type = pane.getMessageType();
          if (type == JOptionPane.QUESTION_MESSAGE)
            {
              Color bc = UIManager.getColor(
                  "OptionPane.questionDialog.border.background");
              if (bc != null)
                g.setColor(bc);
            }
          if (type == JOptionPane.WARNING_MESSAGE)
            {
              Color bc = UIManager.getColor(
                  "OptionPane.warningDialog.border.background");
              if (bc != null)
                g.setColor(bc);              
            }
          else if (type == JOptionPane.ERROR_MESSAGE)
            {
              Color bc = UIManager.getColor(
                  "OptionPane.errorDialog.border.background");
              if (bc != null)
                g.setColor(bc);              
            }
        }
      
      // fill the border background
      g.fillRect(x, y, w, 3);
      g.fillRect(x, y, 3, h);
      g.fillRect(x + w - 3, y, 3, h);
      g.fillRect(x, y + h - 3, w, 3);
      
      // draw a dot in each corner
      g.setColor(MetalLookAndFeel.getControl());
      g.fillRect(x, y, 1, 1);
      g.fillRect(x + w - 1, y, 1, 1);
      g.fillRect(x + w - 1, y + h - 1, 1, 1);
      g.fillRect(x, y + h - 1, 1, 1);
      
    }
    
  }

  /**
   * A border used for {@link JMenu} and {@link JMenuItem} components.
   */
  public static class MenuItemBorder extends AbstractBorder
    implements UIResource
  {
    /** The border insets. */
    protected static Insets borderInsets = new Insets(2, 2, 2, 2);
    
    /**
     * Creates a new border instance.
     */
    public MenuItemBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Paints the border for the component.  A border is painted only if the
     * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate of the border area.
     * @param y  the y-coordinate of the border area.
     * @param w  the width of the border area.
     * @param h  the height of the border area.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
        int h)
    {
      Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
      Color light = MetalLookAndFeel.getPrimaryControlHighlight();
      if (c instanceof JMenu) 
        {
          JMenu menu = (JMenu) c;
          if (menu.isSelected())
            {
              g.setColor(dark);
              g.drawLine(x, y, x, y + h);
              g.drawLine(x, y, x + w, y);
              g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
              g.setColor(light);
              g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
            }
        }
      else if (c instanceof JMenuItem)
        {
          JMenuItem item = (JMenuItem) c;
          if (item.isArmed()) 
            {
              g.setColor(dark);
              g.drawLine(x, y, x + w, y);
              g.setColor(light);
              g.drawLine(x, y + h - 1, x + w, y + h - 1);
            }
          else
            {
              // Normally we draw a light line on the left.
              g.setColor(light);
              g.drawLine(x, y, x, y + h);
            }
        }
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }
    
    /**
     * Populates <code>insets</code> with the border insets, then returns it.
     * 
     * @param c  the component (ignored).
     * @param insets  the object to populate with the border insets.
     * 
     * @return The border insets.
     * 
     * @throws NullPointerException if <code>insets</code> is <code>null</code>.
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      insets.left = borderInsets.left;
      insets.top = borderInsets.top;
      insets.bottom = borderInsets.bottom;
      insets.right = borderInsets.right;
      return insets;
    }
  }

  /**
   * A border used for {@link JMenuBar} components.
   */
  public static class MenuBarBorder
      extends AbstractBorder
      implements UIResource
  {
    /** The border insets. */
    protected static Insets borderInsets = new Insets(1, 0, 1, 0);
    
    // TODO: find where this color really comes from
    private static Color borderColor = new Color(153, 153, 153);
    
    /**
     * Creates a new border instance.
     */
    public MenuBarBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Paints the border for the component.  A border is painted only if the
     * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate of the border area.
     * @param y  the y-coordinate of the border area.
     * @param w  the width of the border area.
     * @param h  the height of the border area.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
        int h)
    {
      g.setColor(borderColor);
      g.drawLine(x, y + h - 1, x + w, y + h - 1);
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return borderInsets;
    }
    
    /**
     * Populates <code>insets</code> with the border insets, then returns it.
     * 
     * @param c  the component (ignored).
     * @param insets  the object to populate with the border insets.
     * 
     * @return The border insets.
     * 
     * @throws NullPointerException if <code>insets</code> is <code>null</code>.
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      insets.left = borderInsets.left;
      insets.top = borderInsets.top;
      insets.bottom = borderInsets.bottom;
      insets.right = borderInsets.right;
      return insets;
    }
  }

  /**
   * A border for {@link JScrollPane} components.
   */
  public static class ScrollPaneBorder
    extends AbstractBorder
    implements UIResource
  {
    /** The border insets. */
    private static Insets insets = new Insets(1, 1, 2, 2);
    
    /**
     * Constructs a new ScrollPaneBorder.
     */
    public ScrollPaneBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the insets of the border for the Component <code>c</code>.
     *
     * @param c the Component for which we return the border insets
     */
    public Insets getBorderInsets(Component c)
    {
      return insets;
    }

    /**
     * Paints the border.
     *
     * @param c the Component for which the border is painted
     * @param g the Graphics context
     * @param x the X coordinate of the upper left corner of the border
     * @param y the Y coordinate of the upper left corner of the border
     * @param w the width of the border
     * @param h the height of the border
     */
    public void paintBorder(Component c, Graphics g, int x, int y,
                            int w, int h)
    {
      Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
      Color shadow = MetalLookAndFeel.getControlShadow();
      Color light = MetalLookAndFeel.getWhite();
      Color middle = MetalLookAndFeel.getControl();

      // paint top border line
      g.setColor(darkShadow);
      g.drawLine(x, y, x + w - 2, y);

      // paint left border line
      g.drawLine(x, y, x, y + h - 2);
 
      // paint right inner border line
      g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);

      // paint bottom inner border line
      g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);

      // draw right outer border line
      g.setColor(light);
      g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);

      // draw bottom outer border line
      g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);

      // paint the lighter points
      g.setColor(middle);
      g.drawLine(x + w - 1, y, x + w - 1, y);
      g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
      g.drawLine(x, y + h - 1, x, y + h - 1);
      g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);

    }
    
  }
  
  /**
   * A button border that is only visible when the mouse pointer is within 
   * the button's bounds.
   */
  public static class RolloverButtonBorder
    extends MetalBorders.ButtonBorder
  {
    /**
     * Creates a new border instance.
     */
    public RolloverButtonBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Paints the border.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
            int h)
    {
      // TODO: What should be done here? Obviously the ButtonBorder already
      // handles the rollover state in Sun's impl. Maybe this is only there
      // for backwards compatibility.
      super.paintBorder(c, g, x, y, w, h);
    }
  }
  
  /**
   * This border is used in Toolbar buttons as inner border.
   */
  static class RolloverMarginBorder extends AbstractBorder
  {
    /** The borders insets. */
    protected static Insets borderInsets = new Insets(3, 3, 3, 3);

    /**
     * Creates a new instance of RolloverBorder.
     */
    public RolloverMarginBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the insets of the RolloverBorder.
     *
     * @param c the component for which the border is used
     *
     * @return the insets of the RolloverBorder
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }

    /**
     * Returns the insets of the RolloverMarginBorder in the specified
     * Insets object.
     *
     * @param c the component for which the border is used
     * @param newInsets the insets object where to put the values
     *
     * @return the insets of the RolloverMarginBorder
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      if (newInsets == null)
        newInsets = new Insets(0, 0, 0, 0);

      AbstractButton b = (AbstractButton) c;
      Insets margin = b.getMargin();
      newInsets.bottom = borderInsets.bottom;
      newInsets.left = borderInsets.left;
      newInsets.right = borderInsets.right;
      newInsets.top = borderInsets.top;
      return newInsets;
    }
  }

  /**
   * A border implementation for popup menus.
   */
  public static class PopupMenuBorder
    extends AbstractBorder
    implements UIResource
  {

    /** The border's insets. */
    protected static Insets borderInsets = new Insets(3, 1, 2, 1);

    /**
     * Constructs a new PopupMenuBorder.
     */
    public PopupMenuBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the insets of the border, creating a new Insets instance
     * with each call.
     *
     * @param c the component for which we return the border insets
     *          (not used here)
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }
    
    /**
     * Returns the insets of the border, using the supplied Insets instance.
     *
     * @param c the component for which we return the border insets
     *          (not used here)
     * @param i the Insets instance to fill with the Insets values
     */
    public Insets getBorderInsets(Component c, Insets i)
    {
      Insets insets;
      if (i == null)
        insets = new Insets(borderInsets.top, borderInsets.left,
                            borderInsets.bottom, borderInsets.right);
      else
        {
          insets = i;
          insets.top = borderInsets.top;
          insets.left = borderInsets.left;
          insets.bottom = borderInsets.bottom;
          insets.right = borderInsets.right;
        }
      
      return insets;
    }

    /**
     * Paints the border for component <code>c</code> using the
     * Graphics context <code>g</code> with the dimension
     * <code>x, y, w, h</code>.
     *
     * @param c the component for which we paint the border
     * @param g the Graphics context to use
     * @param x the X coordinate of the upper left corner of c
     * @param y the Y coordinate of the upper left corner of c
     * @param w the width of c
     * @param h the height of c
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
                            int h)
    {
      Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
      Color light = MetalLookAndFeel.getPrimaryControlHighlight();

      // draw dark outer border
      g.setColor(darkShadow);
      g.drawRect(x, y, w - 1, h - 1);
      
      // draw highlighted inner border (only top and left)
      g.setColor(light);
      g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
    }
    
  }

  /**
   * A border used for the {@link JToggleButton} component.
   * 
   * @since 1.3
   */
  public static class ToggleButtonBorder
    extends ButtonBorder 
  {
    /**
     * Creates a new border instance.
     */
    public ToggleButtonBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Paints the toggle button border.
     *
     * @param c the component for which we paint the border
     * @param g the Graphics context to use
     * @param x the X coordinate of the upper left corner of c
     * @param y the Y coordinate of the upper left corner of c
     * @param w the width of c
     * @param h the height of c
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
                            int h)
    {
      ButtonModel bmodel = null;
      
      if (c instanceof AbstractButton)
        bmodel = ((AbstractButton) c).getModel();

      Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
      Color shadow = MetalLookAndFeel.getControlShadow();
      Color light = MetalLookAndFeel.getWhite();
      Color middle = MetalLookAndFeel.getControl();

      if (c.isEnabled())
        {
          // draw dark border
          g.setColor(darkShadow);
          g.drawRect(x, y, w - 2, h - 2);

          if (!bmodel.isArmed())
            {
              // draw light border
              g.setColor(light);
              g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
              g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
              if (bmodel.isSelected())
                g.setColor(middle);
              g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
              g.drawLine(x + 1, y + 1, x + 1, y + h - 3);

              // draw crossing pixels of both borders
              g.setColor(shadow);
              g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
              g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
            }
          else
            {
              // draw light border
              g.setColor(light);
              g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
              g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);

              // draw shadow border
              g.setColor(shadow);
              g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
              g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
 
              // draw crossing pixels of both borders
              g.setColor(shadow);
              g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
              g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
              
            }
          // draw corners
          g.setColor(middle);
          g.drawLine(x, y + h - 1, x, y + h - 1);
          g.drawLine(x + w - 1, y, x + w - 1, y);
        }
      else 
        {
          // draw disabled border
          g.setColor(MetalLookAndFeel.getControlDisabled());
          g.drawRect(x, y, w - 2, h - 2);          
        }
    }
  }

  /**
   * A border used for the {@link JToolBar} component.
   */
  public static class ToolBarBorder extends AbstractBorder
    implements UIResource, SwingConstants
  {
    /**
     * Creates a new border instance.
     */
    public ToolBarBorder()
    {
      // Nothing to do here.
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * 
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }
    
    /**
     * Returns the border insets.
     * 
     * @param c  the component (ignored).
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      JToolBar tb = (JToolBar) c;
      if (tb.getOrientation() == JToolBar.HORIZONTAL)
        {   
          if (newInsets == null)
            newInsets = new Insets(2, 16, 2, 2);
          else
            {
              newInsets.top = 2;
              newInsets.left = 16;
              newInsets.bottom = 2;
              newInsets.right = 2;
            }
          return newInsets;  
        }
      else // assume JToolBar.VERTICAL
        { 
          if (newInsets == null)
            newInsets = new Insets(16, 2, 2, 2);
          else
            {
              newInsets.top = 16;
              newInsets.left = 2;
              newInsets.bottom = 2;
              newInsets.right = 2;
            }
          return newInsets;  
        }

    }
    
    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component.
     * @param g  the graphics device.
     * @param x  the x-coordinate.
     * @param y  the y-coordinate.
     * @param w  the width.
     * @param h  the height.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
        int h)
    {
        
      JToolBar tb = (JToolBar) c;
      if (tb.getOrientation() == JToolBar.HORIZONTAL)
        {
           MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5, 
                  MetalLookAndFeel.getControlHighlight(), 
                  MetalLookAndFeel.getControlDarkShadow());
        }
      else
        { 
          MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11, 
                  MetalLookAndFeel.getControlHighlight(), 
                  MetalLookAndFeel.getControlDarkShadow());
        }
    }
    
  }
  
  /**
   * A border for table header cells.
   *
   * @since 1.3
   */
  public static class TableHeaderBorder extends AbstractBorder
  {
    /**
     * The insets of this border.
     */
    // TODO: According to tests that I have done, this is really the border
    // that should be returned by getBorderInsets(). However, the name
    // is very distracting. Is there any deeper meaning in it?
    protected Insets editorBorderInsets;

    /**
     * Creates a new instance of <code>TableHeaderBorder</code>.
     */
    public TableHeaderBorder()
    {
      editorBorderInsets = new Insets(1, 1, 1, 1);
    }

    /**
     * Return the insets of this border.
     *
     * @return the insets of this border
     */
    public Insets getBorderInsets(Component c)
    {
      return editorBorderInsets;
    }

    /**
     * Paints the border.
     *
     * @param c the component for which to paint the border
     * @param g the graphics context to use
     * @param x the x cooridinate of the border rectangle
     * @param y the y cooridinate of the border rectangle
     * @param w the width of the border rectangle
     * @param h the height of the border rectangle
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
    {
      Color dark = MetalLookAndFeel.getControlDarkShadow();
      Color light = MetalLookAndFeel.getWhite();
      Color old = g.getColor();
      g.setColor(light);
      g.drawLine(x, y, x + w - 2, y);
      g.drawLine(x, y, x, y + h - 2);
      g.setColor(dark);
      g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
      g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
      g.setColor(old);
    }
  }

  /**
   * Returns a border for Swing buttons in the Metal Look &amp; Feel.
   *
   * @return a border for Swing buttons in the Metal Look &amp; Feel
   */
  public static Border getButtonBorder()
  {
    if (buttonBorder == null)
      {
        Border outer = new ButtonBorder();
        Border inner = getMarginBorder();
        buttonBorder = new BorderUIResource.CompoundBorderUIResource(outer, 
            inner);
      }
    return buttonBorder;
  }
  
  /**
   * Returns a border for use with {@link JToggleButton} components.
   *
   * @return A border.
   * 
   * @since 1.3
   */
  public static Border getToggleButtonBorder()
  {
    if (toggleButtonBorder == null)
      {
        Border outer = new ToggleButtonBorder();
        Border inner = getMarginBorder();
        toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
            outer, inner);
      }
    return toggleButtonBorder;
  }

  /**
   * Returns a border instance that is used with a {@link JInternalFrame} when
   * it is in the iconified state.
   * 
   * @return A border.
   * 
   * @since 1.3
   */
  public static Border getDesktopIconBorder()
  {
    if (desktopIconBorder == null)
      desktopIconBorder = new DesktopIconBorder();
    return desktopIconBorder;      
  }

  /**
   * Returns a border for use by the {@link JTextField} component.
   * 
   * @return A border.
   * 
   * @since 1.3
   */
  public static Border getTextFieldBorder()
  {
    if (textFieldBorder == null)
      {
        Border inner = getMarginBorder();
        Border outer = new TextFieldBorder();
        textFieldBorder =
          new BorderUIResource.CompoundBorderUIResource(outer, inner);
      }
    return textFieldBorder;
  }

  /**
   * Returns the border that is used for text components (except text fields,
   * which use {@link #getTextFieldBorder}.
   *
   * @return the border that is used for text components
   *
   * @since 1.3
   */
  public static Border getTextBorder()
  {
    if (textBorder == null)
      {
        Border inner = getMarginBorder();
        Border outer = new Flush3DBorder();
        textBorder =
          new BorderUIResource.CompoundBorderUIResource(outer, inner);
      }
    return textBorder;
  }

  /**
   * Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
   *
   * @return a border for Toolbar buttons in the Metal Look &amp; Feel
   */
  static Border getToolbarButtonBorder()
  {
    if (toolbarButtonBorder == null)
      {
        Border outer = new ButtonBorder();
        Border inner = new RolloverMarginBorder();
        toolbarButtonBorder = new CompoundBorder(outer, inner);
      }
    return toolbarButtonBorder;
  }

  /**
   * Returns a shared instance of {@link BasicBorders.MarginBorder}.
   *
   * @return a shared instance of {@link BasicBorders.MarginBorder}
   */
  static Border getMarginBorder()
  {
    if (marginBorder == null)
      marginBorder = new BasicBorders.MarginBorder();
    return marginBorder;
  }

  /**
   * Returns a shared instance of a compound border for rollover buttons.
   * 
   * @return A shared border instance.
   */
  static Border getRolloverBorder()
  {
    if (rolloverBorder == null)
      {
        Border outer = new MetalBorders.RolloverButtonBorder();
        Border inner = MetalBorders.getMarginBorder();
        rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer, 
            inner);
      }
    return rolloverBorder;
  }

}
