Source for javax.swing.plaf.basic.BasicToolBarUI

   1: /* BasicToolBarUI.java --
   2:    Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.plaf.basic;
  40: 
  41: import java.awt.BorderLayout;
  42: import java.awt.Color;
  43: import java.awt.Component;
  44: import java.awt.Container;
  45: import java.awt.Dimension;
  46: import java.awt.Graphics;
  47: import java.awt.Insets;
  48: import java.awt.Point;
  49: import java.awt.Rectangle;
  50: import java.awt.Window;
  51: import java.awt.event.ActionEvent;
  52: import java.awt.event.ContainerEvent;
  53: import java.awt.event.ContainerListener;
  54: import java.awt.event.FocusEvent;
  55: import java.awt.event.FocusListener;
  56: import java.awt.event.MouseEvent;
  57: import java.awt.event.WindowAdapter;
  58: import java.awt.event.WindowEvent;
  59: import java.awt.event.WindowListener;
  60: import java.beans.PropertyChangeEvent;
  61: import java.beans.PropertyChangeListener;
  62: import java.util.Hashtable;
  63: 
  64: import javax.swing.AbstractAction;
  65: import javax.swing.AbstractButton;
  66: import javax.swing.Action;
  67: import javax.swing.ActionMap;
  68: import javax.swing.InputMap;
  69: import javax.swing.JButton;
  70: import javax.swing.JComponent;
  71: import javax.swing.JDialog;
  72: import javax.swing.JFrame;
  73: import javax.swing.JToolBar;
  74: import javax.swing.KeyStroke;
  75: import javax.swing.LookAndFeel;
  76: import javax.swing.RootPaneContainer;
  77: import javax.swing.SwingConstants;
  78: import javax.swing.SwingUtilities;
  79: import javax.swing.UIManager;
  80: import javax.swing.border.Border;
  81: import javax.swing.border.CompoundBorder;
  82: import javax.swing.event.MouseInputListener;
  83: import javax.swing.plaf.ActionMapUIResource;
  84: import javax.swing.plaf.ComponentUI;
  85: import javax.swing.plaf.ToolBarUI;
  86: import javax.swing.plaf.UIResource;
  87: import javax.swing.plaf.basic.BasicBorders.ButtonBorder;
  88: 
  89: /**
  90:  * This is the Basic Look and Feel UI class for JToolBar.
  91:  */
  92: public class BasicToolBarUI extends ToolBarUI implements SwingConstants
  93: {
  94: 
  95:   /**
  96:    * Implements the keyboard actions for JToolBar.
  97:    */
  98:   static class ToolBarAction
  99:     extends AbstractAction
 100:   {
 101:     /**
 102:      * Performs the action.
 103:      */
 104:     public void actionPerformed(ActionEvent event)
 105:     {
 106:       Object cmd = getValue("__command__");
 107:       JToolBar toolBar = (JToolBar) event.getSource();
 108:       BasicToolBarUI ui = (BasicToolBarUI) toolBar.getUI();
 109: 
 110:       if (cmd.equals("navigateRight"))
 111:         ui.navigateFocusedComp(EAST);
 112:       else if (cmd.equals("navigateLeft"))
 113:           ui.navigateFocusedComp(WEST);
 114:       else if (cmd.equals("navigateUp"))
 115:           ui.navigateFocusedComp(NORTH);
 116:       else if (cmd.equals("navigateDown"))
 117:         ui.navigateFocusedComp(SOUTH);
 118:       else
 119:         assert false : "Shouldn't reach here";
 120:     }
 121:   }
 122: 
 123:   /** Static owner of all DragWindows.
 124:    * This is package-private to avoid an accessor method.  */
 125:   static JFrame owner = new JFrame();
 126: 
 127:   /** The border used when the JToolBar is in nonrollover mode. */
 128:   private static Border nonRolloverBorder;
 129: 
 130:   /** The border used when the JToolBar is in rollover mode. */
 131:   private static Border rolloverBorder;
 132: 
 133:   /** The last known BorderLayout constraint before floating. */
 134:   protected String constraintBeforeFloating;
 135: 
 136:   /** The last known orientation of the JToolBar before floating.
 137:    * This is package-private to avoid an accessor method.  */
 138:   int lastGoodOrientation;
 139: 
 140:   /** The color of the border when it is dockable. */
 141:   protected Color dockingBorderColor;
 142: 
 143:   /** The background color of the JToolBar when it is dockable. */
 144:   protected Color dockingColor;
 145: 
 146:   /** The docking listener responsible for mouse events on the JToolBar. */
 147:   protected MouseInputListener dockingListener;
 148: 
 149:   /** The window used for dragging the JToolBar. */
 150:   protected BasicToolBarUI.DragWindow dragWindow;
 151: 
 152:   /** The color of the border when it is not dockable. */
 153:   protected Color floatingBorderColor;
 154: 
 155:   /** The background color of the JToolBar when it is not dockable. */
 156:   protected Color floatingColor;
 157: 
 158:   /** The index of the focused component. */
 159:   protected int focusedCompIndex;
 160: 
 161:   /** The PropertyChangeListener for the JToolBar. */
 162:   protected PropertyChangeListener propertyListener;
 163: 
 164:   /** The JToolBar this UI delegate is responsible for. */
 165:   protected JToolBar toolBar;
 166: 
 167:   /** The Container listener for the JToolBar. */
 168:   protected ContainerListener toolBarContListener;
 169: 
 170:   /** The Focus listener for the JToolBar. */
 171:   protected FocusListener toolBarFocusListener;
 172: 
 173:   /**
 174:    * @deprecated since JDK1.3.
 175:    */
 176:   protected KeyStroke leftKey;
 177: 
 178:   /**
 179:    * @deprecated since JDK1.3.
 180:    */
 181:   protected KeyStroke rightKey;
 182: 
 183:   /**
 184:    * @deprecated since JDK1.3.
 185:    */
 186:   protected KeyStroke upKey;
 187: 
 188:   /**
 189:    * @deprecated since JDK1.3.
 190:    */
 191:   protected KeyStroke downKey;
 192: 
 193:   /**
 194:    * The floating window that is responsible for holding the JToolBar when it
 195:    * is dragged outside of its original parent.
 196:    */
 197:   private transient Window floatFrame;
 198: 
 199:   /** The original parent of the JToolBar.
 200:    * This is package-private to avoid an accessor method.  */
 201:   transient Container origParent;
 202: 
 203:   /** A hashtable of components and their original borders.
 204:    * This is package-private to avoid an accessor method.  */
 205:   transient Hashtable borders;
 206: 
 207:   /** A window listener for the floatable frame. */
 208:   private transient WindowListener windowListener;
 209: 
 210:   /** A set of cached bounds of the JToolBar.
 211:    * This is package-private to avoid an accessor method.  */
 212:   transient Dimension cachedBounds;
 213: 
 214:   /** The cached orientation of the JToolBar.
 215:    * This is package-private to avoid an accessor method.  */
 216:   transient int cachedOrientation;
 217: 
 218:   /**
 219:    * This method creates a new <code>BasicToolBarUI</code> object for the given JToolBar.
 220:    */
 221:   public BasicToolBarUI()
 222:   {
 223:     // Do nothing here.
 224:   }
 225: 
 226:   /**
 227:    * This method returns whether the JToolBar can dock at the given position.
 228:    *
 229:    * @param c The component to try to dock in.
 230:    * @param p The position of the mouse cursor relative to the given
 231:    *        component.
 232:    *
 233:    * @return Whether the JToolBar can dock.
 234:    */
 235:   public boolean canDock(Component c, Point p)
 236:   {
 237:     return areaOfClick(c, p) != -1;
 238:   }
 239: 
 240:   /**
 241:    * This helper method returns the position of the JToolBar if it can dock.
 242:    *
 243:    * @param c The component to try to dock in.
 244:    * @param p The position of the mouse cursor relative to the given
 245:    *        component.
 246:    *
 247:    * @return One of the SwingConstants directions or -1 if the JToolBar can't
 248:    *         dock.
 249:    */
 250:   private int areaOfClick(Component c, Point p)
 251:   {
 252:     // Has to dock in immediate parent, not eventual root container.
 253:     Rectangle pBounds = c.getBounds();
 254: 
 255:     // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last.
 256:     Dimension d = toolBar.getSize();
 257:     int limit = Math.min(d.width, d.height);
 258: 
 259:     // The order of checking is 1. top 2. bottom 3. left 4. right
 260:     if (! pBounds.contains(p))
 261:       return -1;
 262: 
 263:     if (p.y < limit)
 264:       return SwingConstants.NORTH;
 265: 
 266:     if (p.y > (pBounds.height - limit))
 267:       return SwingConstants.SOUTH;
 268: 
 269:     if (p.x < limit)
 270:       return SwingConstants.WEST;
 271: 
 272:     if (p.x > (pBounds.width - limit))
 273:       return SwingConstants.EAST;
 274: 
 275:     return -1;
 276:   }
 277: 
 278:   /**
 279:    * This method creates a new DockingListener for the JToolBar.
 280:    *
 281:    * @return A new DockingListener for the JToolBar.
 282:    */
 283:   protected MouseInputListener createDockingListener()
 284:   {
 285:     return new DockingListener(toolBar);
 286:   }
 287: 
 288:   /**
 289:    * This method creates a new DragWindow for the given JToolBar.
 290:    *
 291:    * @param toolbar The JToolBar to create a DragWindow for.
 292:    *
 293:    * @return A new DragWindow.
 294:    */
 295:   protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar)
 296:   {
 297:     return new DragWindow();
 298:   }
 299: 
 300:   /**
 301:    * This method creates a new floating frame for the JToolBar. By default,
 302:    * this UI uses createFloatingWindow instead. This method of creating a
 303:    * floating frame is deprecated.
 304:    *
 305:    * @param toolbar The JToolBar to create a floating frame for.
 306:    *
 307:    * @return A new floating frame.
 308:    */
 309:   protected JFrame createFloatingFrame(JToolBar toolbar)
 310:   {
 311:     // FIXME: Though deprecated, this should still work.
 312:     return null;
 313:   }
 314: 
 315:   /**
 316:    * This method creates a new floating window for the JToolBar. This is the
 317:    * method used by default to create a floating container for the JToolBar.
 318:    *
 319:    * @param toolbar The JToolBar to create a floating window for.
 320:    *
 321:    * @return A new floating window.
 322:    */
 323:   protected RootPaneContainer createFloatingWindow(JToolBar toolbar)
 324:   {
 325:     // This one is used by default though.
 326:     return new ToolBarDialog();
 327:   }
 328: 
 329:   /**
 330:    * This method creates a new WindowListener for the JToolBar.
 331:    *
 332:    * @return A new WindowListener.
 333:    */
 334:   protected WindowListener createFrameListener()
 335:   {
 336:     return new FrameListener();
 337:   }
 338: 
 339:   /**
 340:    * This method creates a new nonRolloverBorder for JButtons when the
 341:    * JToolBar's rollover property is set to false.
 342:    *
 343:    * @return A new NonRolloverBorder.
 344:    */
 345:   protected Border createNonRolloverBorder()
 346:   {
 347:     Border b = UIManager.getBorder("ToolBar.nonrolloverBorder");
 348:     
 349:     if (b == null)
 350:       {
 351:         b = new CompoundBorder(
 352:             new ButtonBorder(UIManager.getColor("Button.shadow"),
 353:                              UIManager.getColor("Button.darkShadow"),
 354:                              UIManager.getColor("Button.light"),
 355:                              UIManager.getColor("Button.highlight")),
 356:             BasicBorders.getMarginBorder());
 357:       }
 358:     
 359:     return b;  }
 360: 
 361:   /**
 362:    * This method creates a new PropertyChangeListener for the JToolBar.
 363:    *
 364:    * @return A new PropertyChangeListener.
 365:    */
 366:   protected PropertyChangeListener createPropertyListener()
 367:   {
 368:     return new PropertyListener();
 369:   }
 370: 
 371:   /**
 372:    * This method creates a new rollover border for JButtons when the
 373:    * JToolBar's rollover property is set to true.
 374:    *
 375:    * @return A new rollover border.
 376:    */
 377:   protected Border createRolloverBorder()
 378:   {
 379:     Border b = UIManager.getBorder("ToolBar.rolloverBorder");
 380:     
 381:     if (b == null)
 382:       {
 383:         b = new CompoundBorder(
 384:             new ButtonBorder(UIManager.getColor("Button.shadow"),
 385:                              UIManager.getColor("Button.darkShadow"),
 386:                              UIManager.getColor("Button.light"),
 387:                              UIManager.getColor("Button.highlight")),
 388:             BasicBorders.getMarginBorder());
 389:       }
 390:     
 391:     return b;
 392:   }
 393: 
 394:   /**
 395:    * This method creates a new Container listener for the JToolBar.
 396:    *
 397:    * @return A new Container listener.
 398:    */
 399:   protected ContainerListener createToolBarContListener()
 400:   {
 401:     return new ToolBarContListener();
 402:   }
 403: 
 404:   /**
 405:    * This method creates a new FocusListener for the JToolBar.
 406:    *
 407:    * @return A new FocusListener for the JToolBar.
 408:    */
 409:   protected FocusListener createToolBarFocusListener()
 410:   {
 411:     return new ToolBarFocusListener();
 412:   }
 413: 
 414:   /**
 415:    * This method creates a new UI delegate for the given JComponent.
 416:    *
 417:    * @param c The JComponent to create a UI delegate for.
 418:    *
 419:    * @return A new UI delegate.
 420:    */
 421:   public static ComponentUI createUI(JComponent c)
 422:   {
 423:     return new BasicToolBarUI();
 424:   }
 425: 
 426:   /**
 427:    * This method is called to drag the DragWindow around when the JToolBar is
 428:    * being dragged around.
 429:    *
 430:    * @param position The mouse cursor coordinates relative to the JToolBar.
 431:    * @param origin The screen position of the JToolBar.
 432:    */
 433:   protected void dragTo(Point position, Point origin)
 434:   {
 435:     int loc = areaOfClick(origParent,
 436:                           SwingUtilities.convertPoint(toolBar, position,
 437:                                                       origParent));
 438: 
 439:     if (loc != -1)
 440:       {
 441:     dragWindow.setBorderColor(dockingBorderColor);
 442:     dragWindow.setBackground(dockingColor);
 443:       }
 444:     else
 445:       {
 446:     dragWindow.setBorderColor(floatingBorderColor);
 447:     dragWindow.setBackground(floatingColor);
 448:       }
 449: 
 450:     int w = 0;
 451:     int h = 0;
 452: 
 453:     boolean tmp = (loc == SwingConstants.NORTH)
 454:                   || (loc == SwingConstants.SOUTH) || (loc == -1);
 455: 
 456:     cachedOrientation = toolBar.getOrientation();
 457:     cachedBounds = toolBar.getSize();
 458:     if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp)
 459:         || ((cachedOrientation == VERTICAL) && ! tmp))
 460:       {
 461:     w = cachedBounds.width;
 462:     h = cachedBounds.height;
 463:       }
 464:     else
 465:       {
 466:     w = cachedBounds.height;
 467:     h = cachedBounds.width;
 468:       }
 469: 
 470:     Point p = dragWindow.getOffset();
 471:     Insets insets = toolBar.getInsets();
 472: 
 473:     dragWindow.setBounds((origin.x + position.x) - p.x
 474:                          - ((insets.left + insets.right) / 2),
 475:                          (origin.y + position.y) - p.y
 476:                          - ((insets.top + insets.bottom) / 2), w, h);
 477: 
 478:     if (! dragWindow.isVisible())
 479:       dragWindow.show();
 480:   }
 481: 
 482:   /**
 483:    * This method is used at the end of a drag session to place the frame in
 484:    * either its original parent as a docked JToolBar or in its floating
 485:    * frame.
 486:    *
 487:    * @param position The position of the mouse cursor relative to the
 488:    *        JToolBar.
 489:    * @param origin The screen position of the JToolBar before the drag session
 490:    *        started.
 491:    */
 492:   protected void floatAt(Point position, Point origin)
 493:   {
 494:     Point p = new Point(position);
 495:     int aoc = areaOfClick(origParent,
 496:                           SwingUtilities.convertPoint(toolBar, p, origParent));
 497: 
 498:     Container oldParent = toolBar.getParent();
 499: 
 500:     oldParent.remove(toolBar);
 501:     oldParent.doLayout();
 502:     oldParent.repaint();
 503: 
 504:     Container newParent;
 505: 
 506:     if (aoc == -1)
 507:       newParent = ((RootPaneContainer) floatFrame).getContentPane();
 508:     else
 509:       {
 510:     floatFrame.hide();
 511:     newParent = origParent;
 512:       }
 513: 
 514:     String constraint;
 515:     switch (aoc)
 516:       {
 517:       case SwingConstants.EAST:
 518:     constraint = BorderLayout.EAST;
 519:     break;
 520:       case SwingConstants.NORTH:
 521:     constraint = BorderLayout.NORTH;
 522:     break;
 523:       case SwingConstants.SOUTH:
 524:     constraint = BorderLayout.SOUTH;
 525:     break;
 526:       case SwingConstants.WEST:
 527:     constraint = BorderLayout.WEST;
 528:     break;
 529:       default:
 530:     constraint = BorderLayout.CENTER;
 531:     break;
 532:       }
 533: 
 534:     int newOrientation = SwingConstants.HORIZONTAL;
 535:     if ((aoc != -1)
 536:         && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST)))
 537:       newOrientation = SwingConstants.VERTICAL;
 538: 
 539:     if (aoc != -1)
 540:       {
 541:     constraintBeforeFloating = constraint;
 542:     lastGoodOrientation = newOrientation;
 543:       }
 544: 
 545:     newParent.add(toolBar, constraint);
 546: 
 547:     setFloating(aoc == -1, null);
 548:     toolBar.setOrientation(newOrientation);
 549: 
 550:     Insets insets = floatFrame.getInsets();
 551:     Dimension dims = toolBar.getPreferredSize();
 552:     p = dragWindow.getOffset();
 553:     setFloatingLocation((position.x + origin.x) - p.x
 554:                         - ((insets.left + insets.right) / 2),
 555:                         (position.y + origin.y) - p.y
 556:                         - ((insets.top + insets.bottom) / 2));
 557: 
 558:     if (aoc == -1)
 559:       {
 560:     floatFrame.pack();
 561:     floatFrame.setSize(dims.width + insets.left + insets.right,
 562:                        dims.height + insets.top + insets.bottom);
 563:     floatFrame.show();
 564:       }
 565: 
 566:     newParent.invalidate();
 567:     newParent.validate();
 568:     newParent.repaint();
 569:   }
 570: 
 571:   /**
 572:    * This method returns the docking color.
 573:    *
 574:    * @return The docking color.
 575:    */
 576:   public Color getDockingColor()
 577:   {
 578:     return dockingColor;
 579:   }
 580: 
 581:   /**
 582:    * This method returns the Color which is displayed when over a floating
 583:    * area.
 584:    *
 585:    * @return The color which is displayed when over a floating area.
 586:    */
 587:   public Color getFloatingColor()
 588:   {
 589:     return floatingColor;
 590:   }
 591: 
 592:   /**
 593:    * This method returns the maximum size of the given JComponent for this UI.
 594:    *
 595:    * @param c The JComponent to find the maximum size for.
 596:    *
 597:    * @return The maximum size for this UI.
 598:    */
 599:   public Dimension getMaximumSize(JComponent c)
 600:   {
 601:     return getPreferredSize(c);
 602:   }
 603: 
 604:   /**
 605:    * This method returns the minimum size of the given JComponent for this UI.
 606:    *
 607:    * @param c The JComponent to find a minimum size for.
 608:    *
 609:    * @return The minimum size for this UI.
 610:    */
 611:   public Dimension getMinimumSize(JComponent c)
 612:   {
 613:     return getPreferredSize(c);
 614:   }
 615: 
 616:   /**
 617:    * This method installs the needed components for the JToolBar.
 618:    */
 619:   protected void installComponents()
 620:   {
 621:     floatFrame = (Window) createFloatingWindow(toolBar);
 622: 
 623:     dragWindow = createDragWindow(toolBar);
 624: 
 625:     nonRolloverBorder = createNonRolloverBorder();
 626:     rolloverBorder = createRolloverBorder();
 627: 
 628:     borders = new Hashtable();
 629:     setRolloverBorders(toolBar.isRollover());
 630: 
 631:     fillHashtable();
 632:   }
 633: 
 634:   /**
 635:    * This method installs the defaults as specified by the look and feel.
 636:    */
 637:   protected void installDefaults()
 638:   {
 639:     LookAndFeel.installBorder(toolBar, "ToolBar.border");
 640:     LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background",
 641:                                      "ToolBar.foreground", "ToolBar.font");
 642: 
 643:     dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground");
 644:     dockingColor = UIManager.getColor("ToolBar.dockingBackground");
 645: 
 646:     floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground");
 647:     floatingColor = UIManager.getColor("ToolBar.floatingBackground");
 648:   }
 649: 
 650:   /**
 651:    * This method installs the keyboard actions for the JToolBar as specified
 652:    * by the look and feel.
 653:    */
 654:   protected void installKeyboardActions()
 655:   {
 656:     // Install the input map.
 657:     InputMap inputMap =
 658:       (InputMap) SharedUIDefaults.get("ToolBar.ancestorInputMap");
 659:     SwingUtilities.replaceUIInputMap(toolBar,
 660:                                  JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
 661:                                  inputMap);
 662: 
 663:     // FIXME: The JDK uses a LazyActionMap for parentActionMap
 664:     SwingUtilities.replaceUIActionMap(toolBar, getActionMap());
 665:   }
 666: 
 667:   /**
 668:    * Fetches the action map from  the UI defaults, or create a new one
 669:    * if the action map hasn't been initialized.
 670:    *
 671:    * @return the action map
 672:    */
 673:   private ActionMap getActionMap()
 674:   {
 675:     ActionMap am = (ActionMap) UIManager.get("ToolBar.actionMap");
 676:     if (am == null)
 677:       {
 678:         am = createDefaultActions();
 679:         UIManager.getLookAndFeelDefaults().put("ToolBar.actionMap", am);
 680:       }
 681:     return am;
 682:   }
 683: 
 684:   private ActionMap createDefaultActions()
 685:   {
 686:     ActionMapUIResource am = new ActionMapUIResource();
 687:     Action action = new ToolBarAction();
 688: 
 689:     am.put("navigateLeft", action);
 690:     am.put("navigateRight", action);
 691:     am.put("navigateUp", action);
 692:     am.put("navigateDown", action);
 693: 
 694:     return am;
 695:   }
 696: 
 697:   /**
 698:    * This method installs listeners for the JToolBar.
 699:    */
 700:   protected void installListeners()
 701:   {
 702:     dockingListener = createDockingListener();
 703:     toolBar.addMouseListener(dockingListener);
 704:     toolBar.addMouseMotionListener(dockingListener);
 705: 
 706:     propertyListener = createPropertyListener();
 707:     toolBar.addPropertyChangeListener(propertyListener);
 708: 
 709:     toolBarContListener = createToolBarContListener();
 710:     toolBar.addContainerListener(toolBarContListener);
 711: 
 712:     windowListener = createFrameListener();
 713:     floatFrame.addWindowListener(windowListener);
 714: 
 715:     toolBarFocusListener = createToolBarFocusListener();
 716:     if (toolBarFocusListener != null)
 717:       {
 718:         int count = toolBar.getComponentCount();
 719:         for (int i = 0; i < count; i++)
 720:           toolBar.getComponent(i).addFocusListener(toolBarFocusListener);
 721:       }
 722:   }
 723: 
 724:   /**
 725:    * This method installs non rollover borders for each component inside the
 726:    * given JComponent.
 727:    *
 728:    * @param c The JComponent whose children need to have non rollover borders
 729:    *        installed.
 730:    */
 731:   protected void installNonRolloverBorders(JComponent c)
 732:   {
 733:     Component[] components = toolBar.getComponents();
 734: 
 735:     for (int i = 0; i < components.length; i++)
 736:       setBorderToNonRollover(components[i]);
 737:   }
 738: 
 739:   /**
 740:    * This method installs normal (or their original) borders for each
 741:    * component inside the given JComponent.
 742:    *
 743:    * @param c The JComponent whose children need to have their original
 744:    *        borders installed.
 745:    */
 746:   protected void installNormalBorders(JComponent c)
 747:   {
 748:     Component[] components = toolBar.getComponents();
 749: 
 750:     for (int i = 0; i < components.length; i++)
 751:       setBorderToNormal(components[i]);
 752:   }
 753: 
 754:   /**
 755:    * This method install rollover borders for each component inside the given
 756:    * JComponent.
 757:    *
 758:    * @param c The JComponent whose children need to have rollover borders
 759:    *        installed.
 760:    */
 761:   protected void installRolloverBorders(JComponent c)
 762:   {
 763:     Component[] components = toolBar.getComponents();
 764: 
 765:     for (int i = 0; i < components.length; i++)
 766:       setBorderToRollover(components[i]);
 767:   }
 768: 
 769:   /**
 770:    * This method fills the borders hashtable with a list of components that
 771:    * are JButtons and their borders.
 772:    */
 773:   private void fillHashtable()
 774:   {
 775:     Component[] c = toolBar.getComponents();
 776: 
 777:     for (int i = 0; i < c.length; i++)
 778:       {
 779:     if (c[i] instanceof JButton)
 780:       {
 781:         // Don't really care about anything other than JButtons
 782:         JButton b = (JButton) c[i];
 783: 
 784:         if (b.getBorder() != null)
 785:           borders.put(b, b.getBorder());
 786:       }
 787:       }
 788:   }
 789: 
 790:   /**
 791:    * This method installs the UI for the given JComponent.
 792:    *
 793:    * @param c The JComponent to install a UI for.
 794:    */
 795:   public void installUI(JComponent c)
 796:   {
 797:     super.installUI(c);
 798: 
 799:     if (c instanceof JToolBar)
 800:       {
 801:     toolBar = (JToolBar) c;
 802:     installDefaults();
 803:     installComponents();
 804:     installListeners();
 805:     installKeyboardActions();
 806:       }
 807:   }
 808: 
 809:   /**
 810:    * This method returns whether the JToolBar is floating.
 811:    *
 812:    * @return Whether the JToolBar is floating.
 813:    */
 814:   public boolean isFloating()
 815:   {
 816:     return floatFrame.isVisible();
 817:   }
 818: 
 819:   /**
 820:    * This method returns whether rollover borders have been set.
 821:    *
 822:    * @return Whether rollover borders have been set.
 823:    */
 824:   public boolean isRolloverBorders()
 825:   {
 826:     return toolBar.isRollover();
 827:   }
 828: 
 829:   /**
 830:    * This method navigates in the given direction giving focus to the next
 831:    * component in the given direction.
 832:    *
 833:    * @param direction The direction to give focus to.
 834:    */
 835:   protected void navigateFocusedComp(int direction)
 836:   {
 837:     int count = toolBar.getComponentCount();
 838:     switch (direction)
 839:     {
 840:       case EAST:
 841:       case SOUTH:
 842:         if (focusedCompIndex >= 0 && focusedCompIndex < count)
 843:           {
 844:             int i = focusedCompIndex + 1;
 845:             boolean focusRequested = false;
 846:             // Find component to focus and request focus on it.
 847:             while (i != focusedCompIndex && ! focusRequested)
 848:               {
 849:                 if (i >= count)
 850:                   i = 0;
 851:                 Component comp = toolBar.getComponentAtIndex(i++);
 852:                 if (comp != null && comp.isFocusable()
 853:                     && comp.isEnabled())
 854:                   {
 855:                     comp.requestFocus();
 856:                     focusRequested = true;
 857:                   }
 858:               }
 859:           }
 860:         break;
 861:       case WEST:
 862:       case NORTH:
 863:         if (focusedCompIndex >= 0 && focusedCompIndex < count)
 864:           {
 865:             int i = focusedCompIndex - 1;
 866:             boolean focusRequested = false;
 867:             // Find component to focus and request focus on it.
 868:             while (i != focusedCompIndex && ! focusRequested)
 869:               {
 870:                 if (i < 0)
 871:                   i = count - 1;
 872:                 Component comp = toolBar.getComponentAtIndex(i--);
 873:                 if (comp != null && comp.isFocusable()
 874:                     && comp.isEnabled())
 875:                   {
 876:                     comp.requestFocus();
 877:                     focusRequested = true;
 878:                   }
 879:               }
 880:           }
 881:         break;
 882:       default:
 883:         break;
 884:     }
 885:   }
 886: 
 887:   /**
 888:    * This method sets the border of the given component to a non rollover
 889:    * border.
 890:    *
 891:    * @param c The Component whose border needs to be set.
 892:    */
 893:   protected void setBorderToNonRollover(Component c)
 894:   {
 895:     if (c instanceof AbstractButton)
 896:       {
 897:     AbstractButton b = (AbstractButton) c;
 898:     b.setRolloverEnabled(false);
 899: 
 900:         // Save old border in hashtable.
 901:     if (b.getBorder() != null)
 902:           borders.put(b, b.getBorder());
 903:         
 904:     b.setBorder(nonRolloverBorder);
 905:       }
 906:   }
 907:<