Source for javax.swing.plaf.basic.BasicToolBarUI

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