Source for javax.swing.plaf.basic.BasicToolBarUI

   1: /* BasicToolBarUI.java --
   2:    Copyright (C) 2004, 2005  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.ContainerEvent;
  52: import java.awt.event.ContainerListener;
  53: import java.awt.event.FocusEvent;
  54: import java.awt.event.FocusListener;
  55: import java.awt.event.MouseEvent;
  56: import java.awt.event.WindowAdapter;
  57: import java.awt.event.WindowEvent;
  58: import java.awt.event.WindowListener;
  59: import java.beans.PropertyChangeEvent;
  60: import java.beans.PropertyChangeListener;
  61: import java.util.Hashtable;
  62: 
  63: import javax.swing.JButton;
  64: import javax.swing.JComponent;
  65: import javax.swing.JDialog;
  66: import javax.swing.JFrame;
  67: import javax.swing.JToolBar;
  68: import javax.swing.KeyStroke;
  69: import javax.swing.LookAndFeel;
  70: import javax.swing.RootPaneContainer;
  71: import javax.swing.SwingConstants;
  72: import javax.swing.SwingUtilities;
  73: import javax.swing.UIManager;
  74: import javax.swing.border.Border;
  75: import javax.swing.event.MouseInputListener;
  76: import javax.swing.plaf.BorderUIResource.EtchedBorderUIResource;
  77: import javax.swing.plaf.ComponentUI;
  78: import javax.swing.plaf.ToolBarUI;
  79: import javax.swing.plaf.UIResource;
  80: 
  81: /**
  82:  * This is the Basic Look and Feel UI class for JToolBar.
  83:  */
  84: public class BasicToolBarUI extends ToolBarUI implements SwingConstants
  85: {
  86:   /** Static owner of all DragWindows.
  87:    * This is package-private to avoid an accessor method.  */
  88:   static JFrame owner = new JFrame();
  89: 
  90:   /** The border used when the JToolBar is in nonrollover mode. */
  91:   private static Border nonRolloverBorder;
  92: 
  93:   /** The border used when the JToolBar is in rollover mode. */
  94:   private static Border rolloverBorder;
  95: 
  96:   /** The last known BorderLayout constraint before floating. */
  97:   protected String constraintBeforeFloating;
  98: 
  99:   /** The last known orientation of the JToolBar before floating.
 100:    * This is package-private to avoid an accessor method.  */
 101:   int lastGoodOrientation;
 102: 
 103:   /** The color of the border when it is dockable. */
 104:   protected Color dockingBorderColor;
 105: 
 106:   /** The background color of the JToolBar when it is dockable. */
 107:   protected Color dockingColor;
 108: 
 109:   /** The docking listener responsible for mouse events on the JToolBar. */
 110:   protected MouseInputListener dockingListener;
 111: 
 112:   /** The window used for dragging the JToolBar. */
 113:   protected BasicToolBarUI.DragWindow dragWindow;
 114: 
 115:   /** The color of the border when it is not dockable. */
 116:   protected Color floatingBorderColor;
 117: 
 118:   /** The background color of the JToolBar when it is not dockable. */
 119:   protected Color floatingColor;
 120: 
 121:   /** The index of the focused component. */
 122:   protected int focusedCompIndex;
 123: 
 124:   /** The PropertyChangeListener for the JToolBar. */
 125:   protected PropertyChangeListener propertyListener;
 126: 
 127:   /** The JToolBar this UI delegate is responsible for. */
 128:   protected JToolBar toolBar;
 129: 
 130:   /** The Container listener for the JToolBar. */
 131:   protected ContainerListener toolBarContListener;
 132: 
 133:   /** The Focus listener for the JToolBar. */
 134:   protected FocusListener toolBarFocusListener;
 135: 
 136:   /**
 137:    * @deprecated since JDK1.3.
 138:    */
 139:   protected KeyStroke leftKey;
 140: 
 141:   /**
 142:    * @deprecated since JDK1.3.
 143:    */
 144:   protected KeyStroke rightKey;
 145: 
 146:   /**
 147:    * @deprecated since JDK1.3.
 148:    */
 149:   protected KeyStroke upKey;
 150: 
 151:   /**
 152:    * @deprecated since JDK1.3.
 153:    */
 154:   protected KeyStroke downKey;
 155: 
 156:   /**
 157:    * The floating window that is responsible for holding the JToolBar when it
 158:    * is dragged outside of its original parent.
 159:    */
 160:   private transient Window floatFrame;
 161: 
 162:   /** The original parent of the JToolBar.
 163:    * This is package-private to avoid an accessor method.  */
 164:   transient Container origParent;
 165: 
 166:   /** A hashtable of components and their original borders.
 167:    * This is package-private to avoid an accessor method.  */
 168:   transient Hashtable borders;
 169: 
 170:   /** A window listener for the floatable frame. */
 171:   private transient WindowListener windowListener;
 172: 
 173:   /** A set of cached bounds of the JToolBar.
 174:    * This is package-private to avoid an accessor method.  */
 175:   transient Dimension cachedBounds;
 176: 
 177:   /** The cached orientation of the JToolBar.
 178:    * This is package-private to avoid an accessor method.  */
 179:   transient int cachedOrientation;
 180: 
 181:   /**
 182:    * This method creates a new <code>BasicToolBarUI</code> object for the given JToolBar.
 183:    */
 184:   public BasicToolBarUI()
 185:   {
 186:     // Do nothing here.
 187:   }
 188: 
 189:   /**
 190:    * This method returns whether the JToolBar can dock at the given position.
 191:    *
 192:    * @param c The component to try to dock in.
 193:    * @param p The position of the mouse cursor relative to the given
 194:    *        component.
 195:    *
 196:    * @return Whether the JToolBar can dock.
 197:    */
 198:   public boolean canDock(Component c, Point p)
 199:   {
 200:     return areaOfClick(c, p) != -1;
 201:   }
 202: 
 203:   /**
 204:    * This helper method returns the position of the JToolBar if it can dock.
 205:    *
 206:    * @param c The component to try to dock in.
 207:    * @param p The position of the mouse cursor relative to the given
 208:    *        component.
 209:    *
 210:    * @return One of the SwingConstants directions or -1 if the JToolBar can't
 211:    *         dock.
 212:    */
 213:   private int areaOfClick(Component c, Point p)
 214:   {
 215:     // Has to dock in immediate parent, not eventual root container.
 216:     Rectangle pBounds = c.getBounds();
 217: 
 218:     // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last.
 219:     Dimension d = toolBar.getSize();
 220:     int limit = Math.min(d.width, d.height);
 221: 
 222:     // The order of checking is 1. top 2. bottom 3. left 4. right
 223:     if (! pBounds.contains(p))
 224:       return -1;
 225: 
 226:     if (p.y < limit)
 227:       return SwingConstants.NORTH;
 228: 
 229:     if (p.y > (pBounds.height - limit))
 230:       return SwingConstants.SOUTH;
 231: 
 232:     if (p.x < limit)
 233:       return SwingConstants.WEST;
 234: 
 235:     if (p.x > (pBounds.width - limit))
 236:       return SwingConstants.EAST;
 237: 
 238:     return -1;
 239:   }
 240: 
 241:   /**
 242:    * This method creates a new DockingListener for the JToolBar.
 243:    *
 244:    * @return A new DockingListener for the JToolBar.
 245:    */
 246:   protected MouseInputListener createDockingListener()
 247:   {
 248:     return new DockingListener(toolBar);
 249:   }
 250: 
 251:   /**
 252:    * This method creates a new DragWindow for the given JToolBar.
 253:    *
 254:    * @param toolbar The JToolBar to create a DragWindow for.
 255:    *
 256:    * @return A new DragWindow.
 257:    */
 258:   protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar)
 259:   {
 260:     return new DragWindow();
 261:   }
 262: 
 263:   /**
 264:    * This method creates a new floating frame for the JToolBar. By default,
 265:    * this UI uses createFloatingWindow instead. This method of creating a
 266:    * floating frame is deprecated.
 267:    *
 268:    * @param toolbar The JToolBar to create a floating frame for.
 269:    *
 270:    * @return A new floating frame.
 271:    */
 272:   protected JFrame createFloatingFrame(JToolBar toolbar)
 273:   {
 274:     // FIXME: Though deprecated, this should still work.
 275:     return null;
 276:   }
 277: 
 278:   /**
 279:    * This method creates a new floating window for the JToolBar. This is the
 280:    * method used by default to create a floating container for the JToolBar.
 281:    *
 282:    * @param toolbar The JToolBar to create a floating window for.
 283:    *
 284:    * @return A new floating window.
 285:    */
 286:   protected RootPaneContainer createFloatingWindow(JToolBar toolbar)
 287:   {
 288:     // This one is used by default though.
 289:     return new ToolBarDialog();
 290:   }
 291: 
 292:   /**
 293:    * This method creates a new WindowListener for the JToolBar.
 294:    *
 295:    * @return A new WindowListener.
 296:    */
 297:   protected WindowListener createFrameListener()
 298:   {
 299:     return new FrameListener();
 300:   }
 301: 
 302:   /**
 303:    * This method creates a new nonRolloverBorder for JButtons when the
 304:    * JToolBar's rollover property is set to false.
 305:    *
 306:    * @return A new NonRolloverBorder.
 307:    */
 308:   protected Border createNonRolloverBorder()
 309:   {
 310:     return new EtchedBorderUIResource();
 311:   }
 312: 
 313:   /**
 314:    * This method creates a new PropertyChangeListener for the JToolBar.
 315:    *
 316:    * @return A new PropertyChangeListener.
 317:    */
 318:   protected PropertyChangeListener createPropertyListener()
 319:   {
 320:     return new PropertyListener();
 321:   }
 322: 
 323:   /**
 324:    * This method creates a new rollover border for JButtons when the
 325:    * JToolBar's rollover property is set to true.
 326:    *
 327:    * @return A new rollover border.
 328:    */
 329:   protected Border createRolloverBorder()
 330:   {
 331:     return new EtchedBorderUIResource()
 332:       {
 333:     public void paintBorder(Component c, Graphics g, int x, int y,
 334:                             int width, int height)
 335:     {
 336:       if (c instanceof JButton)
 337:         {
 338:           if (((JButton) c).getModel().isRollover())
 339:         super.paintBorder(c, g, x, y, width, height);
 340:         }
 341:     }
 342:       };
 343:   }
 344: 
 345:   /**
 346:    * This method creates a new Container listener for the JToolBar.
 347:    *
 348:    * @return A new Container listener.
 349:    */
 350:   protected ContainerListener createToolBarContListener()
 351:   {
 352:     return new ToolBarContListener();
 353:   }
 354: 
 355:   /**
 356:    * This method creates a new FocusListener for the JToolBar.
 357:    *
 358:    * @return A new FocusListener for the JToolBar.
 359:    */
 360:   protected FocusListener createToolBarFocusListener()
 361:   {
 362:     return new ToolBarFocusListener();
 363:   }
 364: 
 365:   /**
 366:    * This method creates a new UI delegate for the given JComponent.
 367:    *
 368:    * @param c The JComponent to create a UI delegate for.
 369:    *
 370:    * @return A new UI delegate.
 371:    */
 372:   public static ComponentUI createUI(JComponent c)
 373:   {
 374:     return new BasicToolBarUI();
 375:   }
 376: 
 377:   /**
 378:    * This method is called to drag the DragWindow around when the JToolBar is
 379:    * being dragged around.
 380:    *
 381:    * @param position The mouse cursor coordinates relative to the JToolBar.
 382:    * @param origin The screen position of the JToolBar.
 383:    */
 384:   protected void dragTo(Point position, Point origin)
 385:   {
 386:     int loc = areaOfClick(origParent,
 387:                           SwingUtilities.convertPoint(toolBar, position,
 388:                                                       origParent));
 389: 
 390:     if (loc != -1)
 391:       {
 392:     dragWindow.setBorderColor(dockingBorderColor);
 393:     dragWindow.setBackground(dockingColor);
 394:       }
 395:     else
 396:       {
 397:     dragWindow.setBorderColor(floatingBorderColor);
 398:     dragWindow.setBackground(floatingColor);
 399:       }
 400: 
 401:     int w = 0;
 402:     int h = 0;
 403: 
 404:     boolean tmp = ((loc == SwingConstants.NORTH)
 405:                   || (loc == SwingConstants.SOUTH) || (loc == -1));
 406: 
 407:     cachedOrientation = toolBar.getOrientation();
 408:     cachedBounds = toolBar.getSize();
 409:     if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp)
 410:         || ((cachedOrientation == VERTICAL) && ! tmp))
 411:       {
 412:     w = cachedBounds.width;
 413:     h = cachedBounds.height;
 414:       }
 415:     else
 416:       {
 417:     w = cachedBounds.height;
 418:     h = cachedBounds.width;
 419:       }
 420: 
 421:     Point p = dragWindow.getOffset();
 422:     Insets insets = toolBar.getInsets();
 423: 
 424:     dragWindow.setBounds((origin.x + position.x) - p.x
 425:                          - ((insets.left + insets.right) / 2),
 426:                          (origin.y + position.y) - p.y
 427:                          - ((insets.top + insets.bottom) / 2), w, h);
 428: 
 429:     if (! dragWindow.isVisible())
 430:       dragWindow.show();
 431:   }
 432: 
 433:   /**
 434:    * This method is used at the end of a drag session to place the frame in
 435:    * either its original parent as a docked JToolBar or in its floating
 436:    * frame.
 437:    *
 438:    * @param position The position of the mouse cursor relative to the
 439:    *        JToolBar.
 440:    * @param origin The screen position of the JToolBar before the drag session
 441:    *        started.
 442:    */
 443:   protected void floatAt(Point position, Point origin)
 444:   {
 445:     Point p = new Point(position);
 446:     int aoc = areaOfClick(origParent,
 447:                           SwingUtilities.convertPoint(toolBar, p, origParent));
 448: 
 449:     Container oldParent = toolBar.getParent();
 450: 
 451:     oldParent.remove(toolBar);
 452:     oldParent.doLayout();
 453:     oldParent.repaint();
 454: 
 455:     Container newParent;
 456: 
 457:     if (aoc == -1)
 458:       newParent = ((RootPaneContainer) floatFrame).getContentPane();
 459:     else
 460:       {
 461:     floatFrame.hide();
 462:     newParent = origParent;
 463:       }
 464: 
 465:     String constraint;
 466:     switch (aoc)
 467:       {
 468:       case SwingConstants.EAST:
 469:     constraint = BorderLayout.EAST;
 470:     break;
 471:       case SwingConstants.NORTH:
 472:     constraint = BorderLayout.NORTH;
 473:     break;
 474:       case SwingConstants.SOUTH:
 475:     constraint = BorderLayout.SOUTH;
 476:     break;
 477:       case SwingConstants.WEST:
 478:     constraint = BorderLayout.WEST;
 479:     break;
 480:       default:
 481:     constraint = BorderLayout.CENTER;
 482:     break;
 483:       }
 484: 
 485:     int newOrientation = SwingConstants.HORIZONTAL;
 486:     if ((aoc != -1)
 487:         && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST)))
 488:       newOrientation = SwingConstants.VERTICAL;
 489: 
 490:     if (aoc != -1)
 491:       {
 492:     constraintBeforeFloating = constraint;
 493:     lastGoodOrientation = newOrientation;
 494:       }
 495: 
 496:     newParent.add(toolBar, constraint);
 497: 
 498:     setFloating(aoc == -1, null);
 499:     toolBar.setOrientation(newOrientation);
 500: 
 501:     Insets insets = floatFrame.getInsets();
 502:     Dimension dims = toolBar.getPreferredSize();
 503:     p = dragWindow.getOffset();
 504:     setFloatingLocation((position.x + origin.x) - p.x
 505:                         - ((insets.left + insets.right) / 2),
 506:                         (position.y + origin.y) - p.y
 507:                         - ((insets.top + insets.bottom) / 2));
 508: 
 509:     if (aoc == -1)
 510:       {
 511:     floatFrame.pack();
 512:     floatFrame.setSize(dims.width + insets.left + insets.right,
 513:                        dims.height + insets.top + insets.bottom);
 514:     floatFrame.show();
 515:       }
 516: 
 517:     newParent.invalidate();
 518:     newParent.validate();
 519:     newParent.repaint();
 520:   }
 521: 
 522:   /**
 523:    * This method returns the docking color.
 524:    *
 525:    * @return The docking color.
 526:    */
 527:   public Color getDockingColor()
 528:   {
 529:     return dockingColor;
 530:   }
 531: 
 532:   /**
 533:    * This method returns the Color which is displayed when over a floating
 534:    * area.
 535:    *
 536:    * @return The color which is displayed when over a floating area.
 537:    */
 538:   public Color getFloatingColor()
 539:   {
 540:     return floatingColor;
 541:   }
 542: 
 543:   /**
 544:    * This method returns the maximum size of the given JComponent for this UI.
 545:    *
 546:    * @param c The JComponent to find the maximum size for.
 547:    *
 548:    * @return The maximum size for this UI.
 549:    */
 550:   public Dimension getMaximumSize(JComponent c)
 551:   {
 552:     return getPreferredSize(c);
 553:   }
 554: 
 555:   /**
 556:    * This method returns the minimum size of the given JComponent for this UI.
 557:    *
 558:    * @param c The JComponent to find a minimum size for.
 559:    *
 560:    * @return The minimum size for this UI.
 561:    */
 562:   public Dimension getMinimumSize(JComponent c)
 563:   {
 564:     return getPreferredSize(c);
 565:   }
 566: 
 567:   /**
 568:    * This method installs the needed components for the JToolBar.
 569:    */
 570:   protected void installComponents()
 571:   {
 572:     floatFrame = (Window) createFloatingWindow(toolBar);
 573: 
 574:     dragWindow = createDragWindow(toolBar);
 575: 
 576:     nonRolloverBorder = createNonRolloverBorder();
 577:     rolloverBorder = createRolloverBorder();
 578: 
 579:     borders = new Hashtable();
 580: 
 581:     fillHashtable();
 582:   }
 583: 
 584:   /**
 585:    * This method installs the defaults as specified by the look and feel.
 586:    */
 587:   protected void installDefaults()
 588:   {
 589:     LookAndFeel.installBorder(toolBar, "ToolBar.border");
 590:     LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background",
 591:                                      "ToolBar.foreground", "ToolBar.font");
 592: 
 593:     dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground");
 594:     dockingColor = UIManager.getColor("ToolBar.dockingBackground");
 595: 
 596:     floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground");
 597:     floatingColor = UIManager.getColor("ToolBar.floatingBackground");
 598:     setRolloverBorders(toolBar.isRollover());
 599:   }
 600: 
 601:   /**
 602:    * This method installs the keyboard actions for the JToolBar as specified
 603:    * by the look and feel.
 604:    */
 605:   protected void installKeyboardActions()
 606:   {
 607:     // FIXME: implement.
 608:   }
 609: 
 610:   /**
 611:    * This method installs listeners for the JToolBar.
 612:    */
 613:   protected void installListeners()
 614:   {
 615:     dockingListener = createDockingListener();
 616:     toolBar.addMouseListener(dockingListener);
 617:     toolBar.addMouseMotionListener(dockingListener);
 618: 
 619:     propertyListener = createPropertyListener();
 620:     toolBar.addPropertyChangeListener(propertyListener);
 621: 
 622:     toolBarContListener = createToolBarContListener();
 623:     toolBar.addContainerListener(toolBarContListener);
 624: 
 625:     windowListener = createFrameListener();
 626:     floatFrame.addWindowListener(windowListener);
 627: 
 628:     toolBarFocusListener = createToolBarFocusListener();
 629:     toolBar.addFocusListener(toolBarFocusListener);
 630:   }
 631: 
 632:   /**
 633:    * This method installs non rollover borders for each component inside the
 634:    * given JComponent.
 635:    *
 636:    * @param c The JComponent whose children need to have non rollover borders
 637:    *        installed.
 638:    */
 639:   protected void installNonRolloverBorders(JComponent c)
 640:   {
 641:     Component[] components = toolBar.getComponents();
 642: 
 643:     for (int i = 0; i < components.length; i++)
 644:       setBorderToNonRollover(components[i]);
 645:   }
 646: 
 647:   /**
 648:    * This method installs normal (or their original) borders for each
 649:    * component inside the given JComponent.
 650:    *
 651:    * @param c The JComponent whose children need to have their original
 652:    *        borders installed.
 653:    */
 654:   protected void installNormalBorders(JComponent c)
 655:   {
 656:     Component[] components = toolBar.getComponents();
 657: 
 658:     for (int i = 0; i < components.length; i++)
 659:       setBorderToNormal(components[i]);
 660:   }
 661: 
 662:   /**
 663:    * This method install rollover borders for each component inside the given
 664:    * JComponent.
 665:    *
 666:    * @param c The JComponent whose children need to have rollover borders
 667:    *        installed.
 668:    */
 669:   protected void installRolloverBorders(JComponent c)
 670:   {
 671:     Component[] components = toolBar.getComponents();
 672: 
 673:     for (int i = 0; i < components.length; i++)
 674:       setBorderToRollover(components[i]);
 675:   }
 676: 
 677:   /**
 678:    * This method fills the borders hashtable with a list of components that
 679:    * are JButtons and their borders.
 680:    */
 681:   private void fillHashtable()
 682:   {
 683:     Component[] c = toolBar.getComponents();
 684: 
 685:     for (int i = 0; i < c.length; i++)
 686:       {
 687:     if (c[i] instanceof JButton)
 688:       {
 689:         // Don't really care about anything other than JButtons
 690:         JButton b = (JButton) c[i];
 691: 
 692:         if (b.getBorder() != null)
 693:           borders.put(b, b.getBorder());
 694:       }
 695:       }
 696:   }
 697: 
 698:   /**
 699:    * This method installs the UI for the given JComponent.
 700:    *
 701:    * @param c The JComponent to install a UI for.
 702:    */
 703:   public void installUI(JComponent c)
 704:   {
 705:     super.installUI(c);
 706: 
 707:     if (c instanceof JToolBar)
 708:       {
 709:     toolBar = (JToolBar) c;
 710:     toolBar.setOpaque(true);
 711:     installDefaults();
 712:     installComponents();
 713:     installListeners();
 714:     installKeyboardActions();
 715:       }
 716:   }
 717: 
 718:   /**
 719:    * This method returns whether the JToolBar is floating.
 720:    *
 721:    * @return Whether the JToolBar is floating.
 722:    */
 723:   public boolean isFloating()
 724:   {
 725:     return floatFrame.isVisible();
 726:   }
 727: 
 728:   /**
 729:    * This method returns whether rollover borders have been set.
 730:    *
 731:    * @return Whether rollover borders have been set.
 732:    */
 733:   public boolean isRolloverBorders()
 734:   {
 735:     return toolBar.isRollover();
 736:   }
 737: 
 738:   /**
 739:    * This method navigates in the given direction giving focus to the next
 740:    * component in the given direction.
 741:    *
 742:    * @param direction The direction to give focus to.
 743:    */
 744:   protected void navigateFocusedComp(int direction)
 745:   {
 746:     // FIXME: Implement.
 747:   }
 748: 
 749:   /**
 750:    * This method sets the border of the given component to a non rollover
 751:    * border.
 752:    *
 753:    * @param c The Component whose border needs to be set.
 754:    */
 755:   protected void setBorderToNonRollover(Component c)
 756:   {
 757:     if (c instanceof JButton)
 758:       {
 759:     JButton b = (JButton) c;
 760:     b.setRolloverEnabled(false);
 761:     b.setBorder(nonRolloverBorder);
 762:       }
 763:   }
 764: 
 765:   /**
 766:    * This method sets the border of the given component to its original value.
 767:    *
 768:    * @param c The Component whose border needs to be set.
 769:    */
 770:   protected void setBorderToNormal(Component c)
 771:   {
 772:     if (c instanceof JButton)
 773:       {
 774:     JButton b = (JButton) c;
 775:     Border border = (Border) borders.get(b);
 776:     b.setBorder(border);
 777:       }
 778:   }
 779: 
 780:   /**
 781:    * This method sets the border of the given component to a rollover border.
 782:    *
 783:    * @param c The Component whose border needs to be set.
 784:    */
 785:   protected void setBorderToRollover(Component c)
 786:   {
 787:     if (c instanceof JButton)
 788:       {
 789:     JButton b = (JButton) c;
 790:     b.setRolloverEnabled(true);
 791:     b.setBorder(rolloverBorder);
 792:       }
 793:   }
 794: 
 795:   /**
 796:    * This method sets the docking color.
 797:    *
 798:    * @param c The docking color.
 799:    */
 800:   public void setDockingColor(Color c)
 801:   {
 802:     dockingColor = c;
 803:   }
 804: 
 805:   /**
 806:    * This method sets the floating property for the JToolBar.
 807:    *
 808:    * @param b Whether the JToolBar is floating.
 809:    * @param p FIXME
 810:    */
 811:   public void setFloating(boolean b, Point p)
 812:   {
 813:     // FIXME: use p for something. It's not location
 814:     // since we already have setFloatingLocation.
 815:     floatFrame.setVisible(b);
 816:   }
 817: 
 818:   /**
 819:    * This method sets the color displayed when the JToolBar is not in a
 820:    * dockable area.
 821:    *
 822:    * @param c The floating color.
 823:    */
 824:   public void setFloatingColor(Color c)
 825:   {
 826:     floatingColor = c;
 827:   }
 828: 
 829:   /**
 830:    * This method sets the floating location of the JToolBar.
 831:    *
 832:    * @param x The x coordinate for the floating frame.
 833:    * @param y The y coordinate for the floating frame.
 834:    */
 835:   public void setFloatingLocation(int x, int y)
 836:   {
 837:     // x,y are the coordinates of the new JFrame created to store the toolbar
 838:     // XXX: The floating location is bogus is not floating.
 839:     floatFrame.setLocation(x, y);
 840:     floatFrame.invalidate();
 841:     floatFrame.validate();
 842:     floatFrame.repaint();
 843:   }
 844: 
 845:   /**
 846:    * This is a convenience method for changing the orientation of the
 847:    * JToolBar.
 848:    *
 849:    * @param orientation The new orientation.
 850:    */
 851:   public void setOrientation(int orientation)
 852:   {
 853:     toolBar.setOrientation(orientation);
 854:   }
 855: 
 856:   /**
 857:    * This method changes the child components to have rollover borders if the
 858:    * given parameter is true. Otherwise, the components are set to have non
 859:    * rollover borders.
 860:    *
 861:    * @param rollover Whether the children will have rollover borders.
 862:    */
 863:   public void setRolloverBorders(boolean rollover)
 864:   {
 865:     if (rollover)
 866:       installRolloverBorders(toolBar);
 867:     else
 868:       installNonRolloverBorders(toolBar);
 869:   }
 870: 
 871:   /**
 872:    * This method uninstall UI installed components from the JToolBar.
 873:    */
 874:   protected void uninstallComponents()
 875:   {
 876:     installNormalBorders(toolBar);
 877:     borders = null;
 878:     rolloverBorder = null;
 879:     nonRolloverBorder = null;
 880:     cachedBounds = null;
 881: 
 882:     floatFrame = null;
 883:     dragWindow = null;
 884:   }
 885: 
 886:   /**
 887:    * This method removes the defaults installed by the Look and Feel.
 888:    */
 889:   protected void uninstallDefaults()
 890:   {
 891:     toolBar.setBackground(null);
 892:     toolBar.setForeground(null);
 893:     toolBar.setFont(null);
 894: 
 895:     dockingBorderColor = null;
 896:     dockingColor = null;
 897:     floatingBorderColor = null;
 898:     floatingColor = null;
 899:   }
 900: 
 901:   /**
 902:    * This method uninstalls keyboard actions installed by the UI.
 903:    */
 904:   protected void uninstallKeyboardActions()
 905:   {
 906:     // FIXME: implement.
 907:   }
 908: 
 909:   /**
 910:    * This method uninstalls listeners installed by the UI.
 911:    */
 912:   protected void uninstallListeners()
 913:   {
 914:     toolBar.removeFocusListener(toolBarFocusListener);
 915:     toolBarFocusListener = null;
 916: 
 917:     floatFrame.removeWindowListener(windowListener);
 918:     windowListener = null;
 919: 
 920:     toolBar.removeContainerListener(toolBarContListener);
 921:     toolBarContListener = null;
 922: 
 923:     toolBar.removeMouseMotionListener(dockingListener);
 924:     toolBar.removeMouseListener(dockingListener);
 925:     dockingListener = null;
 926:   }
 927: 
 928:   /**
 929:    * This method uninstalls the UI.
 930:    *
 931:    * @param c The JComponent that is having this UI removed.
 932:    */
 933:   public void uninstallUI(JComponent c)
 934:   {
 935:     uninstallKeyboardActions();
 936:     uninstallListeners();
 937:     uninstallComponents();
 938:     uninstallDefaults();
 939:     toolBar = null;
 940:   }
 941: 
 942:   /**
 943:    * This is the MouseHandler class that allows the user to drag the JToolBar
 944:    * in and out of the parent and dock it if it can.
 945:    */
 946:   public class DockingListener implements MouseInputListener
 947:   {
 948:     /** Whether the JToolBar is being dragged. */
 949:     protected boolean isDragging;
 950: 
 951:     /**
 952:      * The origin point. This point is saved from the beginning press and is
 953:      * used until the end of the drag session.
 954:      */
 955:     protected Point origin;
 956: 
 957:     /** The JToolBar being dragged. */
 958:     protected JToolBar toolBar;
 959: 
 960:     /**
 961:      * Creates a new DockingListener object.
 962:      *
 963:      * @param t The JToolBar this DockingListener is being used for.
 964:      */
 965:     public DockingListener(JToolBar t)
 966:     {
 967:       toolBar = t;
 968:     }
 969: 
 970:     /**
 971:      * This method is called when the mouse is clicked.
 972:      *
 973:      * @param e The MouseEvent.
 974:      */
 975:     public void mouseClicked(MouseEvent e)
 976:     {
 977:       // Don't care.
 978:     }
 979: 
 980:     /**
 981:      * This method is called when the mouse is dragged. It delegates the drag
 982:      * painting to the dragTo method.
 983:      *
 984:      * @param e The MouseEvent.
 985:      */
 986:     public void mouseDragged(MouseEvent e)
 987:     {
 988:       if (isDragging)
 989:     dragTo(e.getPoint(), origin);
 990:     }
 991: 
 992:     /**
 993:      * This method is called when the mouse enters the JToolBar.
 994:      *
 995:      * @param e The MouseEvent.
 996:      */
 997:     public void mouseEntered(MouseEvent e)
 998:     {
 999:       // Don't care (yet).
1000:     }
1001: 
1002:     /**
1003:      * This method is called when the mouse exits the JToolBar.
1004:      *
1005:      * @param e The MouseEvent.
1006:      */
1007:     public void mouseExited(MouseEvent e)
1008:     {
1009:       // Don't care (yet).
1010:     }
1011: 
1012:     /**
1013:      * This method is called when the mouse is moved in the JToolBar.
1014:      *
1015:      * @param e The MouseEvent.
1016:      */
1017:     public void mouseMoved(MouseEvent e)
1018:     {
1019:       // TODO: What should be done here, if anything?
1020:     }
1021: 
1022:     /**
1023:      * This method is called when the mouse is pressed in the JToolBar. If the
1024:      * press doesn't occur in a place where it causes the JToolBar to be
1025:      * dragged, it returns. Otherwise, it starts a drag session.
1026:      *
1027:      * @param e The MouseEvent.
1028:      */
1029:     public void mousePressed(MouseEvent e)
1030:     {
1031:       if (! toolBar.isFloatable())
1032:     return;
1033: 
1034:       Point ssd = e.getPoint();
1035:       Insets insets = toolBar.getInsets();
1036: 
1037:       // Verify that this click occurs in the top inset.
1038:       if (toolBar.getOrientation() == SwingConstants.HORIZONTAL)
1039:         {
1040:       if (e.getX() > insets.left)
1041:         return;
1042:         }
1043:       else
1044:         {
1045:       if (e.getY() > insets.top)
1046:         return;
1047:         }
1048: 
1049:       origin = new Point(0, 0);
1050:       if (toolBar.isShowing())
1051:         SwingUtilities.convertPointToScreen(ssd, toolBar);
1052: 
1053:       if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource))
1054:     // Need to know who keeps the toolBar if it gets dragged back into it.
1055:     origParent = toolBar.getParent();
1056:       
1057:       if (toolBar.isShowing())
1058:         SwingUtilities.convertPointToScreen(origin, toolBar);
1059: 
1060:       isDragging = true;
1061: 
1062:       if (dragWindow != null)
1063:     dragWindow.setOffset(new Point(cachedBounds.width/2, cachedBounds.height/2));
1064: 
1065:       dragTo(e.getPoint(), origin);
1066:     }
1067: 
1068:     /**
1069:      * This method is called when the mouse is released from the JToolBar.
1070:      *
1071:      * @param e The MouseEvent.
1072:      */
1073:     public void mouseReleased(MouseEvent e)
1074:     {
1075:       if (! isDragging || ! toolBar.isFloatable())
1076:     return;
1077: 
1078:       isDragging = false;
1079:       floatAt(e.getPoint(), origin);
1080:       dragWindow.hide();
1081:     }
1082:   }
1083: 
1084:   /**
1085:    * This is the window that appears when the JToolBar is being dragged
1086:    * around.
1087:    */
1088:   protected class DragWindow extends Window
1089:   {
1090:     /**
1091:      * The current border color. It changes depending on whether the JToolBar
1092:      * is over a place that allows it to dock.
1093:      */
1094:     private Color borderColor;
1095: 
1096:     /** The between the mouse and the top left corner of the window. */
1097:     private Point offset;
1098: 
1099:     /**
1100:      * Creates a new DragWindow object.
1101:      * This is package-private to avoid an accessor method.
1102:      */
1103:     DragWindow()
1104:     {
1105:       super(owner);
1106:     }
1107: 
1108:     /**
1109:      * The color that the border should be.
1110:      *
1111:      * @return The border color.
1112:      */
1113:     public Color getBorderColor()
1114:     {
1115:       if (borderColor == null)
1116:     return Color.BLACK;
1117: 
1118:       return borderColor;
1119:     }
1120: 
1121:     /**
1122:      * This method returns the insets for the DragWindow.
1123:      *
1124:      * @return The insets for the DragWindow.
1125:      */
1126:     public Insets getInsets()
1127:     {
1128:       // This window has no decorations, so insets are empty.
1129:       return new Insets(0, 0, 0, 0);
1130:     }
1131: 
1132:     /**
1133:      * This method returns the mouse offset from the top left corner of the
1134:      * DragWindow.
1135:      *
1136:      * @return The mouse offset.
1137:      */
1138:     public Point getOffset()
1139:     {
1140:       return offset;
1141:     }
1142: 
1143:     /**
1144:      * This method paints the DragWindow.
1145:      *
1146:      * @param g The Graphics object to paint with.
1147:      */
1148:     public void paint(Graphics g)
1149:     {
1150:       //  No visiting children necessary.
1151:       Color saved = g.getColor();
1152:       Rectangle b = getBounds();
1153: 
1154:       g.setColor(getBorderColor());
1155:       g.drawRect(0, 0, b.width - 1, b.height - 1);
1156: 
1157:       g.setColor(saved);
1158:     }
1159: 
1160:     /**
1161:      * This method changes the border color.
1162:      *
1163:      * @param c The new border color.
1164:      */
1165:     public void setBorderColor(Color c)
1166:     {
1167:       borderColor = c;
1168:     }
1169: 
1170:     /**
1171:      * This method changes the mouse offset.
1172:      *
1173:      * @param p The new mouse offset.
1174:      */
1175:     public void setOffset(Point p)
1176:     {
1177:       offset = p;
1178:     }
1179: 
1180:     /**
1181:      * FIXME: Do something.
1182:      *
1183:      * @param o DOCUMENT ME!
1184:      */
1185:     public void setOrientation(int o)
1186:     {
1187:       // FIXME: implement.
1188:     }
1189:   }
1190: 
1191:   /**
1192:    * This helper class listens for Window events from the floatable window and
1193:    * if it is closed, returns the JToolBar to the last known good location.
1194:    */
1195:   protected class FrameListener extends WindowAdapter
1196:   {
1197:     /**
1198:      * This method is called when the floating window is closed.
1199:      *
1200:      * @param e The WindowEvent.
1201:      */
1202:     public void windowClosing(WindowEvent e)
1203:     {
1204:       Container parent = toolBar.getParent();
1205:       parent.remove(toolBar);
1206: 
1207:       if (origParent != null)
1208:         {
1209:       origParent.add(toolBar,
1210:                      (constraintBeforeFloating != null)
1211:                      ? constraintBeforeFloating : BorderLayout.NORTH);
1212:       toolBar.setOrientation(lastGoodOrientation);
1213:         }
1214: 
1215:       origParent.invalidate();
1216:       origParent.validate();
1217:       origParent.repaint();
1218:     }
1219:   }
1220: 
1221:   /**
1222:    * This helper class listens for PropertyChangeEvents from the JToolBar.
1223:    */
1224:   protected class PropertyListener implements PropertyChangeListener
1225:   {
1226:     /**
1227:      * This method is called when a property from the JToolBar is changed.
1228:      *
1229:      * @param e The PropertyChangeEvent.
1230:      */
1231:     public void propertyChange(PropertyChangeEvent e)
1232:     {
1233:       // FIXME: need name properties so can change floatFrame title.
1234:       if (e.getPropertyName().equals("rollover"))
1235:     setRolloverBorders(toolBar.isRollover());
1236:     }
1237:   }
1238: 
1239:   /**
1240:    * This helper class listens for components added to and removed from the
1241:    * JToolBar.
1242:    */
1243:   protected class ToolBarContListener implements ContainerListener
1244:   {
1245:     /**
1246:      * This method is responsible for setting rollover or non rollover for new
1247:      * buttons added to the JToolBar.
1248:      *
1249:      * @param e The ContainerEvent.
1250:      */
1251:     public void componentAdded(ContainerEvent e)
1252:     {
1253:       if (e.getChild() instanceof JButton)
1254:         {
1255:       JButton b = (JButton) e.getChild();
1256: 
1257:       if (b.getBorder() != null)
1258:         borders.put(b, b.getBorder());
1259:         }
1260: 
1261:       if (isRolloverBorders())
1262:     setBorderToRollover(e.getChild());
1263:       else
1264:     setBorderToNonRollover(e.getChild());
1265: 
1266:       cachedBounds = toolBar.getPreferredSize();
1267:       cachedOrientation = toolBar.getOrientation();
1268:     }
1269: 
1270:     /**
1271:      * This method is responsible for giving the child components their
1272:      * original borders when they are removed.
1273:      *
1274:      * @param e The ContainerEvent.
1275:      */
1276:     public void componentRemoved(ContainerEvent e)
1277:     {
1278:       setBorderToNormal(e.getChild());
1279:       cachedBounds = toolBar.getPreferredSize();
1280:       cachedOrientation = toolBar.getOrientation();
1281:     }
1282:   }
1283: 
1284:   /**
1285:    * This is the floating window that is returned when getFloatingWindow is
1286:    * called.
1287:    */
1288:   private class ToolBarDialog extends JDialog implements UIResource
1289:   {
1290:     /**
1291:      * Creates a new ToolBarDialog object with the name given by the JToolBar.
1292:      */
1293:     public ToolBarDialog()
1294:     {
1295:       super();
1296:       setName((toolBar.getName() != null) ? toolBar.getName() : "");
1297:     }
1298:   }
1299: 
1300:   /**
1301:    * DOCUMENT ME!
1302:    */
1303:   protected class ToolBarFocusListener implements FocusListener
1304:   {
1305:     /**
1306:      * Creates a new ToolBarFocusListener object.
1307:      */
1308:     protected ToolBarFocusListener()
1309:     {
1310:       // FIXME: implement.
1311:     }
1312: 
1313:     /**
1314:      * DOCUMENT ME!
1315:      *
1316:      * @param e DOCUMENT ME!
1317:      */
1318:     public void focusGained(FocusEvent e)
1319:     {
1320:       // FIXME: implement.
1321:     }
1322: 
1323:     /**
1324:      * DOCUMENT ME!
1325:      *
1326:      * @param e DOCUMENT ME!
1327:      */
1328:     public void focusLost(FocusEvent e)
1329:     {
1330:       // FIXME: implement.
1331:     }
1332:   }
1333: 
1334:   /**
1335:    * This helper class acts as the border for the JToolBar.
1336:    */
1337:   private static class ToolBarBorder implements Border
1338:   {
1339:     /** The size of the larger, draggable side of the border. */
1340:     private static final int offset = 10;
1341: 
1342:     /** The other sides. */
1343:     private static final int regular = 2;
1344: 
1345:     /**
1346:      * This method returns the border insets for the JToolBar.
1347:      *
1348:      * @param c The Component to find insets for.
1349:      *
1350:      * @return The border insets.
1351:      */
1352:     public Insets getBorderInsets(Component c)
1353:     {
1354:       if (c instanceof JToolBar)
1355:         {
1356:       JToolBar tb = (JToolBar) c;
1357:       int orientation = tb.getOrientation();
1358: 
1359:       if (! tb.isFloatable())
1360:         return new Insets(regular, regular, regular, regular);
1361:       else if (orientation == SwingConstants.HORIZONTAL)
1362:         return new Insets(regular, offset, regular, regular);
1363:       else
1364:         return new Insets(offset, regular, regular, regular);
1365:         }
1366: 
1367:       return new Insets(0, 0, 0, 0);
1368:     }
1369: 
1370:     /**
1371:      * This method returns whether the border is opaque.
1372:      *
1373:      * @return Whether the border is opaque.
1374:      */
1375:     public boolean isBorderOpaque()
1376:     {
1377:       return false;
1378:     }
1379: 
1380:     /**
1381:      * This method paints the ribbed area of the border.
1382:      *
1383:      * @param g The Graphics object to paint with.
1384:      * @param x The x coordinate of the area.
1385:      * @param y The y coordinate of the area.
1386:      * @param w The width of the area.
1387:      * @param h The height of the area.
1388:      * @param size The size of the bump.
1389:      * @param c The color of the bumps.
1390:      */
1391:     private void paintBumps(Graphics g, int x, int y, int w, int h, int size,
1392:                             Color c)
1393:     {
1394:       Color saved = g.getColor();
1395:       g.setColor(c);
1396: 
1397:       int hgap = 2 * size;
1398:       int vgap = 4 * size;
1399:       int count = 0;
1400: 
1401:       for (int i = x; i < (w + x); i += hgap)
1402:     for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y);
1403:          j += vgap)
1404:       g.fillRect(i, j, size, size);
1405: 
1406:       g.setColor(saved);
1407:     }
1408: 
1409:     /**
1410:      * This method paints the border around the given Component.
1411:      *
1412:      * @param c The Component whose border is being painted.
1413:      * @param g The Graphics object to paint with.
1414:      * @param x The x coordinate of the component.
1415:      * @param y The y coordinate of the component.
1416:      * @param width The width of the component.
1417:      * @param height The height of the component.
1418:      */
1419:     public void paintBorder(Component c, Graphics g, int x, int y, int width,
1420:                             int height)
1421:     {
1422:       if (c instanceof JToolBar)
1423:         {
1424:       JToolBar tb = (JToolBar) c;
1425: 
1426:       int orientation = tb.getOrientation();
1427: 
1428:       if (orientation == SwingConstants.HORIZONTAL)
1429:         {
1430:           paintBumps(g, x, y, offset, height, 1, Color.WHITE);
1431:           paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY);
1432:         }
1433:       else
1434:         {
1435:           paintBumps(g, x, y, width, offset, 1, Color.WHITE);
1436:           paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY);
1437:         }
1438:         }
1439:     }
1440:   }
1441: }