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: 
 908:   /**
 909:    * This method sets the border of the given component to its original value.
 910:    *
 911:    * @param c The Component whose border needs to be set.
 912:    */
 913:   protected void setBorderToNormal(Component c)
 914:   {
 915:     if (c instanceof AbstractButton)
 916:       {
 917:         AbstractButton b = (AbstractButton) c;
 918:         b.setRolloverEnabled(true);
 919:         b.setBorder((Border) borders.remove(b));
 920:       }
 921:   }
 922: 
 923:   /**
 924:    * This method sets the border of the given component to a rollover border.
 925:    *
 926:    * @param c The Component whose border needs to be set.
 927:    */
 928:   protected void setBorderToRollover(Component c)
 929:   {
 930:     if (c instanceof AbstractButton)
 931:       {
 932:         AbstractButton b = (AbstractButton) c;
 933:         b.setRolloverEnabled(false);
 934:         
 935:         // Save old border in hashtable.
 936:         if (b.getBorder() != null)
 937:       borders.put(b, b.getBorder());
 938:         
 939:         b.setBorder(rolloverBorder);
 940:       }
 941:   }
 942: 
 943:   /**
 944:    * This method sets the docking color.
 945:    *
 946:    * @param c The docking color.
 947:    */
 948:   public void setDockingColor(Color c)
 949:   {
 950:     dockingColor = c;
 951:   }
 952: 
 953:   /**
 954:    * This method sets the floating property for the JToolBar.
 955:    *
 956:    * @param b Whether the JToolBar is floating.
 957:    * @param p FIXME
 958:    */
 959:   public void setFloating(boolean b, Point p)
 960:   {
 961:     // FIXME: use p for something. It's not location
 962:     // since we already have setFloatingLocation.
 963:     floatFrame.setVisible(b);
 964:   }
 965: 
 966:   /**
 967:    * This method sets the color displayed when the JToolBar is not in a
 968:    * dockable area.
 969:    *
 970:    * @param c The floating color.
 971:    */
 972:   public void setFloatingColor(Color c)
 973:   {
 974:     floatingColor = c;
 975:   }
 976: 
 977:   /**
 978:    * This method sets the floating location of the JToolBar.
 979:    *
 980:    * @param x The x coordinate for the floating frame.
 981:    * @param y The y coordinate for the floating frame.
 982:    */
 983:   public void setFloatingLocation(int x, int y)
 984:   {
 985:     // x,y are the coordinates of the new JFrame created to store the toolbar
 986:     // XXX: The floating location is bogus is not floating.
 987:     floatFrame.setLocation(x, y);
 988:     floatFrame.invalidate();
 989:     floatFrame.validate();
 990:     floatFrame.repaint();
 991:   }
 992: 
 993:   /**
 994:    * This is a convenience method for changing the orientation of the
 995:    * JToolBar.
 996:    *
 997:    * @param orientation The new orientation.
 998:    */
 999:   public void setOrientation(int orientation)
