/* BasicToolBarUI.java --
   Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.BorderLayout;
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.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Hashtable;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JToolBar;
import javax.swing.RootPaneContainer;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.BorderUIResource.EtchedBorderUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ToolBarUI;
import javax.swing.plaf.UIResource;

/**
 * This is the Basic Look and Feel UI class for JToolBar.
 */
public class BasicToolBarUI extends ToolBarUI implements SwingConstants
{
  /** Static owner of all DragWindows. */
  private static JFrame owner = new JFrame();

  /** The border used when the JToolBar is in nonrollover mode. */
  private static Border nonRolloverBorder;

  /** The border used when the JToolBar is in rollover mode. */
  private static Border rolloverBorder;

  /** The last known BorderLayout constraint before floating. */
  protected String constraintBeforeFloating;

  /** The last known orientation of the JToolBar before floating. */
  private int lastGoodOrientation;

  /** The color of the border when it is dockable. */
  protected Color dockingBorderColor;

  /** The background color of the JToolBar when it is dockable. */
  protected Color dockingColor;

  /** The docking listener responsible for mouse events on the JToolBar. */
  protected MouseInputListener dockingListener;

  /** The window used for dragging the JToolBar. */
  protected BasicToolBarUI.DragWindow dragWindow;

  /** The color of the border when it is not dockable. */
  protected Color floatingBorderColor;

  /** The background color of the JToolBar when it is not dockable. */
  protected Color floatingColor;

  /** The index of the focused component. */
  protected int focusedCompIndex;

  /** The PropertyChangeListener for the JToolBar. */
  protected PropertyChangeListener propertyListener;

  /** The JToolBar this UI delegate is responsible for. */
  protected JToolBar toolBar;

  /** The Container listener for the JToolBar. */
  protected ContainerListener toolBarContListener;

  /** The Focus listener for the JToolBar. */
  protected FocusListener toolBarFocusListener;

  /**
   * The floating window that is responsible for holding the JToolBar when it
   * is dragged outside of its original parent.
   */
  private transient Window floatFrame;

  /** The original parent of the JToolBar. */
  private transient Container origParent;

  /** A hashtable of components and their original borders. */
  private transient Hashtable borders;

  /** A window listener for the floatable frame. */
  private transient WindowListener windowListener;

  /** A set of cached bounds of the JToolBar. */
  private transient Dimension cachedBounds;

  /** The cached orientation of the JToolBar. */
  private transient int cachedOrientation;

  /**
   * This method creates a new <code>BasicToolBarUI</code> object for the given JToolBar.
   */
  public BasicToolBarUI()
  {
    // Do nothing here.
  }

  /**
   * This method returns whether the JToolBar can dock at the given position.
   *
   * @param c The component to try to dock in.
   * @param p The position of the mouse cursor relative to the given
   *        component.
   *
   * @return Whether the JToolBar can dock.
   */
  public boolean canDock(Component c, Point p)
  {
    return areaOfClick(c, p) != -1;
  }

  /**
   * This helper method returns the position of the JToolBar if it can dock.
   *
   * @param c The component to try to dock in.
   * @param p The position of the mouse cursor relative to the given
   *        component.
   *
   * @return One of the SwingConstants directions or -1 if the JToolBar can't
   *         dock.
   */
  private int areaOfClick(Component c, Point p)
  {
    // Has to dock in immediate parent, not eventual root container.
    Rectangle pBounds = c.getBounds();

    // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last.
    Dimension d = toolBar.getSize();
    int limit = Math.min(d.width, d.height);

    // The order of checking is 1. top 2. bottom 3. left 4. right
    if (! pBounds.contains(p))
      return -1;

    if (p.y < limit)
      return SwingConstants.NORTH;

    if (p.y > (pBounds.height - limit))
      return SwingConstants.SOUTH;

    if (p.x < limit)
      return SwingConstants.WEST;

    if (p.x > (pBounds.width - limit))
      return SwingConstants.EAST;

    return -1;
  }

