/* BasicBorders.java --
   Copyright (C) 2003, 2004, 2005  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.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.io.Serializable;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JPopupMenu;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.text.JTextComponent;

/**
 * Provides various borders for the Basic look and feel.
 *
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class BasicBorders
{
  /**
   * A MarginBorder that gets shared by multiple components.
   * Created on demand by the private helper function {@link
   * #getMarginBorder()}.
   */
  private static MarginBorder sharedMarginBorder;


  /**
   * Returns a border for drawing push buttons.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;Button.shadow&#x201d;</code>,
   * <code>&#x201c;Button.darkShadow&#x201d;</code>,
   * <code>&#x201c;Button.light&#x201d;</code>, and
   * <code>&#x201c;Button.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300"
   * height="170" alt="[A screen shot of the returned border]" />
   *
   * @return a {@link
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
   *         whose outer border is a {@link ButtonBorder} and whose
   *         inner border is a {@link MarginBorder}.
   */
  public static Border getButtonBorder()
  {
    Border outer;

    /* The keys for UIDefaults have been determined by writing a
     * test program that dumps the UIDefaults to stdout; that program
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
     * the key "light" is usually called "highlight", and "highlight"
     * is usually called "lightHighlight".
     */
    outer = new ButtonBorder(UIManager.getColor("Button.shadow"),
                             UIManager.getColor("Button.darkShadow"),
                             UIManager.getColor("Button.light"),
                             UIManager.getColor("Button.highlight"));

    /* While the inner border is shared between multiple buttons,
     * we do not share the outer border because ButtonBorders store
     * their border colors. We cannot guarantee that the colors
     * (which come from UIDefaults) are unchanged between invocations
     * of getButtonBorder. We could store the last colors, and share
     * the button border if the colors are the same as in the last
     * invocation, but it probably is not worth the effort.
     */
    return new BorderUIResource.CompoundBorderUIResource(
      outer,
      /* inner */ getMarginBorder());
  }


  /**
   * Returns a border for drawing radio buttons.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;RadioButton.shadow&#x201d;</code>,
   * <code>&#x201c;RadioButton.darkShadow&#x201d;</code>,
   * <code>&#x201c;RadioButton.light&#x201d;</code>, and
   * <code>&#x201c;RadioButton.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300"
   * height="135" alt="[A screen shot of the returned border]" />
   *
   * @return a {@link
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
   *         whose outer border is a {@link RadioButtonBorder} and whose
   *         inner border is a {@link MarginBorder}.
   */
  public static Border getRadioButtonBorder()
  {
    Border outer;

    /* The keys for UIDefaults have been determined by writing a
     * test program that dumps the UIDefaults to stdout; that program
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
     * the key "light" is usually called "highlight", and "highlight"
     * is usually called "lightHighlight".
     */
    outer = new RadioButtonBorder(
      UIManager.getColor("RadioButton.shadow"),
      UIManager.getColor("RadioButton.darkShadow"),
      UIManager.getColor("RadioButton.light"),
      UIManager.getColor("RadioButton.highlight"));

    /* While the inner border is shared between multiple buttons, we
     * do not share the outer border because RadioButtonBorders, being
     * ButtonBorders, store their border colors. We cannot guarantee
     * that the colors (which come from UIDefaults) are unchanged
     * between invocations of getButtonBorder. We could store the last
     * colors, and share the button border if the colors are the same
     * as in the last invocation, but it probably is not worth the
     * effort.
     */
    return new BorderUIResource.CompoundBorderUIResource(
      outer,
      /* inner */ getMarginBorder());
  }


  /**
   * Returns a border for drawing toggle buttons.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;ToggleButton.shadow&#x201d;</code>,
   * <code>&#x201c;ToggleButton.darkShadow&#x201d;</code>,
   * <code>&#x201c;ToggleButton.light&#x201d;</code>, and
   * <code>&#x201c;ToggleButton.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png" width="270"
   * height="135" alt="[A screen shot of the returned border]" />
   *
   * @return a {@link
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
   *         whose outer border is a {@link ToggleButtonBorder} and whose
   *         inner border is a {@link MarginBorder}.
   */
  public static Border getToggleButtonBorder()
  {
    Border outer;

    /* The keys for UIDefaults have been determined by writing a
     * test program that dumps the UIDefaults to stdout; that program
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
     * the key "light" is usually called "highlight", and "highlight"
     * is usually called "lightHighlight".
     */
    outer = new ToggleButtonBorder(
      UIManager.getColor("ToggleButton.shadow"),
      UIManager.getColor("ToggleButton.darkShadow"),
      UIManager.getColor("ToggleButton.light"),
      UIManager.getColor("ToggleButton.highlight"));

    /* While the inner border is shared between multiple buttons, we
     * do not share the outer border because ToggleButtonBorders, being
     * ButtonBorders, store their border colors. We cannot guarantee
     * that the colors (which come from UIDefaults) are unchanged
     * between invocations of getButtonBorder. We could store the last
     * colors, and share the button border if the colors are the same
     * as in the last invocation, but it probably is not worth the
     * effort.
     */
    return new BorderUIResource.CompoundBorderUIResource(
      outer,
      /* inner */ getMarginBorder());
  }


  /**
   * Returns a border for drawing a two-pixel thick separator line
   * below menu bars.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;MenuBar.shadow&#x201d;</code> and
   * <code>&#x201c;MenuBar.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
   * height="140" alt="[A screen shot of a JMenuBar with this border]" />
   *
   * @return a {@link MenuBarBorder}.
   *
   * @see javax.swing.JMenuBar
   */
  public static Border getMenuBarBorder()
  {
    /* See comment in methods above for why this border is not shared. */
    return new MenuBarBorder(UIManager.getColor("MenuBar.shadow"),
                             UIManager.getColor("MenuBar.highlight"));
  }


  /**
   * Returns a border for drawing a one-pixel thick border around
   * split panes that are interrupted where the divider joins the
   * border.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;SplitPane.darkShadow&#x201d;</code> and
   * <code>&#x201c;SplitPane.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
   * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
   * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
   *
   * @return a {@link SplitPaneBorder}.
   *
   * @see javax.swing.JSplitPane
   * @see #getSplitPaneDividerBorder()
   */
  public static Border getSplitPaneBorder()
  {
    /* See comment in methods above for why this border is not shared. */
    return new SplitPaneBorder(UIManager.getColor("SplitPane.highlight"),
                               UIManager.getColor("SplitPane.darkShadow"));
  }


  /**
   * Returns a border for drawing a one-pixel thick border around
   * the divider of split panes.
   *
   * <p>The colors of the edges that are adjacent to the child components
   * of the <code>JSplitPane</code> are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;SplitPane.darkShadow&#x201d;</code> and
   * <code>&#x201c;SplitPane.highlight&#x201d;</code>. The color of the
   * other two edges is the background color of the divider.
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
   * width="520" height="200" alt=
   * "[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
   *
   * @return an instance of <code>SplitPaneDividerBorder</code>, which is
   *         not a public API class of this package.
   *
   * @see javax.swing.JSplitPane
   * @see javax.swing.plaf.basic.BasicSplitPaneDivider
   * @see #getSplitPaneBorder()
   *
   * @since 1.3
   */
  public static Border getSplitPaneDividerBorder()
  {
    /* See comment in methods above for why this border is not shared. */
    return new SplitPaneDividerBorder();
  }


  /**
   * Returns a border for drawing a border around a text field
   * that makes the field appear as etched into the surface.
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;TextField.shadow&#x201d;</code>,
   * <code>&#x201c;TextField.darkShadow&#x201d;</code>,
   * <code>&#x201c;TextField.light&#x201d;</code>, and
   * <code>&#x201c;TextField.highlight&#x201d;</code>.
   *
   * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500"
   * height="200" alt="[A screen shot of a border returned by
   * this method]" />
   *
   * @return an instance of {@link FieldBorder}.
   *
   * @see javax.swing.JTextField
   * @see javax.swing.text.JTextComponent
   */
  public static Border getTextFieldBorder()
  {
    /* See comment in methods above for why this border is not shared. */
    return new FieldBorder(
      UIManager.getColor("TextField.shadow"),
      UIManager.getColor("TextField.darkShadow"),
      UIManager.getColor("TextField.light"),
      UIManager.getColor("TextField.highlight"));
  }


  /**
   * Returns a two-pixel thick, green
   * <code>LineBorderUIResource</code>.  This is so ugly that look and
   * feels better use different borders for their progress bars, or
   * they will look really terrible.
   *
   * <p><img src="doc-files/BasicBorders-1.png" width="120" height="80"
   * alt="[A screen shot of a border returned by this method]" />
   */
  public static Border getProgressBarBorder()
  {
    /* There does not seem to exist a way to parametrize the color
     * or thickness of the border through UIDefaults.
     */
    return new BorderUIResource.LineBorderUIResource(Color.green, 2);
  }


  /**
   * Returns a border that is composed of a raised bevel border and a
   * one-pixel thick line border.
   *
   * <p><img src="doc-files/BasicBorders-2.png" width="300" height="200"
   * alt="[A screen shot of a border returned by this method]" />
   *
   * <p>The colors of the border are retrieved from the
   * <code>UIDefaults</code> of the currently active look and feel
   * using the keys <code>&#x201c;InternalFrame.borderShadow&#x201d;</code>,
   * <code>&#x201c;InternalFrame.borderDarkShadow&#x201d;</code>,
   * <code>&#x201c;InternalFrame.borderLight&#x201d;</code>,
   * <code>&#x201c;InternalFrame.borderHighlight&#x201d;</code>, and
   * (for the inner one-pixel thick line)
   * <code>&#x201c;InternalFrame.borderColor&#x201d;</code>.
   */
  public static Border getInternalFrameBorder()
  {
    Color shadow, darkShadow, highlight, lightHighlight, line;

    /* See comment in methods above for why this border is not shared. */
    shadow = UIManager.getColor("InternalFrame.borderShadow");
    darkShadow = UIManager.getColor("InternalFrame.borderDarkShadow");
    highlight = UIManager.getColor("InternalFrame.borderLight");
    lightHighlight = UIManager.getColor("InternalFrame.borderHighlight");
    line = UIManager.getColor("InternalFrame.borderColor");

    return new BorderUIResource.CompoundBorderUIResource(
      /* outer border */
      new BorderUIResource.BevelBorderUIResource(
        BevelBorder.RAISED,
        (highlight != null) ? highlight : Color.lightGray,
        (lightHighlight != null) ? lightHighlight : Color.white,
        (darkShadow != null) ? darkShadow : Color.black,
        (shadow != null) ? shadow : Color.gray),

      /* inner border */
      new BorderUIResource.LineBorderUIResource(
        (line != null) ? line : Color.lightGray));
  }


  /**
   * Returns a shared MarginBorder.
   */
  static Border getMarginBorder()  // intentionally not public
  {
    /* Swing is not designed to be thread-safe, so there is no
     * need to synchronize the access to the global variable.
     */
    if (sharedMarginBorder == null)
      sharedMarginBorder = new MarginBorder();

    return sharedMarginBorder;
  }


  /**
   * A border whose appearance depends on the state of
   * the enclosed button.
   *
   * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300"
   * height="170" alt="[A screen shot of this border]" />
   *
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class ButtonBorder
    extends AbstractBorder
    implements Serializable, UIResource
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = -157053874580739687L;


    /**
     * The color for drawing the shaded parts of the border.
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    protected Color shadow;


    /**
     * The color for drawing the dark shaded parts of the border.
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    protected Color darkShadow;


    /**
     * The color for drawing the highlighted parts of the border.
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    protected Color highlight;


    /**
     * The color for drawing the bright highlighted parts of the border.
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    protected Color lightHighlight;


    /**
     * Constructs a new border for drawing a button in the Basic
     * look and feel.
     *
     * @param shadow the shadow color.
     * @param darkShadow a darker variant of the shadow color.
     * @param highlight the highlight color.
     * @param lightHighlight a brighter variant of the highlight  color.
     */
    public ButtonBorder(Color shadow, Color darkShadow,
                        Color highlight, Color lightHighlight)
    {
      /* These colors usually come from the UIDefaults of the current
       * look and feel. Use fallback values if the colors are not
       * supplied.  The API specification is silent about what
       * behavior is expected for null colors, so users should not
       * rely on this fallback (which is why it is not documented in
       * the above Javadoc).
       */
      this.shadow = (shadow != null) ? shadow : Color.gray;
      this.darkShadow = (darkShadow != null) ? darkShadow : Color.black;
      this.highlight = (highlight != null) ? highlight : Color.lightGray;
      this.lightHighlight = (lightHighlight != null)
        ? lightHighlight
        : Color.white;
    }


    /**
     * Paints the ButtonBorder around a given component.
     *
     * @param c the component whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     *
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      ButtonModel bmodel = null;

      if (c instanceof AbstractButton)
        bmodel = ((AbstractButton) c).getModel();

      BasicGraphicsUtils.drawBezel(
        g, x, y, width, height,
        /* pressed */ (bmodel != null)
                        && /* mouse button pressed */ bmodel.isPressed()
                        && /* mouse inside */ bmodel.isArmed(),
        /* default */ (c instanceof JButton)
                        && ((JButton) c).isDefaultButton(),
        shadow, darkShadow, highlight, lightHighlight);
    }


    /**
     * Measures the width of this border.
     *
     * <p>Although the thickness of the actually painted border
     * depends on the state of the enclosed component, this
     * measurement always returns the same amount of pixels.  Indeed,
     * it would be rather confusing if a button was appearing to
     * change its size depending on whether it is pressed or not.
     *
     * @param c the component whose border is to be measured.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      /* There is no obvious reason for overriding this method, but we
       * try to have exactly the same API as the Sun reference
       * implementation.
       */
      return getBorderInsets(c, null);
    }


    /**
     * Measures the width of this border, storing the results into a
     * pre-existing Insets object.
     *
     * <p>Although the thickness of the actually painted border
     * depends on the state of the enclosed component, this
     * measurement always returns the same amount of pixels.  Indeed,
     * it would be rather confusing if a button was appearing to
     * change its size depending on whether it is pressed or not.
     *
     * @param insets an Insets object for holding the result values.
     *        After invoking this method, the <code>left</code>,
     *        <code>right</code>, <code>top</code> and
     *        <code>bottom</code> fields indicate the width of the
     *        border at the respective edge.
     *
     * @return the same object that was passed for <code>insets</code>.
     *
     * @see #getBorderInsets(Component)
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      /* The exact amount has been determined using a test program
       * that was run on the Sun reference implementation. With
       * Apple/Sun JDK 1.3.1 on MacOS X 10.1.5, the result is
       * [3, 3, 3, 3]. With Sun JDK 1.4.1_01 on Linux/x86, the
       * result is [2, 3, 3, 3]. We use the values from the 1.4.1_01
       * release.
       */
      if (insets == null)
        return new Insets(2, 3, 3, 3);

      insets.top = 2;
      insets.bottom = insets.left = insets.right = 3;
      return insets;
    }
  }


  /**
   * A border that makes its enclosed component appear as lowered
   * into the surface. Typically used for text fields.
   *
   * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500"
   * height="200" alt="[A screen shot of this border]" />
   *
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class FieldBorder
    extends AbstractBorder
    implements UIResource
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = 949220756998454908L;


    /**
     * The color for drawing the outer half of the top and left
     * edges.
     */
    protected Color shadow;


    /**
     * The color for drawing the inner half of the top and left
     * edges.
     */
    protected Color darkShadow;


    /**
     * The color for drawing the inner half of the bottom and right
     * edges.
     */
    protected Color highlight;


    /**
     * The color for drawing the outer half of the bottom and right
     * edges.
     */
    protected Color lightHighlight;


    /**
     * Constructs a new border for drawing a text field in the Basic
     * look and feel.
     *
     * @param shadow the color for drawing the outer half
     *        of the top and left edges.
     *
     * @param darkShadow the color for drawing the inner half
     *        of the top and left edges.
     *
     * @param highlight the color for drawing the inner half
     *        of the bottom and right edges.
     *
     * @param lightHighlight the color for drawing the outer half
     *        of the bottom and right edges.
     */
    public FieldBorder(Color shadow, Color darkShadow,
                       Color highlight, Color lightHighlight)
    {
      /* These colors usually come from the UIDefaults of the current
       * look and feel. Use fallback values if the colors are not
       * supplied.  The API specification is silent about what
       * behavior is expected for null colors, so users should not
       * rely on this fallback (which is why it is not documented in
       * the above Javadoc).
       */
      this.shadow = (shadow != null) ? shadow : Color.gray;
      this.darkShadow = (darkShadow != null) ? darkShadow : Color.black;
      this.highlight = (highlight != null) ? highlight : Color.lightGray;
      this.lightHighlight = (lightHighlight != null)
        ? lightHighlight : Color.white;
    }


    /**
     * Paints the FieldBorder around a given component.
     *
     * @param c the component whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     *
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height,
                                        shadow, darkShadow,
                                        highlight, lightHighlight);
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured.
     *        If <code>c</code> is an instance of {@link
     *        javax.swing.text.JTextComponent}, its margin is
     *        added to the border size.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }


    /**
     * Measures the width of this border, storing the results into a
     * pre-existing Insets object.
     *
     * @param c the component whose border is to be measured.
     *        If <code>c</code> is an instance of {@link
     *        javax.swing.text.JTextComponent}, its margin is
     *        added to the border size.
     *
     * @param insets an Insets object for holding the result values.
     *        After invoking this method, the <code>left</code>,
     *        <code>right</code>, <code>top</code> and
     *        <code>bottom</code> fields indicate the width of the
     *        border at the respective edge.
     *
     * @return the same object that was passed for <code>insets</code>.
     *
     * @see #getBorderInsets(Component)
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      if (insets == null)
        insets = new Insets(2, 2, 2, 2);
      else
        insets.top = insets.left = insets.bottom = insets.right = 2;

      if (c instanceof JTextComponent)
      {
        Insets margin = ((JTextComponent) c).getMargin();
        insets.top += margin.top;
        insets.left += margin.left;
        insets.bottom += margin.bottom;
        insets.right += margin.right;
      }

      return insets;
    }
  }


  /**
   * An invisible, but spacing border whose margin is determined
   * by calling the <code>getMargin()</code> method of the enclosed
   * component.  If the enclosed component has no such method,
   * this border will not occupy any space.
   *
   * <p><img src="doc-files/BasicBorders.MarginBorder-1.png" width="325"
   * height="200" alt="[An illustration that shows how MarginBorder
   * determines its borders]" />
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class MarginBorder
    extends AbstractBorder
    implements Serializable, UIResource
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = -3035848353448896090L;


    /**
     * Constructs a new MarginBorder.
     */
    public MarginBorder()
    {
      // Nothing to do here.
    }

    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured.
     *
     * @return an Insets object whose <code>left</code>, <code>right</code>,
     *         <code>top</code> and <code>bottom</code> fields indicate the
     *         width of the border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, new Insets(0, 0, 0, 0));
    }


    /**
     * Determines the insets of this border by calling the
     * <code>getMargin()</code> method of the enclosed component.  The
     * resulting margin will be stored into the the <code>left</code>,
     * <code>right</code>, <code>top</code> and <code>bottom</code>
     * fields of the passed <code>insets</code> parameter.
     *
     * <p>Unfortunately, <code>getMargin()</code> is not a method of
     * {@link javax.swing.JComponent} or some other common superclass
     * of things with margins. While reflection could be used to
     * determine the existence of this method, this would be slow on
     * many virtual machines. Therefore, the current implementation
     * knows about {@link javax.swing.AbstractButton#getMargin()},
     * {@link javax.swing.JPopupMenu#getMargin()}, {@link
     * javax.swing.JToolBar#getMargin()}, and {@link
     * javax.swing.text.JTextComponent}. If <code>c</code> is an
     * instance of a known class, the respective
     * <code>getMargin()</code> method is called to determine the
     * correct margin. Otherwise, a zero-width margin is returned.
     *
     * @param c the component whose border is to be measured.
     *
     * @return the same object that was passed for <code>insets</code>,
     *         but with changed fields.
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      Insets margin = null;

      /* This is terrible object-oriented design. See the above Javadoc
       * for an excuse.
       */
      if (c instanceof AbstractButton)
        margin = ((AbstractButton) c).getMargin();
      else if (c instanceof JPopupMenu)
        margin = ((JPopupMenu) c).getMargin();
      else if (c instanceof JToolBar)
        margin = ((JToolBar) c).getMargin();
      else if (c instanceof JTextComponent)
        margin = ((JTextComponent) c).getMargin();

      if (margin == null)
        insets.top = insets.left = insets.bottom = insets.right = 0;
      else
      {
        insets.top = margin.top;
        insets.left = margin.left;
        insets.bottom = margin.bottom;
        insets.right = margin.right;
      }

      return insets;
    }
  }


  /**
   * A border for drawing a separator line below JMenuBar.
   *
   * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
   * height="140" alt="[A screen shot of a JMenuBar with this border]" />
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class MenuBarBorder
    extends AbstractBorder
    implements UIResource
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = -6909056571935227506L;


    /**
     * The shadow color, which is used for the upper line of the
     * two-pixel thick bottom edge.
     */
    private Color shadow;


    /**
     * The highlight color, which is used for the lower line of the
     * two-pixel thick bottom edge.
     */
    private Color highlight;


    /**
     * Constructs a new MenuBarBorder for drawing a JMenuBar in
     * the Basic look and feel.
     *
     * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
     * height="140" alt="[A screen shot of a JMenuBar with this
     * border]" />
     *
     * @param shadow the shadow color, which is used for the upper
     *        line of the two-pixel thick bottom edge.
     *
     * @param highlight the shadow color, which is used for the lower
     *        line of the two-pixel thick bottom edge.
     */
    public MenuBarBorder(Color shadow, Color highlight)
    {
      /* These colors usually come from the UIDefaults of the current
       * look and feel. Use fallback values if the colors are not
       * supplied.  The API specification is silent about what
       * behavior is expected for null colors, so users should not
       * rely on this fallback (which is why it is not documented in
       * the above Javadoc).
       */
      this.shadow = (shadow != null) ? shadow : Color.gray;
      this.highlight = (highlight != null) ? highlight : Color.white;
    }


    /**
     * Paints the MenuBarBorder around a given component.
     *
     * @param c the component whose border is to be painted, usually
     *        an instance of {@link javax.swing.JMenuBar}.
     *
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      Color oldColor;

      /* To understand this code, it might be helpful to look at the
       * image "BasicBorders.MenuBarBorder-1.png" that is included
       * with the JavaDoc. It is located in the "doc-files"
       * subdirectory.
       */
      oldColor = g.getColor();
      y = y + height - 2;
      try
      {
        g.setColor(shadow);
        g.drawLine(x, y, x + width - 2, y);
        g.drawLine(x, y + 1, x, y + 1);
        g.drawLine(x + width - 2, y + 1, x + width - 2, y + 1);

        g.setColor(highlight);
        g.drawLine(x + 1, y + 1, x + width - 3, y + 1);
        g.drawLine(x + width - 1, y, x + width - 1, y + 1);
      }
      finally
      {
        g.setColor(oldColor);
      }
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      /* There is no obvious reason for overriding this method, but we
       * try to have exactly the same API as the Sun reference
       * implementation.
       */
      return getBorderInsets(c, null);
    }


    /**
     * Measures the width of this border, storing the results into a
     * pre-existing Insets object.
     *
     * @param insets an Insets object for holding the result values.
     *        After invoking this method, the <code>left</code>,
     *        <code>right</code>, <code>top</code> and
     *        <code>bottom</code> fields indicate the width of the
     *        border at the respective edge.
     *
     * @return the same object that was passed for <code>insets</code>.
     *
     * @see #getBorderInsets(Component)
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      /* The exact amount has been determined using a test program
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [0,0,2,0],
       * which was expected from looking at the screen shot.
       */
      if (insets == null)
        return new Insets(0, 0, 2, 0);

      insets.left = insets.right = insets.top = 0;
      insets.bottom = 2;
      return insets;
    }
  }


  /**
   * A border for drawing radio buttons in the Basic look and feel.
   *
   * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300"
   * height="135" alt="[A screen shot of this border]" />
   *
   * <p>Note about the screen shot: Normally, the
   * <code>borderPainted</code> property is <code>false</code> for
   * JRadioButtons. For this screen shot, it has been set to
   * <code>true</code> so the borders get drawn. Also, a
   * concretization of the Basic look and would typically provide
   * icons for the various states of radio buttons.
   *
   * <p>Note that the focus rectangle is invisible If the radio button
   * is currently selected. While it might be debatable whether this
   * makes a lot of sense, this behavior can be observed in the Sun
   * reference implementation (in JDK 1.3.1 and 1.4.1). The Classpath
   * implementation tries to exactly replicate the JDK appearance.
   *
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class RadioButtonBorder
    extends ButtonBorder
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = 1596945751743747369L;


    /**
     * Constructs a new border for drawing a JRadioButton in
     * the Basic look and feel.
     *
     * @param shadow the shadow color.
     * @param darkShadow a darker variant of the shadow color.
     * @param highlight the highlight color.
     * @param lightHighlight a brighter variant of the highlight  color.
     */
    public RadioButtonBorder(Color shadow, Color darkShadow,
                             Color highlight, Color lightHighlight)
    {
      /* The superclass ButtonBorder substitutes null arguments
       * with fallback colors.
       */
      super(shadow, darkShadow, highlight, lightHighlight);
    }


    /**
     * Paints the RadioButtonBorder around a given component.
     *
     * <p>The Sun implementation always seems to draw exactly
     * the same border, irrespective of the state of the button.
     * This is rather surprising, but GNU Classpath emulates the
     * observable behavior.
     *
     * @param c the component whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     *
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      AbstractButton button = null;
      ButtonModel bmodel = null;
      boolean lowered = false;
      boolean focused = false;

      if (c instanceof AbstractButton)
      {
        button = (AbstractButton) c;
        bmodel = button.getModel();
      }

      if (bmodel != null)
      {
        lowered = button.isSelected()
          || (/* mouse inside */ bmodel.isArmed() && bmodel.isPressed());
        focused = button.hasFocus() && button.isFocusPainted();
      }

      if (lowered)
        BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height,
                                            shadow, darkShadow,
                                            highlight, lightHighlight);
      else
        BasicGraphicsUtils.drawBezel(g, x, y, width, height,
                                     /* isPressed */ false,
                                     /* isPefault */ focused,
                                     shadow, darkShadow,
                                     highlight, lightHighlight);
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      /* There is no obvious reason for overriding this method, but we
       * try to have exactly the same API as the Sun reference
       * implementation.
       */
      return getBorderInsets(c, null);
    }


    /**
     * Measures the width of this border, storing the results into a
     * pre-existing Insets object.
     *
     * @param insets an Insets object for holding the result values.
     *        After invoking this method, the <code>left</code>,
     *        <code>right</code>, <code>top</code> and
     *        <code>bottom</code> fields indicate the width of the
     *        border at the respective edge.
     *
     * @return the same object that was passed for <code>insets</code>.
     *
     * @see #getBorderInsets(Component)
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      /* The exact amount has been determined using a test program
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2].
       */
      if (insets == null)
        return new Insets(2, 2, 2, 2);

      insets.left = insets.right = insets.top = insets.bottom = 2;
      return insets;
    }
  }


  /**
   * A one-pixel thick border for rollover buttons, for example in
   * tool bars.
   *
   * @since 1.4
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class RolloverButtonBorder
    extends ButtonBorder
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Sun JDK 1.4.1_01 on GNU/Linux 2.4.20 for x86.
     */
    static final long serialVersionUID = 1976364864896996846L;


    /**
     * Constructs a new border for drawing a roll-over button
     * in the Basic look and feel.
     *
     * @param shadow the shadow color.
     * @param darkShadow a darker variant of the shadow color.
     * @param highlight the highlight color.
     * @param lightHighlight a brighter variant of the highlight  color.
     */
    public RolloverButtonBorder(Color shadow, Color darkShadow,
                                Color highlight, Color lightHighlight)
    {
      super(shadow, darkShadow, highlight, lightHighlight);
    }


    /**
     * Paints the border around a rollover button.  If <code>c</code>
     * is not an {@link javax.swing.AbstractButton} whose model
     * returns <code>true</code> for {@link
     * javax.swing.ButtonModel#isRollover}, nothing gets painted at
     * all.
     *
     * @param c the button whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      ButtonModel bmodel = null;
      boolean drawPressed;
      Color oldColor = g.getColor();
      int x2, y2;

      if (c instanceof AbstractButton)
        bmodel = ((AbstractButton) c).getModel();

      /* Draw nothing if c is not a rollover button. */
      if ((bmodel == null) || !bmodel.isRollover())
        return;

      /* Draw nothing if the mouse is pressed, but outside the button. */
      if (bmodel.isPressed() && !bmodel.isArmed())
        return;

      drawPressed = bmodel.isSelected() || bmodel.isPressed();
      x2 = x + width - 1;
      y2 = y + height - 1;

      try
      {
        g.setColor(drawPressed ? shadow : lightHighlight);
        g.drawLine(x, y, x2 - 1, y);     // top edge
        g.drawLine(x, y + 1, x, y2 - 1); // left edge

        g.setColor(drawPressed ? lightHighlight : shadow);
        g.drawLine(x, y2, x2, y2);       // bottom edge
        g.drawLine(x2, y, x2, y2 - 1);   // right edge
      }
      finally
      {
        g.setColor(oldColor);
      }
    }
  }


  /**
   * A border for JSplitPanes in the Basic look and feel. The divider
   * in the middle of the JSplitPane has its own border class, of which
   * an instance can be obtained with {@link #getSplitPaneDividerBorder()}.
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
   * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
   * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
   *
   * <p>In contrast to the other borders of the Basic look and feel,
   * this class is not serializable. While this might be unintended,
   * GNU Classpath follows the specification in order to be fully
   * compatible with the Sun reference implementation.
   *
   * <p>In the Sun JDK, the bottom edge of the divider also gets
   * painted if the orientation of the enclosed JSplitPane is
   * <code>JSplitPane.VERTICAL_SPLIT</code> (at least in versions
   * 1.3.1 and 1.4.1).  GNU Classpath does not replicate this bug. A
   * report has been filed with Sun (bug ID 4885629).
   *
   * <p>Note that the bottom left pixel of the border has a different
   * color depending on the orientation of the enclosed JSplitPane.
   * Although this is visually inconsistent, Classpath replicates the
   * appearance of the Sun reference implementation. A bug report has
   * been filed with Sun (review ID 188774).
   *
   * @see #getSplitPaneBorder()
   * @see #getSplitPaneDividerBorder()
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class SplitPaneBorder implements Border, UIResource
  {
    /**
     * Indicates that the top edge shall be not be painted
     * by {@link #paintRect}.
     */
    private static final int SUPPRESS_TOP = 1;


    /**
     * Indicates that the left edge shall be not be painted
     * by {@link #paintRect}.
     */
    private static final int SUPPRESS_LEFT = 2;


    /**
     * Indicates that the bottom edge shall be not be painted
     * by {@link #paintRect}.
     */
    private static final int SUPPRESS_BOTTOM = 4;


    /**
     * Indicates that the right edge shall be not be painted
     * by {@link #paintRect}.
     */
    private static final int SUPPRESS_RIGHT = 8;


    /**
     * The color for drawing the bottom and right edges of the border.
     */
    protected Color highlight;


    /**
     * The color for drawing the top and left edges of the border.
     */
    protected Color shadow;


    /**
     * Constructs a new border for drawing a JSplitPane in the Basic
     * look and feel.  The divider in the middle of the JSplitPane has
     * its own border class, <code>SplitPaneDividerBorder</code>.
     *
     * @param shadow the shadow color.
     * @param highlight the highlight color.
     */
    public SplitPaneBorder(Color highlight, Color shadow)
    {
      /* These colors usually come from the UIDefaults of the current
       * look and feel. Use fallback values if the colors are not
       * supplied.  The API specification is silent about what
       * behavior is expected for null colors, so users should not
       * rely on this fallback (which is why it is not documented in
       * the above Javadoc).
       */
      this.shadow = (shadow != null) ? shadow : Color.black;
      this.highlight = (highlight != null) ? highlight : Color.white;
    }


    /**
     * Paints the border around a <code>JSplitPane</code>.
     *
     * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
     * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
     *
     * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
     * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
     *
     * @param c the <code>JSplitPane</code> whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      JSplitPane splitPane;
      Component content;

      if (!(c instanceof JSplitPane))
        return;

      splitPane = (JSplitPane) c;
      switch (splitPane.getOrientation())
      {
      case JSplitPane.HORIZONTAL_SPLIT:
        if ((content = splitPane.getLeftComponent()) != null)
          paintRect(g, SUPPRESS_RIGHT, true, x, y, content.getBounds());
        if ((content = splitPane.getRightComponent()) != null)
          paintRect(g, SUPPRESS_LEFT, true, x, y, content.getBounds());
        break;

      case JSplitPane.VERTICAL_SPLIT:
        if ((content = splitPane.getTopComponent()) != null)
          paintRect(g, SUPPRESS_BOTTOM, false, x, y, content.getBounds());
        if ((content = splitPane.getBottomComponent()) != null)
          paintRect(g, SUPPRESS_TOP, false, x, y, content.getBounds());
        break;
      }
    }


    /**
     * Paints a border around a child of a <code>JSplitPane</code>,
     * omitting some of the edges.
     *
     * @param g the graphics for painting.
     *
     * @param suppress a bit mask indicating the set of suppressed
     *        edges, for example <code>SUPPRESS_TOP | SUPPRESS_RIGHT</code>.
     *
     * @param x the x coordinate of the SplitPaneBorder.
     *
     * @param y the y coordinate of the SplitPaneBorder.
     *
     * @param shadeBottomLeftPixel <code>true</code> to paint the
     *        bottom left pixel in the shadow color,
     *        <code>false</code> for the highlight color. The Basic
     *        look and feel uses the highlight color for the bottom
     *        left pixel of the border of a JSplitPane whose
     *        orientation is VERTICAL_SPLIT, and the shadow color
     *        otherwise. While this might be a strange distinction,
     *        Classpath tries to look identical to the reference
     *        implementation. A bug report has been filed with Sun;
     *        its review ID is 188774. We currently replicate the
     *        Sun behavior.
     *
     * @param rect the bounds of the child of JSplitPane whose
     *        border is to be painted.
     */
    private void paintRect(Graphics g, int suppress,
                           boolean shadeBottomLeftPixel,
                           int x, int y,
                           Rectangle rect)
    {
      if (rect == null)
        return;

      /* On each edge, the border exceeds the enclosed child by one
       * pixel. See the image "BasicBorders.SplitPaneBorder-1.png" in
       * the directory "doc-files".
       */
      x += rect.x - 1;
      y += rect.y - 1;
      int right = x + rect.width + 1;
      int bottom = y + rect.height + 1;

      Color oldColor = g.getColor();
      try
      {
        g.setColor(shadow);
        if ((suppress & SUPPRESS_TOP) == 0)
          g.drawLine(x, y, right, y);
        if ((suppress & SUPPRESS_LEFT) == 0)
          g.drawLine(x, y, x, bottom);
        else
          g.drawLine(x, bottom, x, bottom); // one pixel

        g.setColor(highlight);
        if ((suppress & SUPPRESS_BOTTOM) == 0)
          g.drawLine(x + (shadeBottomLeftPixel ? 1 : 0), bottom, right, bottom);
        else if (!shadeBottomLeftPixel)
          g.drawLine(x, bottom, x, bottom); // one pixel

        if ((suppress & SUPPRESS_RIGHT) == 0)
          g.drawLine(right, y, right, bottom);
      }
      finally
      {
        g.setColor(oldColor);
      }
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured, usually
     *        an instance of {@link javax.swing.JSplitPane}.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     */
    public Insets getBorderInsets(Component c)
    {
      return new Insets(1, 1, 1, 1);
    }


    /**
     * Determines whether this border fills every pixel in its area
     * when painting.
     *
     * @return <code>false</code> because this border does not
     *         paint over the pixels where the divider joins
     *         the border.
     */
    public boolean isBorderOpaque()
    {
      /* Strangely, the Sun implementation (tested with JDK 1.3.1 and
       * 1.4.1_01) seems to always return true. It could be a bug,
       * but without knowing the details of their implementation, it is
       * hard to decide.
       */
      return false;
    }
  }


  /**
   * A border for the divider inside a JSplitPane.
   *
   * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
   * width="520" height="200" alt="[A screen shot of this border]" />
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  private static class SplitPaneDividerBorder
    implements Border, UIResource, Serializable
  {
    /**
     * Constructs a new border for drawing the divider of a JSplitPane
     * in the Basic look and feel.  The outer parts of the JSplitPane have
     * their own border class, <code>SplitPaneBorder</code>.
     */
    public SplitPaneDividerBorder()
    {
      // Nothing to do here.
    }

    /**
     * Paints the border around the divider of a <code>JSplitPane</code>.
     *
     * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
     * width="520" height="200" alt="[A picture that shows which pixels
     * get painted in what color]" />
     *
     * @param c the <code>JSplitPane</code> whose divider&#x2019;s border
     *        is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      Color highlight = UIManager.getColor("SplitPane.highlight");
      Color shadow = UIManager.getColor("SplitPane.shadow");
      Color oldColor, dcol;
      int x2, y2;
      JSplitPane sp;

      sp = getSplitPane(c);
      if (sp == null)
        return;

      x2 = x + width - 1;
      y2 = y + height - 1;
      oldColor = g.getColor();
      dcol = c.getBackground();
      try
      {
        switch (sp.getOrientation())
        {
        case JSplitPane.HORIZONTAL_SPLIT:
          g.setColor(dcol);
          g.drawLine(x + 1, y, x2 - 1, y);
          g.drawLine(x + 1, y2, x2 - 1, y2);
          g.setColor(sp.getLeftComponent() != null ? highlight : dcol);
          g.drawLine(x, y, x, y2);
          g.setColor(sp.getRightComponent() != null ? shadow : dcol);
          g.drawLine(x2, y, x2, y2);
          break;

        case JSplitPane.VERTICAL_SPLIT:
          g.setColor(dcol);
          g.drawLine(x, y + 1, x, y2 - 1);
          g.drawLine(x2, y + 1, x2, y2 - 1);
          g.setColor(sp.getTopComponent() != null ? highlight : dcol);
          g.drawLine(x, y, x2, y);
          g.setColor(sp.getBottomComponent() != null ? shadow : dcol);
          g.drawLine(x, y2, x2, y2);
          break;
        }
      }
      finally
      {
        g.setColor(oldColor);
      }
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured, usually
     *        an instance of {@link javax.swing.JSplitPane}.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     */
    public Insets getBorderInsets(Component c)
    {
      return new Insets(1, 1, 1, 1);
    }

    /**
     * Determines whether this border fills every pixel in its area
     * when painting.
     *
     * @return <code>true</code>
     */
    public boolean isBorderOpaque()
    {
      return true;
    }


    /**
     * Determines the JSplitPane whose divider is being painted.
     *
     * @param c an instance of BasicSplitPaneDivider.
     *
     * @return a <code>JSplitPane</code>, or <code>null</code> if
     *         <code>c</code> is not an instance of {@link
     *         javax.swing.plaf.basic.BasicSplitPaneDivider}.
     */
    private JSplitPane getSplitPane(Component c)
    {
      if (c instanceof BasicSplitPaneDivider)
        return (((BasicSplitPaneDivider) c).getBasicSplitPaneUI())
          .getSplitPane();
      else
        return null;
    }
  }


  /**
   * A border for toggle buttons in the Basic look and feel.
   *
   * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png"
   * width="270" height="135" alt="[A screen shot of this border]" />
   *
   * <p>The Sun implementation always seems to draw exactly
   * the same border, irrespective of the state of the button.
   * This is rather surprising, but GNU Classpath emulates the
   * observable behavior.
   *
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
   *
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static class ToggleButtonBorder
    extends ButtonBorder
  {
    /**
     * Determined using the <code>serialver</code> tool
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
     */
    static final long serialVersionUID = -3528666548001058394L;


    /**
     * Constructs a new border for drawing a JToggleButton in
     * the Basic look and feel.
     *
     * @param shadow the shadow color.
     * @param darkShadow a darker variant of the shadow color.
     * @param highlight the highlight color.
     * @param lightHighlight a brighter variant of the highlight  color.
     */
    public ToggleButtonBorder(Color shadow, Color darkShadow,
                              Color highlight, Color lightHighlight)
    {
      /* The superclass ButtonBorder substitutes null arguments
       * with fallback colors.
       */
      super(shadow, darkShadow, highlight, lightHighlight);
    }


    /**
     * Paints the ToggleButtonBorder around a given component.
     *
     * <p>The Sun implementation always seems to draw exactly
     * the same border, irrespective of the state of the button.
     * This is rather surprising, but GNU Classpath emulates the
     * observable behavior.
     *
     * @param c the component whose border is to be painted.
     * @param g the graphics for painting.
     * @param x the horizontal position for painting the border.
     * @param y the vertical position for painting the border.
     * @param width the width of the available area for painting the border.
     * @param height the height of the available area for painting the border.
     *
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
     */
    public void paintBorder(Component c, Graphics  g,
                            int x, int y, int width, int height)
    {
      /* The author of this code tried various variants for setting
       * the state of the enclosed JToggleButton, but it seems that
       * the drawn border is always identical. Weird, because this
       * means that the user does not see whether the JToggleButton
       * is selected or not.
       */
      BasicGraphicsUtils.drawBezel(g, x, y, width, height,
                                   /* pressed */ false,
                                   /* default */ false,
                                   shadow, darkShadow,
                                   highlight, lightHighlight);
    }


    /**
     * Measures the width of this border.
     *
     * @param c the component whose border is to be measured.
     *
     * @return an Insets object whose <code>left</code>,
     *         <code>right</code>, <code>top</code> and
     *         <code>bottom</code> fields indicate the width of the
     *         border at the respective edge.
     *
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
     */
    public Insets getBorderInsets(Component c)
    {
      /* There is no obvious reason for overriding this method, but we
       * try to have exactly the same API as the Sun reference
       * implementation.
       */
      return getBorderInsets(c, null);
    }


    /**
     * Measures the width of this border, storing the results into a
     * pre-existing Insets object.
     *
     * @param insets an Insets object for holding the result values.
     *        After invoking this method, the <code>left</code>,
     *        <code>right</code>, <code>top</code> and
     *        <code>bottom</code> fields indicate the width of the
     *        border at the respective edge.
     *
     * @return the same object that was passed for <code>insets</code>.
     *
     * @see #getBorderInsets(Component)
     */
    public Insets getBorderInsets(Component c, Insets insets)
    {
      /* The exact amount has been determined using a test program
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2].
       */
      if (insets == null)
        return new Insets(2, 2, 2, 2);

      insets.left = insets.right = insets.top = insets.bottom = 2;
      return insets;
    }
  }

}
