Source for javax.swing.JToolBar

   1: /* JToolBar.java --
   2:    Copyright (C) 2002, 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;
  40: 
  41: import java.awt.Component;
  42: import java.awt.Container;
  43: import java.awt.Dimension;
  44: import java.awt.Graphics;
  45: import java.awt.Insets;
  46: import java.awt.LayoutManager;
  47: import java.beans.PropertyChangeListener;
  48: 
  49: import javax.accessibility.Accessible;
  50: import javax.accessibility.AccessibleContext;
  51: import javax.accessibility.AccessibleRole;
  52: import javax.accessibility.AccessibleStateSet;
  53: import javax.swing.JButton;
  54: import javax.swing.plaf.ToolBarUI;
  55: 
  56: /**
  57:  * JToolBar is a component that provides a toolbar to Swing programs. Users
  58:  * can add buttons (or actions that will be represented by JButtons) as well
  59:  * as other components to the JToolBar. JToolBars can be dragged in and out
  60:  * of their parent components. If the JToolBar is dragged out of the parent,
  61:  * then it will be displayed in its own RootPaneContainer. For dragging to
  62:  * work properly, JToolBars need to be placed in a Container that has a
  63:  * BorderLayout. That parent Container cannot have components in the NORTH,
  64:  * EAST, SOUTH,  or WEST components (that is not the JToolBar).
  65:  */
  66: public class JToolBar extends JComponent implements SwingConstants, Accessible
  67: {
  68:   /**
  69:    * AccessibleJToolBar
  70:    */
  71:   // FIXME: This inner class is a complete stub and must be implemented
  72:   // properly.
  73:   protected class AccessibleJToolBar extends AccessibleJComponent
  74:   {
  75:     /** DOCUMENT ME! */
  76:     private static final long serialVersionUID = -5516888265903814215L;
  77: 
  78:     /**
  79:      * Constructor AccessibleJToolBar
  80:      */
  81:     protected AccessibleJToolBar()
  82:     {
  83:       // Nothing to do here.
  84:     }
  85: 
  86:     /**
  87:      * getAccessibleStateSet
  88:      *
  89:      * @return AccessibleStateSet
  90:      */
  91:     public AccessibleStateSet getAccessibleStateSet()
  92:     {
  93:       return null; // TODO
  94:     }
  95: 
  96:     /**
  97:      * getAccessibleRole
  98:      *
  99:      * @return AccessibleRole
 100:      */
 101:     public AccessibleRole getAccessibleRole()
 102:     {
 103:       return AccessibleRole.TOOL_BAR;
 104:     }
 105:   }
 106: 
 107:   /**
 108:    * This is the private JToolBar layout manager.
 109:    */
 110:   private class DefaultToolBarLayout implements LayoutManager
 111:   {
 112:     /**
 113:      * This method is called when a new component is added to the container.
 114:      *
 115:      * @param name The name of the component added.
 116:      * @param comp The component that was added.
 117:      */
 118:     public void addLayoutComponent(String name, Component comp)
 119:     {
 120:       // Do nothing.
 121:     }
 122: 
 123:     /**
 124:      * This method is called to lay out the given container  to position and
 125:      * size the child components.
 126:      *
 127:      * @param c The container to lay out.
 128:      *
 129:      * @throws Error DOCUMENT ME!
 130:      */
 131:     public void layoutContainer(Container c)
 132:     {
 133:       if (! (c instanceof JToolBar))
 134:     throw new Error("DefaultToolBarLayout can only be used on JToolBars.");
 135:       Insets insets = getInsets();
 136:       Insets margin = getMargin();
 137:       int middle;
 138:       if (margin != null)
 139:         {
 140:       insets.left += margin.left;
 141:       insets.top += margin.top;
 142:       insets.bottom += margin.bottom;
 143:       insets.right += margin.right;
 144:         }
 145:       Component[] components = c.getComponents();
 146:       Dimension tdims = c.getSize();
 147:       int start = 0;
 148:       Dimension pref;
 149: 
 150:       if (getOrientation() == SwingUtilities.HORIZONTAL)
 151:         {
 152:       start += insets.left;
 153:       for (int i = 0; i < components.length; i++)
 154:         {
 155:           if (components[i] != null && components[i].isVisible())
 156:             {
 157:           pref = components[i].getPreferredSize();
 158:           if (pref != null)
 159:             {
 160:               middle = (tdims.height - pref.height) / 2;
 161:               components[i].setBounds(start, middle, pref.width,
 162:                                       pref.height);
 163:               start += pref.width;
 164:             }
 165:             }
 166:         }
 167:         }
 168:       else
 169:         {
 170:       start += insets.top;
 171:       for (int i = 0; i < components.length; i++)
 172:         {
 173:           if (components[i] != null && components[i].isVisible())
 174:             {
 175:           pref = components[i].getPreferredSize();
 176:           if (pref != null)
 177:             {
 178:               middle = (tdims.width - pref.width) / 2;
 179:               components[i].setBounds(middle, start, pref.width,
 180:                                       pref.height);
 181:               start += pref.height;
 182:             }
 183:             }
 184:         }
 185:         }
 186:     }
 187: 
 188:     /**
 189:      * This method returns the minimum size of the given container given the
 190:      * child components.
 191:      *
 192:      * @param parent The container to measure.
 193:      *
 194:      * @return The minimum size of the given container.
 195:      */
 196:     public Dimension minimumLayoutSize(Container parent)
 197:     {
 198:       return preferredLayoutSize(parent);
 199:     }
 200: 
 201:     /**
 202:      * This method returns the preferred size of the given container given the
 203:      * child components.
 204:      *
 205:      * @param parent The container to measure.
 206:      *
 207:      * @return The preferred size of the given container.
 208:      */
 209:     public Dimension preferredLayoutSize(Container parent)
 210:     {
 211:       int orientation = getOrientation();
 212:       Component[] components = getComponents();
 213: 
 214:       int limit = 0;
 215:       int total = 0;
 216:       Dimension dims;
 217: 
 218:       int w = 0;
 219:       int h = 0;
 220: 
 221:       if (orientation == SwingConstants.HORIZONTAL)
 222:         {
 223:       for (int i = 0; i < components.length; i++)
 224:         {
 225:           dims = components[i].getPreferredSize();
 226:           if (dims != null)
 227:             {
 228:           if (dims.height > limit)
 229:             limit = dims.height;
 230:           total += dims.width;
 231:             }
 232:         }
 233:       w = total;
 234:       h = limit;
 235:         }
 236:       else
 237:         {
 238:       for (int i = 0; i < components.length; i++)
 239:         {
 240:           dims = components[i].getPreferredSize();
 241:           if (dims != null)
 242:             {
 243:           if (dims.width > limit)
 244:             limit = dims.width;
 245:           total += dims.height;
 246:             }
 247:         }
 248:       w = limit;
 249:       h = total;
 250:         }
 251: 
 252:       Insets insets = getInsets();
 253:       w += insets.left + insets.right;
 254:       h += insets.top + insets.bottom;
 255: 
 256:       Insets margin = getMargin();
 257:       if (margin != null)
 258:         {
 259:       w += margin.left + margin.right;
 260:       h += margin.top + margin.bottom;
 261:         }
 262: 
 263:       return new Dimension(w, h);
 264:     }
 265: 
 266:     /**
 267:      * This method is called when the given component  is removed from the
 268:      * container.
 269:      *
 270:      * @param comp The component removed.
 271:      */
 272:     public void removeLayoutComponent(Component comp)
 273:     {
 274:       // Do nothing.
 275:     }
 276:   }
 277: 
 278:   /**
 279:    * This is an extension of JSeparator used in toolbars. Unlike JSeparator,
 280:    * nothing is painted for this Separator, it is only blank space that
 281:    * separates components.
 282:    */
 283:   public static class Separator extends JSeparator
 284:   {
 285:     /** DOCUMENT ME! */
 286:     private static final long serialVersionUID = -1656745644823105219L;
 287: 
 288:     /**
 289:      * Creates a new Separator object.
 290:      */
 291:     public Separator()
 292:     {
 293:       super();
 294:     } // Separator()
 295: 
 296:     /**
 297:      * Creates a new Separator object with the given size.
 298:      *
 299:      * @param size The size of the separator.
 300:      */
 301:     public Separator(Dimension size)
 302:     {
 303:       setPreferredSize(size);
 304:     } // Separator()
 305: 
 306:     /**
 307:      * This method returns the String ID of the UI class of  Separator.
 308:      *
 309:      * @return The UI class' String ID.
 310:      */
 311:     public String getUIClassID()
 312:     {
 313:       return "ToolBarSeparatorUI";
 314:     } // getUIClassID()
 315: 
 316:     /**
 317:      * This method returns the preferred size of the Separator.
 318:      *
 319:      * @return The preferred size of the Separator.
 320:      */
 321:     public Dimension getPreferredSize()
 322:     {
 323:       return super.getPreferredSize();
 324:     } // getPreferredSize()
 325: 
 326:     /**
 327:      * This method returns the maximum size of the Separator.
 328:      *
 329:      * @return The maximum size of the Separator.
 330:      */
 331:     public Dimension getMaximumSize()
 332:     {
 333:       return super.getPreferredSize();
 334:     } // getMaximumSize()
 335: 
 336:     /**
 337:      * This method returns the minimum size of the Separator.
 338:      *
 339:      * @return The minimum size of the Separator.
 340:      */
 341:     public Dimension getMinimumSize()
 342:     {
 343:       return super.getPreferredSize();
 344:     } // getMinimumSize()
 345: 
 346:     /**
 347:      * This method returns the size of the Separator.
 348:      *
 349:      * @return The size of the Separator.
 350:      */
 351:     public Dimension getSeparatorSize()
 352:     {
 353:       return super.getPreferredSize();
 354:     } // getSeparatorSize()
 355: 
 356:     /**
 357:      * This method sets the size of the Separator.
 358:      *
 359:      * @param size The new size of the Separator.
 360:      */
 361:     public void setSeparatorSize(Dimension size)
 362:     {
 363:       setPreferredSize(size);
 364:     } // setSeparatorSize()
 365:   } // Separator
 366: 
 367:   /** DOCUMENT ME! */
 368:   private static final long serialVersionUID = -1269915519555129643L;
 369: 
 370:   /** Whether the JToolBar paints its border. */
 371:   private transient boolean paintBorder = true;
 372: 
 373:   /** The extra insets around the JToolBar. */
 374:   private transient Insets margin;
 375: 
 376:   /** Whether the JToolBar can float (and be dragged around). */
 377:   private transient boolean floatable = true;
 378: 
 379:   /** Whether the buttons will have rollover borders. */
 380:   private transient boolean rollover;
 381: 
 382:   /** The orientation of the JToolBar. */
 383:   private int orientation = HORIZONTAL;
 384: 
 385:   /**
 386:    * This method creates a new JToolBar object with horizontal orientation
 387:    * and no name.
 388:    */
 389:   public JToolBar()
 390:   {
 391:     this(null, HORIZONTAL);
 392:   } // JToolBar()
 393: 
 394:   /**
 395:    * This method creates a new JToolBar with the given orientation and  no
 396:    * name.
 397:    *
 398:    * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL)
 399:    */
 400:   public JToolBar(int orientation)
 401:   {
 402:     this(null, orientation);
 403:   } // JToolBar()
 404: 
 405:   /**
 406:    * This method creates a new JToolBar object with the given name and
 407:    * horizontal orientation.
 408:    *
 409:    * @param name Name assigned to undocked tool bar.
 410:    */
 411:   public JToolBar(String name)
 412:   {
 413:     this(name, HORIZONTAL);
 414:   } // JToolBar()
 415: 
 416:   /**
 417:    * This method creates a new JToolBar object with the given name and
 418:    * orientation.
 419:    *
 420:    * @param name Name assigned to undocked tool bar.
 421:    * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL)
 422:    */
 423:   public JToolBar(String name, int orientation)
 424:   {
 425:     setName(name);
 426:     setOrientation(orientation);
 427:     setLayout(new DefaultToolBarLayout());
 428:     revalidate();
 429:     updateUI();
 430:   } // JToolBar()
 431: 
 432:   /**
 433:    * This method adds a new JButton that performs the given Action to the
 434:    * JToolBar.
 435:    *
 436:    * @param action The Action to add to the JToolBar.
 437:    *
 438:    * @return The JButton that wraps the Action.
 439:    */
 440:   public JButton add(Action action)
 441:   {
 442:     JButton b = createActionComponent(action);
 443:     add(b);
 444:     return b;
 445:   } // add()
 446: 
 447:   /**
 448:    * This method paints the border if the borderPainted property is true.
 449:    *
 450:    * @param graphics The graphics object to paint with.
 451:    */
 452:   protected void paintBorder(Graphics graphics)
 453:   {
 454:     if (paintBorder && isFloatable())
 455:       super.paintBorder(graphics);
 456:   } // paintBorder()
 457: 
 458:   /**
 459:    * This method returns the UI class used to paint this JToolBar.
 460:    *
 461:    * @return The UI class for this JToolBar.
 462:    */
 463:   public ToolBarUI getUI()
 464:   {
 465:     return (ToolBarUI) ui;
 466:   } // getUI()
 467: 
 468:   /**
 469:    * This method sets the UI used with the JToolBar.
 470:    *
 471:    * @param ui The UI used with the JToolBar.
 472:    */
 473:   public void setUI(ToolBarUI ui)
 474:   {
 475:     super.setUI(ui);
 476:   } // setUI()
 477: 
 478:   /**
 479:    * This method resets the UI used to the Look and Feel defaults.
 480:    */
 481:   public void updateUI()
 482:   {
 483:     setUI((ToolBarUI) UIManager.getUI(this));
 484:     revalidate();
 485:     repaint();
 486:   } // updateUI()
 487: 
 488:   /**
 489:    * This method returns the String identifier for the UI class to the used
 490:    * with the JToolBar.
 491:    *
 492:    * @return The String identifier for the UI class.
 493:    */
 494:   public String getUIClassID()
 495:   {
 496:     return "ToolBarUI";
 497:   } // getUIClassID()
 498: 
 499:   /**
 500:    * This method sets the rollover property for the JToolBar. In rollover
 501:    * mode, JButtons inside the JToolBar will only display their borders when
 502:    * the mouse is moving over them.
 503:    *
 504:    * @param b The new rollover property.
 505:    */
 506:   public void setRollover(boolean b)
 507:   {
 508:     if (b != rollover)
 509:       {
 510:     rollover = b;
 511:     firePropertyChange("rollover", ! rollover, rollover);
 512:     revalidate();
 513:     repaint();
 514:       }
 515:   }
 516: 
 517:   /**
 518:    * This method returns the rollover property.
 519:    *
 520:    * @return The rollover property.
 521:    */
 522:   public boolean isRollover()
 523:   {
 524:     return rollover;
 525:   }
 526: 
 527:   /**
 528:    * This method returns the index of the given component.
 529:    *
 530:    * @param component The component to find.
 531:    *
 532:    * @return The index of the given component.
 533:    */
 534:   public int getComponentIndex(Component component)
 535:   {
 536:     Component[] components = getComponents();
 537:     if (components == null)
 538:       return -1;
 539: 
 540:     for (int i = 0; i < components.length; i++)
 541:       if (components[i] == component)
 542:     return i;
 543: 
 544:     return -1;
 545:   } // getComponentIndex()
 546: 
 547:   /**
 548:    * This method returns the component at the given index.
 549:    *
 550:    * @param index The index of the component.
 551:    *
 552:    * @return The component at the given index.
 553:    */
 554:   public Component getComponentAtIndex(int index)
 555:   {
 556:     return getComponent(index);
 557:   } // getComponentAtIndex()
 558: 
 559:   /**
 560:    * This method returns the margin property.
 561:    *
 562:    * @return The margin property.
 563:    */
 564:   public Insets getMargin()
 565:   {
 566:     return margin;
 567:   } // getMargin()
 568: 
 569:   /**
 570:    * This method sets the margin property. The margin property determines the
 571:    * extra space between the children components of the JToolBar and the
 572:    * border.
 573:    *
 574:    * @param margin The margin property.
 575:    */
 576:   public void setMargin(Insets margin)
 577:   {
 578:     if ((this.margin != null && margin == null)
 579:         || (this.margin == null && margin != null)
 580:         || (margin != null && this.margin != null
 581:         && (margin.left != this.margin.left
 582:         || margin.right != this.margin.right || margin.top != this.margin.top
 583:         || margin.bottom != this.margin.bottom)))
 584:       {
 585:     Insets oldMargin = this.margin;
 586:     this.margin = margin;
 587:     firePropertyChange("margin", oldMargin, this.margin);
 588:     revalidate();
 589:     repaint();
 590:       }
 591:   } // setMargin()
 592: 
 593:   /**
 594:    * This method returns the borderPainted property.
 595:    *
 596:    * @return The borderPainted property.
 597:    */
 598:   public boolean isBorderPainted()
 599:   {
 600:     return paintBorder;
 601:   } // isBorderPainted()
 602: 
 603:   /**
 604:    * This method sets the borderPainted property. If set to false, the border
 605:    * will not be painted.
 606:    *
 607:    * @param painted Whether the border will be painted.
 608:    */
 609:   public void setBorderPainted(boolean painted)
 610:   {
 611:     if (painted != paintBorder)
 612:       {
 613:     paintBorder = painted;
 614:     firePropertyChange("borderPainted", ! paintBorder,
 615:                        paintBorder);
 616:     repaint();
 617:       }
 618:   } // setBorderPainted()
 619: 
 620:   /**
 621:    * This method returns the floatable property.
 622:    *
 623:    * @return The floatable property.
 624:    */
 625:   public boolean isFloatable()
 626:   {
 627:     return floatable;
 628:   } // isFloatable()
 629: 
 630:   /**
 631:    * This method sets the floatable property. If set to false, the JToolBar
 632:    * cannot be dragged.
 633:    *
 634:    * @param floatable Whether the JToolBar can be dragged.
 635:    */
 636:   public void setFloatable(boolean floatable)
 637:   {
 638:     if (floatable != this.floatable)
 639:       {
 640:     this.floatable = floatable;
 641:     firePropertyChange("floatable", ! floatable, floatable);
 642:       }
 643:   } // setFloatable()
 644: 
 645:   /**
 646:    * This method returns the orientation of the JToolBar.
 647:    *
 648:    * @return The orientation of the JToolBar.
 649:    */
 650:   public int getOrientation()
 651:   {
 652:     return orientation;
 653:   } // getOrientation()
 654: 
 655:   /**
 656:    * This method sets the layout manager to be used with the JToolBar.
 657:    *
 658:    * @param mgr The Layout Manager used with the JToolBar.
 659:    */
 660:   public void setLayout(LayoutManager mgr)
 661:   {
 662:     super.setLayout(mgr);
 663:     revalidate();
 664:     repaint();
 665:   } // setLayout()
 666: 
 667:   /**
 668:    * This method sets the orientation property for JToolBar.
 669:    *
 670:    * @param orientation The new orientation for JToolBar.
 671:    *
 672:    * @throws IllegalArgumentException If the orientation is not HORIZONTAL or
 673:    *         VERTICAL.
 674:    */
 675:   public void setOrientation(int orientation)
 676:   {
 677:     if (orientation != HORIZONTAL && orientation != VERTICAL)
 678:       throw new IllegalArgumentException(orientation
 679:                                          + " is not a legal orientation");
 680:     if (orientation != this.orientation)
 681:       {
 682:     int oldOrientation = this.orientation;
 683:     this.orientation = orientation;
 684:     firePropertyChange("orientation", oldOrientation, this.orientation);
 685:     revalidate();
 686:     repaint();
 687:       }
 688:   } // setOrientation()
 689: 
 690:   /**
 691:    * This method adds a Separator of default size to the JToolBar.
 692:    */
 693:   public void addSeparator()
 694:   {
 695:     add(new Separator());
 696:   } // addSeparator()
 697: 
 698:   /**
 699:    * This method adds a Separator with the given size to the JToolBar.
 700:    *
 701:    * @param size The size of the Separator.
 702:    */
 703:   public void addSeparator(Dimension size)
 704:   {
 705:     add(new Separator(size));
 706:   } // addSeparator()
 707: 
 708:   /**
 709:    * This method is used to create JButtons which can be added to the JToolBar
 710:    * for the given action.
 711:    *
 712:    * @param action The action to create a JButton for.
 713:    *
 714:    * @return The JButton created from the action.
 715:    */
 716:   protected JButton createActionComponent(Action action)
 717:   {
 718:     return new JButton(action);
 719:   } // createActionComponent()
 720: 
 721:   /**
 722:    * This method creates a pre-configured PropertyChangeListener which updates
 723:    * the control as changes are made to the Action. However, this is no
 724:    * longer the recommended way of adding Actions to Containers. As such,
 725:    * this method returns null.
 726:    *
 727:    * @param button The JButton to configure a PropertyChangeListener for.
 728:    *
 729:    * @return null.
 730:    */
 731:   protected PropertyChangeListener createActionChangeListener(JButton button)
 732:   {
 733:     // XXX: As specified, this returns null. But seems kind of strange, usually deprecated methods don't just return null, verify!
 734:     return null;
 735:   } // createActionChangeListener()
 736: 
 737:   /**
 738:    * This method overrides Container's addImpl method. If a JButton is added,
 739:    * it is disabled.
 740:    *
 741:    * @param component The Component to add.
 742:    * @param constraints The Constraints placed on the component.
 743:    * @param index The index to place the Component at.
 744:    */
 745:   protected void addImpl(Component component, Object constraints, int index)
 746:   {
 747:     // XXX: Sun says disable button but test cases show otherwise.
 748:     super.addImpl(component, constraints, index);
 749: 
 750:     // if we added a Swing Button then adjust this a little
 751:     if (component instanceof AbstractButton)
 752:       {
 753:         AbstractButton b = (AbstractButton) component;
 754:         b.setRolloverEnabled(rollover);
 755:       }
 756: 
 757:   } // addImpl()
 758: 
 759:   /**
 760:    * This method returns a String description of the JToolBar.
 761:    *
 762:    * @return A String description of the JToolBar.
 763:    */
 764:   protected String paramString()
 765:   {
 766:     return "JToolBar";
 767:   } // paramString()
 768: 
 769:   /**
 770:    * getAccessibleContext
 771:    *
 772:    * @return AccessibleContext
 773:    */
 774:   public AccessibleContext getAccessibleContext()
 775:   {
 776:     if (accessibleContext == null)
 777:       accessibleContext = new AccessibleJToolBar();
 778: 
 779:     return accessibleContext;
 780:   }
 781: }