  /**
   * This method creates a new DockingListener for the JToolBar.
   *
   * @return A new DockingListener for the JToolBar.
   */
  protected MouseInputListener createDockingListener()
  {
    return new DockingListener(toolBar);
  }

  /**
   * This method creates a new DragWindow for the given JToolBar.
   *
   * @param toolbar The JToolBar to create a DragWindow for.
   *
   * @return A new DragWindow.
   */
  protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar)
  {
    return new DragWindow();
  }

  /**
   * This method creates a new floating frame for the JToolBar. By default,
   * this UI uses createFloatingWindow instead. This method of creating a
   * floating frame is deprecated.
   *
   * @param toolbar The JToolBar to create a floating frame for.
   *
   * @return A new floating frame.
   */
  protected JFrame createFloatingFrame(JToolBar toolbar)
  {
    // FIXME: Though deprecated, this should still work.
    return null;
  }

  /**
   * This method creates a new floating window for the JToolBar. This is the
   * method used by default to create a floating container for the JToolBar.
   *
   * @param toolbar The JToolBar to create a floating window for.
   *
   * @return A new floating window.
   */
  protected RootPaneContainer createFloatingWindow(JToolBar toolbar)
  {
    // This one is used by default though.
    return new ToolBarDialog();
  }

  /**
   * This method creates a new WindowListener for the JToolBar.
   *
   * @return A new WindowListener.
   */
  protected WindowListener createFrameListener()
  {
    return new FrameListener();
  }

  /**
   * This method creates a new nonRolloverBorder for JButtons when the
   * JToolBar's rollover property is set to false.
   *
   * @return A new NonRolloverBorder.
   */
  protected Border createNonRolloverBorder()
  {
    return new EtchedBorderUIResource();
  }

  /**
   * This method creates a new PropertyChangeListener for the JToolBar.
   *
   * @return A new PropertyChangeListener.
   */
  protected PropertyChangeListener createPropertyListener()
  {
    return new PropertyListener();
  }

  /**
   * This method creates a new rollover border for JButtons when the
   * JToolBar's rollover property is set to true.
   *
   * @return A new rollover border.
   */
  protected Border createRolloverBorder()
  {
    return new EtchedBorderUIResource()
      {
	public void paintBorder(Component c, Graphics g, int x, int y,
	                        int width, int height)
	{
	  if (c instanceof JButton)
	    {
	      if (((JButton) c).getModel().isRollover())
		super.paintBorder(c, g, x, y, width, height);
	    }
	}
      };
  }

  /**
   * This method creates a new Container listener for the JToolBar.
   *
   * @return A new Container listener.
   */
  protected ContainerListener createToolBarContListener()
  {
    return new ToolBarContListener();
  }

  /**
   * This method creates a new FocusListener for the JToolBar.
   *
   * @return A new FocusListener for the JToolBar.
   */
  protected FocusListener createToolBarFocusListener()
  {
    return new ToolBarFocusListener();
  }

  /**
   * This method creates a new UI delegate for the given JComponent.
   *
   * @param c The JComponent to create a UI delegate for.
   *
   * @return A new UI delegate.
   */
  public static ComponentUI createUI(JComponent c)
  {
    return new BasicToolBarUI();
  }

  /**
   * This method is called to drag the DragWindow around when the JToolBar is
   * being dragged around.
   *
   * @param position The mouse cursor coordinates relative to the JToolBar.
   * @param origin The screen position of the JToolBar.
   */
  protected void dragTo(Point position, Point origin)
  {
    int loc = areaOfClick(origParent,
                          SwingUtilities.convertPoint(toolBar, position,
                                                      origParent));

    if (loc != -1)
      {
	dragWindow.setBorderColor(dockingBorderColor);
	dragWindow.setBackground(dockingColor);
      }
    else
      {
	dragWindow.setBorderColor(floatingBorderColor);
	dragWindow.setBackground(floatingColor);
      }

    int w = 0;
    int h = 0;

    boolean tmp = ((loc == SwingConstants.NORTH)
                  || (loc == SwingConstants.SOUTH) || (loc == -1));

    if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp)
        || ((cachedOrientation == VERTICAL) && ! tmp))
      {
	w = cachedBounds.width;
	h = cachedBounds.height;
      }
    else
      {
	w = cachedBounds.height;
	h = cachedBounds.width;
      }

    Point p = dragWindow.getOffset();
    Insets insets = toolBar.getInsets();

    dragWindow.setBounds((origin.x + position.x) - p.x
                         - ((insets.left + insets.right) / 2),
                         (origin.y + position.y) - p.y
                         - ((insets.top + insets.bottom) / 2), w, h);

    if (! dragWindow.isVisible())
      dragWindow.show();
  }

  /**
   * This method is used at the end of a drag session to place the frame in
   * either its original parent as a docked JToolBar or in its floating
   * frame.
   *
   * @param position The position of the mouse cursor relative to the
   *        JToolBar.
   * @param origin The screen position of the JToolBar before the drag session
   *        started.
   */
  protected void floatAt(Point position, Point origin)
  {
    Point p = new Point(position);
    int aoc = areaOfClick(origParent,
                          SwingUtilities.convertPoint(toolBar, p, origParent));

    Container oldParent = toolBar.getParent();

    oldParent.remove(toolBar);
    oldParent.doLayout();
    oldParent.repaint();

    Container newParent;

    if (aoc == -1)
      newParent = ((RootPaneContainer) floatFrame).getContentPane();
    else
      {
	floatFrame.hide();
	newParent = origParent;
      }

    String constraint;
    switch (aoc)
      {
      case SwingConstants.EAST:
	constraint = BorderLayout.EAST;
	break;
      case SwingConstants.NORTH:
	constraint = BorderLayout.NORTH;
	break;
      case SwingConstants.SOUTH:
	constraint = BorderLayout.SOUTH;
	break;
      case SwingConstants.WEST:
	constraint = BorderLayout.WEST;
	break;
      default:
	constraint = BorderLayout.CENTER;
	break;
      }

    int newOrientation = SwingConstants.HORIZONTAL;
    if ((aoc != -1)
        && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST)))
      newOrientation = SwingConstants.VERTICAL;

    if (aoc != -1)
      {
	constraintBeforeFloating = constraint;
	lastGoodOrientation = newOrientation;
      }

    newParent.add(toolBar, constraint);

    setFloating(aoc == -1, null);
    toolBar.setOrientation(newOrientation);

    Insets insets = floatFrame.getInsets();
    Dimension dims = toolBar.getPreferredSize();
    p = dragWindow.getOffset();
    setFloatingLocation((position.x + origin.x) - p.x
                        - ((insets.left + insets.right) / 2),
                        (position.y + origin.y) - p.y
                        - ((insets.top + insets.bottom) / 2));

    if (aoc == -1)
      {
	floatFrame.pack();
	floatFrame.setSize(dims.width + insets.left + insets.right,
	                   dims.height + insets.top + insets.bottom);
	floatFrame.show();
      }

    newParent.invalidate();
    newParent.validate();
    newParent.repaint();
  }

  /**
   * This method returns the docking color.
   *
   * @return The docking color.
   */
  public Color getDockingColor()
  {
    return dockingColor;
  }

  /**
   * This method returns the Color which is displayed when over a floating
   * area.
   *
   * @return The color which is displayed when over a floating area.
   */
  public Color getFloatingColor()
  {
    return floatingColor;
  }

  /**
   * This method returns the maximum size of the given JComponent for this UI.
   *
   * @param c The JComponent to find the maximum size for.
   *
   * @return The maximum size for this UI.
   */
  public Dimension getMaximumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the minimum size of the given JComponent for this UI.
   *
   * @param c The JComponent to find a minimum size for.
   *
   * @return The minimum size for this UI.
   */
  public Dimension getMinimumSize(JComponent c)
  {
    return getPreferredSize(c);
  }

  /**
   * This method returns the preferred size of the given JComponent for this
   * UI.
   *
   * @param c The JComponent to find a preferred size for.
   *
   * @return The preferred size for this UI.
   */
  public Dimension getPreferredSize(JComponent c)
  {
    return toolBar.getLayout().preferredLayoutSize(c);
  }

  /**
   * This method installs the needed components for the JToolBar.
   */
  protected void installComponents()
  {
    floatFrame = (Window) createFloatingWindow(toolBar);

    dragWindow = createDragWindow(toolBar);

    cachedBounds = toolBar.getPreferredSize();
    cachedOrientation = toolBar.getOrientation();

    nonRolloverBorder = createNonRolloverBorder();
    rolloverBorder = createRolloverBorder();

    borders = new Hashtable();

    fillHashtable();
  }

  /**
   * This method installs the defaults as specified by the look and feel.
   */
  protected void installDefaults()
  {
    UIDefaults defaults = UIManager.getLookAndFeelDefaults();

    toolBar.setBorder(new ToolBarBorder());
    toolBar.setBackground(defaults.getColor("ToolBar.background"));
    toolBar.setForeground(defaults.getColor("ToolBar.foreground"));
    toolBar.setFont(defaults.getFont("ToolBar.font"));

    dockingBorderColor = defaults.getColor("ToolBar.dockingForeground");
    dockingColor = defaults.getColor("ToolBar.dockingBackground");

    floatingBorderColor = defaults.getColor("ToolBar.floatingForeground");
    floatingColor = defaults.getColor("ToolBar.floatingBackground");
  }

  /**
   * This method installs the keyboard actions for the JToolBar as specified
   * by the look and feel.
   */
  protected void installKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method installs listeners for the JToolBar.
   *
   * @param toolbar The JToolBar to register listeners for.
   */
  protected void installListeners(JToolBar toolbar)
  {
    dockingListener = createDockingListener();
    toolBar.addMouseListener(dockingListener);
    toolBar.addMouseMotionListener(dockingListener);

    propertyListener = createPropertyListener();
    toolBar.addPropertyChangeListener(propertyListener);

    toolBarContListener = createToolBarContListener();
    toolBar.addContainerListener(toolBarContListener);

    windowListener = createFrameListener();
    floatFrame.addWindowListener(windowListener);

    toolBarFocusListener = createToolBarFocusListener();
    toolBar.addFocusListener(toolBarFocusListener);
  }

  /**
   * This method installs non rollover borders for each component inside the
   * given JComponent.
   *
   * @param c The JComponent whose children need to have non rollover borders
   *        installed.
   */
  protected void installNonRolloverBorders(JComponent c)
  {
    Component[] components = toolBar.getComponents();

    for (int i = 0; i < components.length; i++)
      setBorderToNonRollover(components[i]);
  }

  /**
   * This method installs normal (or their original) borders for each
   * component inside the given JComponent.
   *
   * @param c The JComponent whose children need to have their original
   *        borders installed.
   */
  protected void installNormalBorders(JComponent c)
  {
    Component[] components = toolBar.getComponents();

    for (int i = 0; i < components.length; i++)
      setBorderToNormal(components[i]);
  }

  /**
   * This method install rollover borders for each component inside the given
   * JComponent.
   *
   * @param c The JComponent whose children need to have rollover borders
   *        installed.
   */
  protected void installRolloverBorders(JComponent c)
  {
    Component[] components = toolBar.getComponents();

    for (int i = 0; i < components.length; i++)
      setBorderToRollover(components[i]);
  }

  /**
   * This method fills the borders hashtable with a list of components that
   * are JButtons and their borders.
   */
  private void fillHashtable()
  {
    Component[] c = toolBar.getComponents();

    for (int i = 0; i < c.length; i++)
      {
	if (c[i] instanceof JButton)
	  {
	    // Don't really care about anything other than JButtons
	    JButton b = (JButton) c[i];

	    if (b.getBorder() != null)
	      borders.put(b, b.getBorder());
	  }
      }
  }

  /**
   * This method installs the UI for the given JComponent.
   *
   * @param c The JComponent to install a UI for.
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);

    if (c instanceof JToolBar)
      {
	toolBar = (JToolBar) c;
	toolBar.setOpaque(true);
	installDefaults();
	installComponents();
	installListeners(toolBar);
	installKeyboardActions();
      }
  }

  /**
   * This method returns whether the JToolBar is floating.
   *
   * @return Whether the JToolBar is floating.
   */
  public boolean isFloating()
  {
    return floatFrame.isVisible();
  }

  /**
   * This method returns whether rollover borders have been set.
   *
   * @return Whether rollover borders have been set.
   */
  public boolean isRolloverBorders()
  {
    return toolBar.isRollover();
  }

  /**
   * This method navigates in the given direction giving focus to the next
   * component in the given direction.
   *
   * @param direction The direction to give focus to.
   */
  protected void navigateFocusedComp(int direction)
  {
    // FIXME: Implement.
  }

  /**
   * This method sets the border of the given component to a non rollover
   * border.
   *
   * @param c The Component whose border needs to be set.
   */
  protected void setBorderToNonRollover(Component c)
  {
    if (c instanceof JButton)
      {
	JButton b = (JButton) c;
	b.setRolloverEnabled(false);
	b.setBorder(nonRolloverBorder);
      }
  }

  /**
   * This method sets the border of the given component to its original value.
   *
   * @param c The Component whose border needs to be set.
   */
  protected void setBorderToNormal(Component c)
  {
    if (c instanceof JButton)
      {
	JButton b = (JButton) c;
	Border border = (Border) borders.get(b);
	b.setBorder(border);
      }
  }

  /**
   * This method sets the border of the given component to a rollover border.
   *
   * @param c The Component whose border needs to be set.
   */
  protected void setBorderToRollover(Component c)
  {
    if (c instanceof JButton)
      {
	JButton b = (JButton) c;
	b.setRolloverEnabled(true);
	b.setBorder(rolloverBorder);
      }
  }

  /**
   * This method sets the docking color.
   *
   * @param c The docking color.
   */
  public void setDockingColor(Color c)
  {
    dockingColor = c;
  }

  /**
   * This method sets the floating property for the JToolBar.
   *
   * @param b Whether the JToolBar is floating.
   * @param p FIXME
   */
  public void setFloating(boolean b, Point p)
  {
    // FIXME: use p for something. It's not location
    // since we already have setFloatingLocation.
    floatFrame.setVisible(b);
  }

  /**
   * This method sets the color displayed when the JToolBar is not in a
   * dockable area.
   *
   * @param c The floating color.
   */
  public void setFloatingColor(Color c)
  {
    floatingColor = c;
  }

  /**
   * This method sets the floating location of the JToolBar.
   *
   * @param x The x coordinate for the floating frame.
   * @param y The y coordinate for the floating frame.
   */
  public void setFloatingLocation(int x, int y)
  {
    // x,y are the coordinates of the new JFrame created to store the toolbar
    // XXX: The floating location is bogus is not floating.
    floatFrame.setLocation(x, y);
    floatFrame.invalidate();
    floatFrame.validate();
    floatFrame.repaint();
  }

  /**
   * This is a convenience method for changing the orientation of the
   * JToolBar.
   *
   * @param orientation The new orientation.
   */
  public void setOrientation(int orientation)
  {
    toolBar.setOrientation(orientation);
  }

  /**
   * This method changes the child components to have rollover borders if the
   * given parameter is true. Otherwise, the components are set to have non
   * rollover borders.
   *
   * @param rollover Whether the children will have rollover borders.
   */
  public void setRolloverBorders(boolean rollover)
  {
    if (rollover)
      installRolloverBorders(toolBar);
    else
      installNonRolloverBorders(toolBar);
  }

  /**
   * This method uninstall UI installed components from the JToolBar.
   */
  protected void uninstallComponents()
  {
    installNormalBorders(toolBar);
    borders = null;
    rolloverBorder = null;
    nonRolloverBorder = null;
    cachedBounds = null;

    floatFrame = null;
    dragWindow = null;
  }

  /**
   * This method removes the defaults installed by the Look and Feel.
   */
  protected void uninstallDefaults()
  {
    toolBar.setBackground(null);
    toolBar.setForeground(null);
    toolBar.setFont(null);

    dockingBorderColor = null;
    dockingColor = null;
    floatingBorderColor = null;
    floatingColor = null;
  }

  /**
   * This method uninstalls keyboard actions installed by the UI.
   */
  protected void uninstallKeyboardActions()
  {
    // FIXME: implement.
  }

  /**
   * This method uninstalls listeners installed by the UI.
   */
  protected void uninstallListeners()
  {
    toolBar.removeFocusListener(toolBarFocusListener);
    toolBarFocusListener = null;

    floatFrame.removeWindowListener(windowListener);
    windowListener = null;

    toolBar.removeContainerListener(toolBarContListener);
    toolBarContListener = null;

    toolBar.removeMouseMotionListener(dockingListener);
    toolBar.removeMouseListener(dockingListener);
    dockingListener = null;
  }

  /**
   * This method uninstalls the UI.
   *
   * @param c The JComponent that is having this UI removed.
   */
  public void uninstallUI(JComponent c)
  {
    uninstallKeyboardActions();
    uninstallListeners();
    uninstallComponents();
    uninstallDefaults();
    toolBar = null;
  }

  /**
   * This is the MouseHandler class that allows the user to drag the JToolBar
   * in and out of the parent and dock it if it can.
   */
  public class DockingListener implements MouseInputListener
  {
    /** Whether the JToolBar is being dragged. */
    protected boolean isDragging;

    /**
     * The origin point. This point is saved from the beginning press and is
     * used until the end of the drag session.
     */
    protected Point origin;

    /** The JToolBar being dragged. */
    protected JToolBar toolBar;

    /**
     * Creates a new DockingListener object.
     *
     * @param t The JToolBar this DockingListener is being used for.
     */
    public DockingListener(JToolBar t)
    {
      toolBar = t;
    }

    /**
     * This method is called when the mouse is clicked.
     *
     * @param e The MouseEvent.
     */
    public void mouseClicked(MouseEvent e)
    {
      // Don't care.
    }

    /**
     * This method is called when the mouse is dragged. It delegates the drag
     * painting to the dragTo method.
     *
     * @param e The MouseEvent.
     */
    public void mouseDragged(MouseEvent e)
    {
      if (isDragging)
	dragTo(e.getPoint(), origin);
    }

    /**
     * This method is called when the mouse enters the JToolBar.
     *
     * @param e The MouseEvent.
     */
    public void mouseEntered(MouseEvent e)
    {
      // Don't care (yet).
    }

    /**
     * This method is called when the mouse exits the JToolBar.
     *
     * @param e The MouseEvent.
     */
    public void mouseExited(MouseEvent e)
    {
      // Don't care (yet).
    }

    /**
     * This method is called when the mouse is moved in the JToolBar.
     *
     * @param e The MouseEvent.
     */
    public void mouseMoved(MouseEvent e)
    {
    }

    /**
     * This method is called when the mouse is pressed in the JToolBar. If the
     * press doesn't occur in a place where it causes the JToolBar to be
     * dragged, it returns. Otherwise, it starts a drag session.
     *
     * @param e The MouseEvent.
     */
    public void mousePressed(MouseEvent e)
    {
      if (! toolBar.isFloatable())
	return;

      Point ssd = e.getPoint();
      Insets insets = toolBar.getInsets();

      // Verify that this click occurs in the top inset.
      if (toolBar.getOrientation() == SwingConstants.HORIZONTAL)
        {
	  if (e.getX() > insets.left)
	    return;
        }
      else
        {
	  if (e.getY() > insets.top)
	    return;
        }

      origin = new Point(0, 0);
      SwingUtilities.convertPointToScreen(ssd, toolBar);

      if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource))
	// Need to know who keeps the toolBar if it gets dragged back into it.
	origParent = toolBar.getParent();

      SwingUtilities.convertPointToScreen(origin, toolBar);

      isDragging = true;

      if (dragWindow != null)
	dragWindow.setOffset(new Point(e.getX(), e.getY()));

      dragTo(e.getPoint(), origin);
    }

    /**
     * This method is called when the mouse is released from the JToolBar.
     *
     * @param e The MouseEvent.
     */
    public void mouseReleased(MouseEvent e)
    {
      if (! isDragging || ! toolBar.isFloatable())
	return;

      isDragging = false;
      floatAt(e.getPoint(), origin);
      dragWindow.hide();
    }
  }

  /**
   * This is the window that appears when the JToolBar is being dragged
   * around.
   */
  protected class DragWindow extends Window
  {
    /**
     * The current border color. It changes depending on whether the JToolBar
     * is over a place that allows it to dock.
     */
    private Color borderColor;

    /** The between the mouse and the top left corner of the window. */
    private Point offset;

    /**
     * Creates a new DragWindow object.
     */
    private DragWindow()
    {
      super(owner);
    }

    /**
     * The color that the border should be.
     *
     * @return The border color.
     */
    public Color getBorderColor()
    {
      if (borderColor == null)
	return Color.BLACK;

      return borderColor;
    }

    /**
     * This method returns the insets for the DragWindow.
     *
     * @return The insets for the DragWindow.
     */
    public Insets getInsets()
    {
      // This window has no decorations, so insets are empty.
      return new Insets(0, 0, 0, 0);
    }

    /**
     * This method returns the mouse offset from the top left corner of the
     * DragWindow.
     *
     * @return The mouse offset.
     */
    public Point getOffset()
    {
      return offset;
    }

    /**
     * This method paints the DragWindow.
     *
     * @param g The Graphics object to paint with.
     */
    public void paint(Graphics g)
    {
      //  No visiting children necessary.
      Color saved = g.getColor();
      Rectangle b = getBounds();

      g.setColor(getBorderColor());
      g.drawRect(0, 0, b.width - 1, b.height - 1);

      g.setColor(saved);
    }

    /**
     * This method changes the border color.
     *
     * @param c The new border color.
     */
    public void setBorderColor(Color c)
    {
      borderColor = c;
    }

    /**
     * This method changes the mouse offset.
     *
     * @param p The new mouse offset.
     */
    public void setOffset(Point p)
    {
      offset = p;
    }

    /**
     * FIXME: Do something.
     *
     * @param o DOCUMENT ME!
     */
    public void setOrientation(int o)
    {
      // FIXME: implement.
    }
  }

  /**
   * This helper class listens for Window events from the floatable window and
   * if it is closed, returns the JToolBar to the last known good location.
   */
  protected class FrameListener extends WindowAdapter
  {
    /**
     * This method is called when the floating window is closed.
     *
     * @param e The WindowEvent.
     */
    public void windowClosing(WindowEvent e)
    {
      Container parent = toolBar.getParent();
      parent.remove(toolBar);

      if (origParent != null)
        {
	  origParent.add(toolBar,
	                 (constraintBeforeFloating != null)
	                 ? constraintBeforeFloating : BorderLayout.NORTH);
	  toolBar.setOrientation(lastGoodOrientation);
        }

      origParent.invalidate();
      origParent.validate();
      origParent.repaint();
    }
  }

  /**
   * This helper class listens for PropertyChangeEvents from the JToolBar.
   */
  protected class PropertyListener implements PropertyChangeListener
  {
    /**
     * This method is called when a property from the JToolBar is changed.
     *
     * @param e The PropertyChangeEvent.
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      // FIXME: need name properties so can change floatFrame title.
      if (e.getPropertyName().equals("rollover"))
	setRolloverBorders(toolBar.isRollover());
    }
  }

  /**
   * This helper class listens for components added to and removed from the
   * JToolBar.
   */
  protected class ToolBarContListener implements ContainerListener
  {
    /**
     * This method is responsible for setting rollover or non rollover for new
     * buttons added to the JToolBar.
     *
     * @param e The ContainerEvent.
     */
    public void componentAdded(ContainerEvent e)
    {
      if (e.getChild() instanceof JButton)
        {
	  JButton b = (JButton) e.getChild();

	  if (b.getBorder() != null)
	    borders.put(b, b.getBorder());
        }

      if (isRolloverBorders())
	setBorderToRollover(e.getChild());
      else
	setBorderToNonRollover(e.getChild());

      cachedBounds = toolBar.getPreferredSize();
      cachedOrientation = toolBar.getOrientation();
    }

    /**
     * This method is responsible for giving the child components their
     * original borders when they are removed.
     *
     * @param e The ContainerEvent.
     */
    public void componentRemoved(ContainerEvent e)
    {
      setBorderToNormal(e.getChild());
      cachedBounds = toolBar.getPreferredSize();
      cachedOrientation = toolBar.getOrientation();
    }
  }

  /**
   * This is the floating window that is returned when getFloatingWindow is
   * called.
   */
  private class ToolBarDialog extends JDialog implements UIResource
  {
    /**
     * Creates a new ToolBarDialog object with the name given by the JToolBar.
     */
    public ToolBarDialog()
    {
      super();
      setName((toolBar.getName() != null) ? toolBar.getName() : "");
    }
  }

  /**
   * DOCUMENT ME!
   */
  protected class ToolBarFocusListener implements FocusListener
  {
    /**
     * Creates a new ToolBarFocusListener object.
     */
    protected ToolBarFocusListener()
    {
      // FIXME: implement.
    }

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void focusGained(FocusEvent e)
    {
      // FIXME: implement.
    }

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void focusLost(FocusEvent e)
    {
      // FIXME: implement.
    }
  }

  /**
   * This helper class acts as the border for the JToolBar.
   */
  private static class ToolBarBorder implements Border
  {
    /** The size of the larger, draggable side of the border. */
    private static final int offset = 10;

    /** The other sides. */
    private static final int regular = 2;

    /**
     * This method returns the border insets for the JToolBar.
     *
     * @param c The Component to find insets for.
     *
     * @return The border insets.
     */
    public Insets getBorderInsets(Component c)
    {
      if (c instanceof JToolBar)
        {
	  JToolBar tb = (JToolBar) c;
	  int orientation = tb.getOrientation();

	  if (! tb.isFloatable())
	    return new Insets(regular, regular, regular, regular);
	  else if (orientation == SwingConstants.HORIZONTAL)
	    return new Insets(regular, offset, regular, regular);
	  else
	    return new Insets(offset, regular, regular, regular);
        }

      return new Insets(0, 0, 0, 0);
    }

    /**
     * This method returns whether the border is opaque.
     *
     * @return Whether the border is opaque.
     */
    public boolean isBorderOpaque()
    {
      return false;
    }

    /**
     * This method paints the ribbed area of the border.
     *
     * @param g The Graphics object to paint with.
     * @param x The x coordinate of the area.
     * @param y The y coordinate of the area.
     * @param w The width of the area.
     * @param h The height of the area.
     * @param size The size of the bump.
     * @param c The color of the bumps.
     */
    private void paintBumps(Graphics g, int x, int y, int w, int h, int size,
                            Color c)
    {
      Color saved = g.getColor();
      g.setColor(c);

      int hgap = 2 * size;
      int vgap = 4 * size;
      int count = 0;

      for (int i = x; i < (w + x); i += hgap)
	for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y);
	     j += vgap)
	  g.fillRect(i, j, size, size);

      g.setColor(saved);
    }

    /**
     * This method paints the border around the given Component.
     *
     * @param c The Component whose border is being painted.
     * @param g The Graphics object to paint with.
     * @param x The x coordinate of the component.
     * @param y The y coordinate of the component.
     * @param width The width of the component.
     * @param height The height of the component.
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int width,
                            int height)
    {
      if (c instanceof JToolBar)
        {
	  JToolBar tb = (JToolBar) c;

	  int orientation = tb.getOrientation();

	  if (orientation == SwingConstants.HORIZONTAL)
	    {
	      paintBumps(g, x, y, offset, height, 1, Color.WHITE);
	      paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY);
	    }
	  else
	    {
	      paintBumps(g, x, y, width, offset, 1, Color.WHITE);
	      paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY);
	    }
        }
    }
  }
}