1000:   {
1001:     toolBar.setOrientation(orientation);
1002:   }
1003: 
1004:   /**
1005:    * This method changes the child components to have rollover borders if the
1006:    * given parameter is true. Otherwise, the components are set to have non
1007:    * rollover borders.
1008:    *
1009:    * @param rollover Whether the children will have rollover borders.
1010:    */
1011:   public void setRolloverBorders(boolean rollover)
1012:   {
1013:     if (rollover)
1014:       installRolloverBorders(toolBar);
1015:     else
1016:       installNonRolloverBorders(toolBar);
1017:   }
1018: 
1019:   /**
1020:    * This method uninstall UI installed components from the JToolBar.
1021:    */
1022:   protected void uninstallComponents()
1023:   {
1024:     installNormalBorders(toolBar);
1025:     borders = null;
1026:     cachedBounds = null;
1027: 
1028:     floatFrame = null;
1029:     dragWindow = null;
1030:   }
1031: 
1032:   /**
1033:    * This method removes the defaults installed by the Look and Feel.
1034:    */
1035:   protected void uninstallDefaults()
1036:   {
1037:     toolBar.setBackground(null);
1038:     toolBar.setForeground(null);
1039:     toolBar.setFont(null);
1040: 
1041:     dockingBorderColor = null;
1042:     dockingColor = null;
1043:     floatingBorderColor = null;
1044:     floatingColor = null;
1045:   }
1046: 
1047:   /**
1048:    * This method uninstalls keyboard actions installed by the UI.
1049:    */
1050:   protected void uninstallKeyboardActions()
1051:   {
1052:     SwingUtilities.replaceUIInputMap(toolBar, JComponent.
1053:                                      WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
1054:     SwingUtilities.replaceUIActionMap(toolBar, null);
1055:   }
1056: 
1057:   /**
1058:    * This method uninstalls listeners installed by the UI.
1059:    */
1060:   protected void uninstallListeners()
1061:   {
1062:     if (toolBarFocusListener != null)
1063:       {
1064:         int count = toolBar.getComponentCount();
1065:         for (int i = 0; i < count; i++)
1066:           toolBar.getComponent(i).removeFocusListener(toolBarFocusListener);
1067:         toolBarFocusListener = null;
1068:       }
1069: 
1070:     floatFrame.removeWindowListener(windowListener);
1071:     windowListener = null;
1072: 
1073:     toolBar.removeContainerListener(toolBarContListener);
1074:     toolBarContListener = null;
1075: 
1076:     toolBar.removeMouseMotionListener(dockingListener);
1077:     toolBar.removeMouseListener(dockingListener);
1078:     dockingListener = null;
1079:   }
1080: 
1081:   /**
1082:    * This method uninstalls the UI.
1083:    *
1084:    * @param c The JComponent that is having this UI removed.
1085:    */
1086:   public void uninstallUI(JComponent c)
1087:   {
1088:     uninstallKeyboardActions();
1089:     uninstallListeners();
1090:     uninstallComponents();
1091:     uninstallDefaults();
1092:     toolBar = null;
1093:   }
1094: 
1095:   /**
1096:    * This is the MouseHandler class that allows the user to drag the JToolBar
1097:    * in and out of the parent and dock it if it can.
1098:    */
1099:   public class DockingListener implements MouseInputListener
1100:   {
1101:     /** Whether the JToolBar is being dragged. */
1102:     protected boolean isDragging;
1103: 
1104:     /**
1105:      * The origin point. This point is saved from the beginning press and is
1106:      * used until the end of the drag session.
1107:      */
1108:     protected Point origin;
1109: 
1110:     /** The JToolBar being dragged. */
1111:     protected JToolBar toolBar;
1112: 
1113:     /**
1114:      * Creates a new DockingListener object.
1115:      *
1116:      * @param t The JToolBar this DockingListener is being used for.
1117:      */
1118:     public DockingListener(JToolBar t)
1119:     {
1120:       toolBar = t;
1121:     }
1122: 
1123:     /**
1124:      * This method is called when the mouse is clicked.
1125:      *
1126:      * @param e The MouseEvent.
1127:      */
1128:     public void mouseClicked(MouseEvent e)
1129:     {
1130:       // Nothing to do here.
1131:     }
1132: 
1133:     /**
1134:      * This method is called when the mouse is dragged. It delegates the drag
1135:      * painting to the dragTo method.
1136:      *
1137:      * @param e The MouseEvent.
1138:      */
1139:     public void mouseDragged(MouseEvent e)
1140:     {
1141:       if (isDragging)
1142:     dragTo(e.getPoint(), origin);
1143:     }
1144: 
1145:     /**
1146:      * This method is called when the mouse enters the JToolBar.
1147:      *
1148:      * @param e The MouseEvent.
1149:      */
1150:     public void mouseEntered(MouseEvent e)
1151:     {
1152:       // Nothing to do here.
1153:     }
1154: 
1155:     /**
1156:      * This method is called when the mouse exits the JToolBar.
1157:      *
1158:      * @param e The MouseEvent.
1159:      */
1160:     public void mouseExited(MouseEvent e)
1161:     {
1162:       // Nothing to do here.
1163:     }
1164: 
1165:     /**
1166:      * This method is called when the mouse is moved in the JToolBar.
1167:      *
1168:      * @param e The MouseEvent.
1169:      */
1170:     public void mouseMoved(MouseEvent e)
1171:     {
1172:       // Nothing to do here.
1173:     }
1174: 
1175:     /**
1176:      * This method is called when the mouse is pressed in the JToolBar. If the
1177:      * press doesn't occur in a place where it causes the JToolBar to be
1178:      * dragged, it returns. Otherwise, it starts a drag session.
1179:      *
1180:      * @param e The MouseEvent.
1181:      */
1182:     public void mousePressed(MouseEvent e)
1183:     {
1184:       if (! toolBar.isFloatable())
1185:     return;
1186: 
1187:       Point ssd = e.getPoint();
1188:       Insets insets = toolBar.getInsets();
1189: 
1190:       // Verify that this click occurs in the top inset.
1191:       if (toolBar.getOrientation() == SwingConstants.HORIZONTAL)
1192:         {
1193:       if (e.getX() > insets.left)
1194:         return;
1195:         }
1196:       else
1197:         {
1198:       if (e.getY() > insets.top)
1199:         return;
1200:         }
1201: 
1202:       origin = new Point(0, 0);
1203:       if (toolBar.isShowing())
1204:         SwingUtilities.convertPointToScreen(ssd, toolBar);
1205: 
1206:       if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource))
1207:     // Need to know who keeps the toolBar if it gets dragged back into it.
1208:     origParent = toolBar.getParent();
1209:       
1210:       if (toolBar.isShowing())
1211:         SwingUtilities.convertPointToScreen(origin, toolBar);
1212: 
1213:       isDragging = true;
1214: 
1215:       if (dragWindow != null)
1216:     dragWindow.setOffset(new Point(cachedBounds.width / 2, 
1217:             cachedBounds.height / 2));
1218: 
1219:       dragTo(e.getPoint(), origin);
1220:     }
1221: 
1222:     /**
1223:      * This method is called when the mouse is released from the JToolBar.
1224:      *
1225:      * @param e The MouseEvent.
1226:      */
1227:     public void mouseReleased(MouseEvent e)
1228:     {
1229:       if (! isDragging || ! toolBar.isFloatable())
1230:     return;
1231: 
1232:       isDragging = false;
1233:       floatAt(e.getPoint(), origin);
1234:       dragWindow.hide();
1235:     }
1236:   }
1237: 
1238:   /**
1239:    * This is the window that appears when the JToolBar is being dragged
1240:    * around.
1241:    */
1242:   protected class DragWindow extends Window
1243:   {
1244:     /**
1245:      * The current border color. It changes depending on whether the JToolBar
1246:      * is over a place that allows it to dock.
1247:      */
1248:     private Color borderColor;
1249: 
1250:     /** The between the mouse and the top left corner of the window. */
1251:     private Point offset;
1252: 
1253:     /**
1254:      * Creates a new DragWindow object.
1255:      * This is package-private to avoid an accessor method.
1256:      */
1257:     DragWindow()
1258:     {
1259:       super(owner);
1260:     }
1261: 
1262:     /**
1263:      * The color that the border should be.
1264:      *
1265:      * @return The border color.
1266:      */
1267:     public Color getBorderColor()
1268:     {
1269:       if (borderColor == null)
1270:     return Color.BLACK;
1271: 
1272:       return borderColor;
1273:     }
1274: 
1275:     /**
1276:      * This method returns the insets for the DragWindow.
1277:      *
1278:      * @return The insets for the DragWindow.
1279:      */
1280:     public Insets getInsets()
1281:     {
1282:       // This window has no decorations, so insets are empty.
1283:       return new Insets(0, 0, 0, 0);
1284:     }
1285: 
1286:     /**
1287:      * This method returns the mouse offset from the top left corner of the
1288:      * DragWindow.
1289:      *
1290:      * @return The mouse offset.
1291:      */
1292:     public Point getOffset()
1293:     {
1294:       return offset;
1295:     }
1296: 
1297:     /**
1298:      * This method paints the DragWindow.
1299:      *
1300:      * @param g The Graphics object to paint with.
1301:      */
1302:     public void paint(Graphics g)
1303:     {
1304:       //  No visiting children necessary.
1305:       Color saved = g.getColor();
1306:       Rectangle b = getBounds();
1307: 
1308:       g.setColor(getBorderColor());
1309:       g.drawRect(0, 0, b.width - 1, b.height - 1);
1310: 
1311:       g.setColor(saved);
1312:     }
1313: 
1314:     /**
1315:      * This method changes the border color.
1316:      *
1317:      * @param c The new border color.
1318:      */
1319:     public void setBorderColor(Color c)
1320:     {
1321:       borderColor = c;
1322:     }
1323: 
1324:     /**
1325:      * This method changes the mouse offset.
1326:      *
1327:      * @param p The new mouse offset.
1328:      */
1329:     public void setOffset(Point p)
1330:     {
1331:       offset = p;
1332:     }
1333: 
1334:     /**
1335:      * Sets the orientation of the toolbar and the
1336:      * drag window.
1337:      *
1338:      * @param o - the new orientation of the toolbar and drag
1339:      * window.
1340:      */
1341:     public void setOrientation(int o)
1342:     {
1343:       toolBar.setOrientation(o);
1344:       if (dragWindow != null) 
1345:         dragWindow.setOrientation(o);
1346:     }
1347:   }
1348: 
1349:   /**
1350:    * This helper class listens for Window events from the floatable window and
1351:    * if it is closed, returns the JToolBar to the last known good location.
1352:    */
1353:   protected class FrameListener extends WindowAdapter
1354:   {
1355:     /**
1356:      * This method is called when the floating window is closed.
1357:      *
1358:      * @param e The WindowEvent.
1359:      */
1360:     public void windowClosing(WindowEvent e)
1361:     {
1362:       Container parent = toolBar.getParent();
1363:       parent.remove(toolBar);
1364: 
1365:       if (origParent != null)
1366:         {
1367:       origParent.add(toolBar,
1368:                      (constraintBeforeFloating != null)
1369:                      ? constraintBeforeFloating : BorderLayout.NORTH);
1370:       toolBar.setOrientation(lastGoodOrientation);
1371:         }
1372: 
1373:       origParent.invalidate();
1374:       origParent.validate();
1375:       origParent.repaint();
1376:     }
1377:   }
1378: 
1379:   /**
1380:    * This helper class listens for PropertyChangeEvents from the JToolBar.
1381:    */
1382:   protected class PropertyListener implements PropertyChangeListener
1383:   {
1384:     /**
1385:      * This method is called when a property from the JToolBar is changed.
1386:      *
1387:      * @param e The PropertyChangeEvent.
1388:      */
1389:     public void propertyChange(PropertyChangeEvent e)
1390:     {
1391:       // FIXME: need name properties so can change floatFrame title.
1392:       if (e.getPropertyName().equals("rollover") && toolBar != null)
1393:         setRolloverBorders(toolBar.isRollover());
1394:     }
1395:   }
1396: 
1397:   /**
1398:    * This helper class listens for components added to and removed from the
1399:    * JToolBar.
1400:    */
1401:   protected class ToolBarContListener implements ContainerListener
1402:   {
1403:     /**
1404:      * This method is responsible for setting rollover or non rollover for new
1405:      * buttons added to the JToolBar.
1406:      *
1407:      * @param e The ContainerEvent.
1408:      */
1409:     public void componentAdded(ContainerEvent e)
1410:     {
1411:       if (e.getChild() instanceof JButton)
1412:         {
1413:       JButton b = (JButton) e.getChild();
1414: 
1415:       if (b.getBorder() != null)
1416:         borders.put(b, b.getBorder());
1417:         }
1418: 
1419:       if (isRolloverBorders())
1420:     setBorderToRollover(e.getChild());
1421:       else
1422:     setBorderToNonRollover(e.getChild());
1423: 
1424:       cachedBounds = toolBar.getPreferredSize();
1425:       cachedOrientation = toolBar.getOrientation();
1426: 
1427:       Component c = e.getChild();
1428:       if (toolBarFocusListener != null)
1429:         c.addFocusListener(toolBarFocusListener);
1430:     }
1431: 
1432:     /**
1433:      * This method is responsible for giving the child components their
1434:      * original borders when they are removed.
1435:      *
1436:      * @param e The ContainerEvent.
1437:      */
1438:     public void componentRemoved(ContainerEvent e)
1439:     {
1440:       setBorderToNormal(e.getChild());
1441:       cachedBounds = toolBar.getPreferredSize();
1442:       cachedOrientation = toolBar.getOrientation();
1443: 
1444:       Component c = e.getChild();
1445:       if (toolBarFocusListener != null)
1446:         c.removeFocusListener(toolBarFocusListener);
1447:     }
1448:   }
1449: 
1450:   /**
1451:    * This is the floating window that is returned when getFloatingWindow is
1452:    * called.
1453:    */
1454:   private class ToolBarDialog extends JDialog implements UIResource
1455:   {
1456:     /**
1457:      * Creates a new ToolBarDialog object with the name given by the JToolBar.
1458:      */
1459:     public ToolBarDialog()
1460:     {
1461:       super();
1462:       setName((toolBar.getName() != null) ? toolBar.getName() : "");
1463:     }
1464:   }
1465: 
1466:   /**
1467:    * DOCUMENT ME!
1468:    */
1469:   protected class ToolBarFocusListener implements FocusListener
1470:   {
1471:     /**
1472:      * Creates a new ToolBarFocusListener object.
1473:      */
1474:     protected ToolBarFocusListener()
1475:     {
1476:       // Nothing to do here.
1477:     }
1478: 
1479:     /**
1480:      * Receives notification when the toolbar or one of it's component
1481:      * receives the keyboard input focus.
1482:      * 
1483:      * @param e the focus event
1484:      */
1485:     public void focusGained(FocusEvent e)
1486:     {
1487:       Component c = e.getComponent();
1488:       focusedCompIndex = toolBar.getComponentIndex(c);
1489:     }
1490: 
1491:     /**
1492:      * Receives notification when the toolbar or one of it's component
1493:      * looses the keyboard input focus.
1494:      * 
1495:      * @param e the focus event
1496:      */
1497:     public void focusLost(FocusEvent e)
1498:     {
1499:       // Do nothing here.
1500:     }
1501:   }
1502: 
1503:   /**
1504:    * This helper class acts as the border for the JToolBar.
1505:    */
1506:   private static class ToolBarBorder implements Border
1507:   {
1508:     /** The size of the larger, draggable side of the border. */
1509:     private static final int offset = 10;
1510: 
1511:     /** The other sides. */
1512:     private static final int regular = 2;
1513: 
1514:     /**
1515:      * This method returns the border insets for the JToolBar.
1516:      *
1517:      * @param c The Component to find insets for.
1518:      *
1519:      * @return The border insets.
1520:      */
1521:     public Insets getBorderInsets(Component c)
1522:     {
1523:       if (c instanceof JToolBar)
1524:         {
1525:       JToolBar tb = (JToolBar) c;
1526:       int orientation = tb.getOrientation();
1527: 
1528:       if (! tb.isFloatable())
1529:         return new Insets(regular, regular, regular, regular);
1530:       else if (orientation == SwingConstants.HORIZONTAL)
1531:         return new Insets(regular, offset, regular, regular);
1532:       else
1533:         return new Insets(offset, regular, regular, regular);
1534:         }
1535: 
1536:       return new Insets(0, 0, 0, 0);
1537:     }
1538: 
1539:     /**
1540:      * This method returns whether the border is opaque.
1541:      *
1542:      * @return Whether the border is opaque.
1543:      */
1544:     public boolean isBorderOpaque()
1545:     {
1546:       return false;
1547:     }
1548: 
1549:     /**
1550:      * This method paints the ribbed area of the border.
1551:      *
1552:      * @param g The Graphics object to paint with.
1553:      * @param x The x coordinate of the area.
1554:      * @param y The y coordinate of the area.
1555:      * @param w The width of the area.
1556:      * @param h The height of the area.
1557:      * @param size The size of the bump.
1558:      * @param c The color of the bumps.
1559:      */
1560:     private void paintBumps(Graphics g, int x, int y, int w, int h, int size,
1561:                             Color c)
1562:     {
1563:       Color saved = g.getColor();
1564:       g.setColor(c);
1565: 
1566:       int hgap = 2 * size;
1567:       int vgap = 4 * size;
1568:       int count = 0;
1569: 
1570:       for (int i = x; i < (w + x); i += hgap)
1571:     for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y);
1572:          j += vgap)
1573:       g.fillRect(i, j, size, size);
1574: 
1575:       g.setColor(saved);
1576:     }
1577: 
1578:     /**
1579:      * This method paints the border around the given Component.
1580:      *
1581:      * @param c The Component whose border is being painted.
1582:      * @param g The Graphics object to paint with.
1583:      * @param x The x coordinate of the component.
1584:      * @param y The y coordinate of the component.
1585:      * @param width The width of the component.
1586:      * @param height The height of the component.
1587:      */
1588:     public void paintBorder(Component c, Graphics g, int x, int y, int width,
1589:                             int height)
1590:     {
1591:       if (c instanceof JToolBar)
1592:         {
1593:       JToolBar tb = (JToolBar) c;
1594: 
1595:       int orientation = tb.getOrientation();
1596: 
1597:       if (orientation == SwingConstants.HORIZONTAL)
1598:         {
1599:           paintBumps(g, x, y, offset, height, 1, Color.WHITE);
1600:           paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY);
1601:         }
1602:       else
1603:         {
1604:           paintBumps(g, x, y, width, offset, 1, Color.WHITE);
1605:           paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY);
1606:         }
1607:         }
1608:     }
1609:   }
1610: }