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