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