/* BasicSplitPaneDivider.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.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import javax.swing.border.Border;

/**
 * The divider that separates the two parts of a JSplitPane in the Basic look
 * and feel.
 *
 * <p>
 * Implementation status: We do not have a real implementation yet. Currently,
 * it is mostly a stub to allow compiling other parts of the
 * javax.swing.plaf.basic package, although some parts are already
 * functional.
 * </p>
 *
 * @author Sascha Brawer (brawer_AT_dandelis.ch)
 */
public class BasicSplitPaneDivider extends Container
  implements PropertyChangeListener
{
  /**
   * The buttons used as one touch buttons.
   */
  private class BasicOneTouchButton
    extends JButton
  {
    /**
     * Denotes a left button.
     */
    static final int LEFT = 0;

    /**
     * Denotes a right button.
     */
    static final int RIGHT = 1;

    /**
     * The x points for the arrow.
     */
    private int[] xpoints;

    /**
     * The y points for the arrow.
     */
    private int[] ypoints;

    /**
     * Either LEFT or RIGHT.
     */
    private int direction;

    /**
     * Creates a new instance.
     *
     * @param dir either LEFT or RIGHT
     */
    BasicOneTouchButton(int dir)
    {
      direction = dir;
      xpoints = new int[3];
      ypoints = new int[3];
    }

    /**
     * Never allow borders.
     */
    public void setBorder(Border b)
    {
    }

    /**
     * Never allow focus traversal.
     */
    public boolean isFocusTraversable()
    {
      return false;
    }

    /**
     * Paints the one touch button.
     */
    public void paint(Graphics g)
    {
      if (splitPane != null)
        {
          // Fill background.
          g.setColor(splitPane.getBackground());
          g.fillRect(0, 0, getWidth(), getHeight());

          // Draw arrow.
          int size;
          if (direction == LEFT)
            {
              if (orientation == JSplitPane.VERTICAL_SPLIT)
                {
                  size = Math.min(getHeight(), ONE_TOUCH_SIZE);
                  xpoints[0] = 0;
                  xpoints[1] = size / 2;
                  xpoints[2] = size;
                  ypoints[0] = size;
                  ypoints[1] = 0;
                  ypoints[2] = size;
                }
              else
                {
                  size = Math.min(getWidth(), ONE_TOUCH_SIZE);
                  xpoints[0] = size;
                  xpoints[1] = 0;
                  xpoints[2] = size;
                  ypoints[0] = 0;
                  ypoints[1] = size / 2;
                  ypoints[2] = size;
                }
            }
          else
            {
              if (orientation == JSplitPane.VERTICAL_SPLIT)
                {
                  size = Math.min(getHeight(), ONE_TOUCH_SIZE);
                  xpoints[0] = 0;
                  xpoints[1] = size / 2;
                  xpoints[2] = size;
                  ypoints[0] = 0;
                  ypoints[1] = size;
                  ypoints[2] = 0;
                }
              else
                {
                  size = Math.min(getWidth(), ONE_TOUCH_SIZE);
                  xpoints[0] = 0;
                  xpoints[1] = size;
                  xpoints[2] = 0;
                  ypoints[0] = 0;
                  ypoints[1] = size / 2;
                  ypoints[2] = size;
                }
            }
          g.setColor(Color.BLACK);
          g.fillPolygon(xpoints, ypoints, 3);
        }
    }
  }

  /**
   * Listens for actions on the one touch buttons.
   */
  private class OneTouchAction
    implements ActionListener
  {

    public void actionPerformed(ActionEvent ev)
    {
      Insets insets = splitPane.getInsets();
      int lastLoc = splitPane.getLastDividerLocation();
      int currentLoc = splitPaneUI.getDividerLocation(splitPane);
      int newLoc;

      if (ev.getSource() == leftButton)
        {
          if (orientation == JSplitPane.VERTICAL_SPLIT)
            {
              if (currentLoc
                  >= splitPane.getHeight() - insets.bottom - getHeight())
                {
                  newLoc = Math.min(splitPane.getMaximumDividerLocation(),
                                    lastLoc);
                }
              else
                {
                  newLoc = insets.top;
                }
            }
          else
            {
              if (currentLoc
                  >= splitPane.getWidth() - insets.right - getWidth())
                {
                  newLoc = Math.min(splitPane.getMaximumDividerLocation(),
                                    lastLoc);
                }
              else
                {
                  newLoc = insets.left;
                }
            }
        }
      else
        {
          if (orientation == JSplitPane.VERTICAL_SPLIT)
            {
              if (currentLoc == insets.top)
                {
                  newLoc = Math.min(splitPane.getMaximumDividerLocation(),
                                    lastLoc);
                }
              else
                {
                  newLoc = splitPane.getHeight() - insets.top - getHeight();
                }
            }
          else
            {
              if (currentLoc == insets.left)
                {
                  newLoc = Math.min(splitPane.getMaximumDividerLocation(),
                                    lastLoc);
                }
              else
                {
                  newLoc = splitPane.getWidth() - insets.left - getWidth();
                }
            }
        }
      if (currentLoc != newLoc)
        {
          splitPane.setDividerLocation(newLoc);
          splitPane.setLastDividerLocation(currentLoc);
        }
    }
  }

  /**
   * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1
   * on MacOS X 10.1.5.
   */
  static final long serialVersionUID = 1463404307042803342L;

  /**
   * The width and height of the little buttons for showing and hiding parts
   * of a JSplitPane in a single mouse click.
   */
  protected static final int ONE_TOUCH_SIZE = 6;

  /** The distance the one touch buttons will sit from the divider's edges. */
  protected static final int ONE_TOUCH_OFFSET = 2;

  /**
   * An object that performs the tasks associated with an ongoing drag
   * operation, or <code>null</code> if the user is currently not dragging
   * the divider.
   */
  protected DragController dragger;

  /**
   * The delegate object that is responsible for the UI of the
   * <code>JSplitPane</code> that contains this divider.
   */
  protected BasicSplitPaneUI splitPaneUI;

  /** The thickness of the divider in pixels. */
  protected int dividerSize;

  /** A divider that is used for layout purposes. */
  protected Component hiddenDivider;

  /** The JSplitPane containing this divider. */
  protected JSplitPane splitPane;

  /**
   * The listener for handling mouse events from both the divider and the
   * containing <code>JSplitPane</code>.
   *
   * <p>
   * The reason for also handling MouseEvents from the containing
   * <code>JSplitPane</code> is that users should be able to start a drag
   * gesture from inside the JSplitPane, but slightly outisde the divider.
   * </p>
   */
  protected MouseHandler mouseHandler = new MouseHandler();

  /**
   * The current orientation of the containing <code>JSplitPane</code>, which
   * is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or {@link
   * javax.swing.JSplitPane#VERTICAL_SPLIT}.
   */
  protected int orientation;

  /**
   * The button for showing and hiding the left (or top) component of the
   * <code>JSplitPane</code>.
   */
  protected JButton leftButton;

  /**
   * The button for showing and hiding the right (or bottom) component of the
   * <code>JSplitPane</code>.
   */
  protected JButton rightButton;

  /**
   * The border of this divider. Typically, this will be an instance of {@link
   * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}.
   *
   * @see #getBorder()
   * @see #setBorder(javax.swing.border.Border)
   */
  private Border border;

  // This is not a pixel count.
  // This int should be able to take 3 values.
  // left (top), middle, right(bottom)
  //    0          1          2

  /**
   * Keeps track of where the divider should be placed when using one touch
   * expand buttons.
   * This is package-private to avoid an accessor method.
   */
  transient int currentDividerLocation = 1;

  /**
   * Indicates if the ont touch buttons are laid out centered or at the
   * top/left.
   *
   * Package private to avoid accessor method.
   */
  boolean centerOneTouchButtons;

  /**
   * Constructs a new divider.
   *
   * @param ui the UI delegate of the enclosing <code>JSplitPane</code>.
   */
  public BasicSplitPaneDivider(BasicSplitPaneUI ui)
  {
    setLayout(new DividerLayout());
    setBasicSplitPaneUI(ui);
    setDividerSize(splitPane.getDividerSize());
    centerOneTouchButtons =
      UIManager.getBoolean("SplitPane.centerOneTouchButtons");
  }

  /**
   * Sets the delegate object that is responsible for the UI of the {@link
   * javax.swing.JSplitPane} containing this divider.
   *
   * @param newUI the UI delegate, or <code>null</code> to release the
   *        connection to the current delegate.
   */
  public void setBasicSplitPaneUI(BasicSplitPaneUI newUI)
  {
    /* Remove the connection to the existing JSplitPane. */
    if (splitPane != null)
      {
        splitPane.removePropertyChangeListener(this);
        removeMouseListener(mouseHandler);
        removeMouseMotionListener(mouseHandler);
        splitPane = null;
        hiddenDivider = null;
      }

    /* Establish the connection to the new JSplitPane. */
    splitPaneUI = newUI;
    if (splitPaneUI != null)
      splitPane = newUI.getSplitPane();
    if (splitPane != null)
      {
        splitPane.addPropertyChangeListener(this);
        addMouseListener(mouseHandler);
        addMouseMotionListener(mouseHandler);
        hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider();
        orientation = splitPane.getOrientation();
        if (splitPane.isOneTouchExpandable())
          oneTouchExpandableChanged();
      }
  }

  /**
   * Returns the delegate object that is responsible for the UI of the {@link
   * javax.swing.JSplitPane} containing this divider.
   *
   * @return The UI for the JSplitPane.
   */
  public BasicSplitPaneUI getBasicSplitPaneUI()
  {
    return splitPaneUI;
  }

  /**
   * Sets the thickness of the divider.
   *
   * @param newSize the new width or height in pixels.
   */
  public void setDividerSize(int newSize)
  {
    this.dividerSize = newSize;
  }

  /**
   * Retrieves the thickness of the divider.
   *
   * @return The thickness of the divider.
   */
  public int getDividerSize()
  {
    return dividerSize;
  }

  /**
   * Sets the border of this divider.
   *
   * @param border the new border. Typically, this will be an instance of
   *        {@link
   *        javax.swing.plaf.basic.BasicBorders.SplitPaneBorder}.
   *
   * @since 1.3
   */
  public void setBorder(Border border)
  {
    if (border != this.border)
      {
        Border oldValue = this.border;
        this.border = border;
        firePropertyChange("border", oldValue, border);
      }
  }

  /**
   * Retrieves the border of this divider.
   *
   * @return the current border, or <code>null</code> if no border has been
   *         set.
   *
   * @since 1.3
   */
  public Border getBorder()
  {
    return border;
  }

  /**
   * Retrieves the insets of the divider. If a border has been installed on
   * the divider, the result of calling its <code>getBorderInsets</code>
   * method is returned. Otherwise, the inherited implementation will be
   * invoked.
   *
   * @see javax.swing.border.Border#getBorderInsets(java.awt.Component)
   */
  public Insets getInsets()
  {
    if (border != null)
      return border.getBorderInsets(this);
    else
      return super.getInsets();
  }

  /**
   * Returns the preferred size of this divider, which is
   * <code>dividerSize</code> by <code>dividerSize</code> pixels.
   *
   * @return The preferred size of the divider.
   */
  public Dimension getPreferredSize()
  {
    Dimension d;
    if (orientation == JSplitPane.HORIZONTAL_SPLIT)
      d = new Dimension(getDividerSize(), 1);
    else
      d = new Dimension(1, getDividerSize());
    return d;
  }

  /**
   * Returns the minimal size of this divider, which is
   * <code>dividerSize</code> by <code>dividerSize</code> pixels.
   *
   * @return The minimal size of the divider.
   */
  public Dimension getMinimumSize()
  {
    return getPreferredSize();
  }

  /**
   * Processes events from the <code>JSplitPane</code> that contains this
   * divider.
   *
   * @param e The PropertyChangeEvent.
   */
  public void propertyChange(PropertyChangeEvent e)
  {
    if (e.getPropertyName().equals(JSplitPane.ONE_TOUCH_EXPANDABLE_PROPERTY))
      oneTouchExpandableChanged();
    else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY))
      {
        orientation = splitPane.getOrientation();
        invalidate();
        if (splitPane != null)
          splitPane.revalidate();
      }
    else if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY))
      dividerSize = splitPane.getDividerSize();
  }

  /**
   * Paints the divider by painting its border.
   *
   * @param g The Graphics Object to paint with.
   */
  public void paint(Graphics g)
  {
    Dimension dividerSize;

    super.paint(g);
    if (border != null)
      {
        dividerSize = getSize();
        border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height);
      }
  }

  /**
   * Reacts to changes of the <code>oneToughExpandable</code> property of the
   * containing <code>JSplitPane</code>.
   */
  protected void oneTouchExpandableChanged()
  {
    if (splitPane.isOneTouchExpandable())
      {
        leftButton = createLeftOneTouchButton();
        if (leftButton != null)
          leftButton.addActionListener(new OneTouchAction());

        rightButton = createRightOneTouchButton();
        if (rightButton != null)
          rightButton.addActionListener(new OneTouchAction());

        // Only add them when both are non-null.
        if (leftButton != null && rightButton != null)
          {
            add(leftButton);
            add(rightButton);
          }
      }
    invalidate();
    if (splitPane != null)
      splitPane.revalidate();
  }

  /**
   * Creates a button for showing and hiding the left (or top) part of a
   * <code>JSplitPane</code>.
   *
   * @return The left one touch button.
   */
  protected JButton createLeftOneTouchButton()
  {
    JButton button = new BasicOneTouchButton(BasicOneTouchButton.LEFT);
    button.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
    button.setRequestFocusEnabled(false);
    return button;
  }

  /**
   * Creates a button for showing and hiding the right (or bottom) part of a
   * <code>JSplitPane</code>.
   *
   * @return The right one touch button.
   */
  protected JButton createRightOneTouchButton()
  {
    JButton button = new BasicOneTouchButton(BasicOneTouchButton.RIGHT);
    button.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
    button.setRequestFocusEnabled(false);
    return button;
  }

  /**
   * Prepares the divider for dragging by calling the
   * <code>startDragging</code> method of the UI delegate of the enclosing
   * <code>JSplitPane</code>.
   *
   * @see BasicSplitPaneUI#startDragging()
   */
  protected void prepareForDragging()
  {
    if (splitPaneUI != null)
      splitPaneUI.startDragging();
  }

  /**
   * Drags the divider to a given location by calling the
   * <code>dragDividerTo</code> method of the UI delegate of the enclosing
   * <code>JSplitPane</code>.
   *
   * @param location the new location of the divider.
   *
   * @see BasicSplitPaneUI#dragDividerTo(int location)
   */
  protected void dragDividerTo(int location)
  {
    if (splitPaneUI != null)
      splitPaneUI.dragDividerTo(location);
  }

  /**
   * Finishes a dragging gesture by calling the <code>finishDraggingTo</code>
   * method of the UI delegate of the enclosing <code>JSplitPane</code>.
   *
   * @param location the new, final location of the divider.
   *
   * @see BasicSplitPaneUI#finishDraggingTo(int location)
   */
  protected void finishDraggingTo(int location)
  {
    if (splitPaneUI != null)
      splitPaneUI.finishDraggingTo(location);
  }

  /**
   * This helper method moves the divider to one of the  three locations when
   * using one touch expand buttons. Location 0 is the left (or top) most
   * location. Location 1 is the middle. Location 2 is the right (or bottom)
   * most location.
   * This is package-private to avoid an accessor method.
   *
   * @param locationIndex The location to move to.
   */
  void moveDividerTo(int locationIndex)
  {
    Insets insets = splitPane.getInsets();
    switch (locationIndex)
      {
      case 1:
        splitPane.setDividerLocation(splitPane.getLastDividerLocation());
        break;
      case 0:
        int top = (orientation == JSplitPane.HORIZONTAL_SPLIT) ? insets.left
                                                               : insets.top;
        splitPane.setDividerLocation(top);
        break;
      case 2:
        int bottom;
        if (orientation == JSplitPane.HORIZONTAL_SPLIT)
          bottom = splitPane.getBounds().width - insets.right - dividerSize;
        else
          bottom = splitPane.getBounds().height - insets.bottom - dividerSize;
        splitPane.setDividerLocation(bottom);
        break;
      }
  }

  /**
   * The listener for handling mouse events from both the divider and the
   * containing <code>JSplitPane</code>.
   *
   * <p>
   * The reason for also handling MouseEvents from the containing
   * <code>JSplitPane</code> is that users should be able to start a drag
   * gesture from inside the JSplitPane, but slightly outisde the divider.
   * </p>
   *
   * @author Sascha Brawer (brawer_AT_dandelis.ch)
   */
  protected class MouseHandler extends MouseAdapter
    implements MouseMotionListener
  {
    /** Keeps track of whether a drag is occurring. */
    private transient boolean isDragging;

    /**
     * This method is called when the mouse is pressed.
     *
     * @param e The MouseEvent.
     */
    public void mousePressed(MouseEvent e)
    {
      isDragging = true;
      currentDividerLocation = 1;
      if (orientation == JSplitPane.HORIZONTAL_SPLIT)
        dragger = new DragController(e);
      else
        dragger = new VerticalDragController(e);
      prepareForDragging();
    }

    /**
     * This method is called when the mouse is released.
     *
     * @param e The MouseEvent.
     */
    public void mouseReleased(MouseEvent e)
    {
      if (isDragging)
        dragger.completeDrag(e);
      isDragging = false;
    }

    /**
     * Repeatedly invoked when the user is dragging the mouse cursor while
     * having pressed a mouse button.
     *
     * @param e The MouseEvent.
     */
    public void mouseDragged(MouseEvent e)
    {
      if (dragger != null)
        dragger.continueDrag(e);
    }

    /**
     * Repeatedly invoked when the user is dragging the mouse cursor without
     * having pressed a mouse button.
     *
     * @param e The MouseEvent.
     */
    public void mouseMoved(MouseEvent e)
    {
      // Do nothing.
    }
  }

  /**
   * Performs the tasks associated with an ongoing drag operation.
   *
   * @author Sascha Brawer (brawer_AT_dandelis.ch)
   */
  protected class DragController
  {
    /**
     * The difference between where the mouse is clicked and the  initial
     * divider location.
     */
    transient int offset;

    /**
     * Creates a new DragController object.
     *
     * @param e The MouseEvent to initialize with.
     */
    protected DragController(MouseEvent e)
    {
      offset = e.getX();
    }

    /**
     * This method returns true if the divider can move.
     *
     * @return True if dragging is allowed.
     */
    protected boolean isValid()
    {
      // Views can always be resized?
      return true;
    }

    /**
     * Returns a position for the divider given the MouseEvent.
     *
     * @param e MouseEvent.
     *
     * @return The position for the divider to move to.
     */
    protected int positionForMouseEvent(MouseEvent e)
    {
      return e.getX() + getX() - offset;
    }

    /**
     * This method returns one of the two paramters for the orientation. In
     * this case, it returns x.
     *
     * @param x The x coordinate.
     * @param y The y coordinate.
     *
     * @return The x coordinate.
     */
    protected int getNeededLocation(int x, int y)
    {
      return x;
    }

    /**
     * This method is called to pass on the drag information to the UI through
     * dragDividerTo.
     *
     * @param newX The x coordinate of the MouseEvent.
     * @param newY The y coordinate of the MouseEvent.
     */
    protected void continueDrag(int newX, int newY)
    {
      if (isValid())
        dragDividerTo(adjust(newX, newY));
    }

    /**
     * This method is called to pass on the drag information  to the UI
     * through dragDividerTo.
     *
     * @param e The MouseEvent.
     */
    protected void continueDrag(MouseEvent e)
    {
      if (isValid())
        dragDividerTo(positionForMouseEvent(e));
    }

    /**
     * This method is called to finish the drag session  by calling
     * finishDraggingTo.
     *
     * @param x The x coordinate of the MouseEvent.
     * @param y The y coordinate of the MouseEvent.
     */
    protected void completeDrag(int x, int y)
    {
      finishDraggingTo(adjust(x, y));
    }

    /**
     * This method is called to finish the drag session  by calling
     * finishDraggingTo.
     *
     * @param e The MouseEvent.
     */
    protected void completeDrag(MouseEvent e)
    {
      finishDraggingTo(positionForMouseEvent(e));
    }

    /**
     * This is a helper method that includes the offset in the needed
     * location.
     *
     * @param x The x coordinate of the MouseEvent.
     * @param y The y coordinate of the MouseEvent.
     *
     * @return The needed location adjusted by the offsets.
     */
    int adjust(int x, int y)
    {
      return getNeededLocation(x, y) + getX() - offset;
    }
  }

  /**
   * This is a helper class that controls dragging when  the orientation is
   * VERTICAL_SPLIT.
   */
  protected class VerticalDragController extends DragController
  {
    /**
     * Creates a new VerticalDragController object.
     *
     * @param e The MouseEvent to initialize with.
     */
    protected VerticalDragController(MouseEvent e)
    {
      super(e);
      offset = e.getY();
    }

    /**
     * This method returns one of the two parameters given the orientation. In
     * this case, it returns y.
     *
     * @param x The x coordinate of the MouseEvent.
     * @param y The y coordinate of the MouseEvent.
     *
     * @return The y coordinate.
     */
    protected int getNeededLocation(int x, int y)
    {
      return y;
    }

    /**
     * This method returns the new location of the divider given a MouseEvent.
     *
     * @param e The MouseEvent.
     *
     * @return The new location of the divider.
     */
    protected int positionForMouseEvent(MouseEvent e)
    {
      return e.getY() + getY() - offset;
    }

    /**
     * This is a helper method that includes the offset in the needed
     * location.
     *
     * @param x The x coordinate of the MouseEvent.
     * @param y The y coordinate of the MouseEvent.
     *
     * @return The needed location adjusted by the offsets.
     */
    int adjust(int x, int y)
    {
      return getNeededLocation(x, y) + getY() - offset;
    }
  }

  /**
   * This helper class acts as the Layout Manager for the divider.
   */
  protected class DividerLayout implements LayoutManager
  {
    /**
     * Creates a new DividerLayout object.
     */
    protected DividerLayout()
    {
      // Nothing to do here.
    }

    /**
     * This method is called when a Component is added.
     *
     * @param string The constraints string.
     * @param c The Component to add.
     */
    public void addLayoutComponent(String string, Component c)
    {
      // Do nothing.
    }

    /**
     * This method is called to lay out the container.
     *
     * @param c The container to lay out.
     */
    public void layoutContainer(Container c)
    {
      if (leftButton != null && rightButton != null
          && c == BasicSplitPaneDivider.this)
        {
          if (splitPane.isOneTouchExpandable())
            {
              Insets insets = getInsets();
              if (orientation == JSplitPane.HORIZONTAL_SPLIT)
                {
                  int size = getWidth() - insets.left - insets.right;
                  size = Math.max(size, 0);
                  size = Math.min(size, ONE_TOUCH_SIZE);
                  int x, y;
                  if (centerOneTouchButtons)
                    {
                      y = insets.top;
                      x = (getWidth() - size) / 2;
                    }
                  else
                    {
                      x = insets.left;
                      y = 0;
                    }

                  leftButton.setBounds(x, y + ONE_TOUCH_OFFSET, size,
                                       size * 2);
                  rightButton.setBounds(x, y + ONE_TOUCH_OFFSET
                                        + ONE_TOUCH_SIZE * 2, size, size * 2);
                }
              else
                {
                  int size = getHeight() - insets.top - insets.bottom;
                  size = Math.max(size, 0);
                  size = Math.min(size, ONE_TOUCH_SIZE);
                  int x, y;
                  if (centerOneTouchButtons)
                    {
                      x = insets.left;
                      y = (getHeight() - size) / 2;
                    }
                  else
                    {
                      x = 0;
                      y = insets.top;
                    }
                  leftButton.setBounds(x + ONE_TOUCH_OFFSET, y, size * 2,
                                       size);
                  rightButton.setBounds(x + ONE_TOUCH_OFFSET
                                        + ONE_TOUCH_SIZE * 2, y, size * 2,
                                        size);
                }
            }
          else
            {
              // The JDK sets this bounds for disabled one touch buttons, so
              // do we.
              leftButton.setBounds(-5, -5, 1, 1);
              rightButton.setBounds(-5, -5, 1, 1);
            }
        }
    }

    /**
     * This method returns the minimum layout size.
     *
     * @param c The container to calculate for.
     *
     * @return The minimum layout size.
     */
    public Dimension minimumLayoutSize(Container c)
    {
      return preferredLayoutSize(c);
    }

    /**
     * This method returns the preferred layout size.
     *
     * @param c The container to calculate for.
     *
     * @return The preferred layout size.
     */
    public Dimension preferredLayoutSize(Container c)
    {
      return new Dimension(dividerSize, dividerSize);
    }

    /**
     * This method is called when a component is removed.
     *
     * @param c The component to remove.
     */
    public void removeLayoutComponent(Component c)
    {
      // Do nothing.
    }

  }
}
