1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing;
  27 
  28 import java.awt.Color;
  29 import java.awt.Component;
  30 import java.awt.ComponentOrientation;
  31 import java.awt.Container;
  32 import java.awt.Dimension;
  33 import java.awt.Graphics;
  34 import java.awt.Insets;
  35 import java.awt.LayoutManager;
  36 import java.awt.LayoutManager2;
  37 import java.awt.event.*;
  38 import java.beans.*;
  39 
  40 import javax.swing.border.Border;
  41 import javax.swing.plaf.*;
  42 import javax.accessibility.*;
  43 
  44 import java.io.Serializable;
  45 import java.io.ObjectOutputStream;
  46 import java.io.ObjectInputStream;
  47 import java.io.IOException;
  48 import java.util.Hashtable;
  49 
  50 
  51 /**
  52  * <code>JToolBar</code> provides a component that is useful for
  53  * displaying commonly used <code>Action</code>s or controls.
  54  * For examples and information on using tool bars see
  55  * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html">How to Use Tool Bars</a>,
  56  * a section in <em>The Java Tutorial</em>.
  57  *
  58  * <p>
  59  * With most look and feels,
  60  * the user can drag out a tool bar into a separate window
  61  * (unless the <code>floatable</code> property is set to <code>false</code>).
  62  * For drag-out to work correctly, it is recommended that you add
  63  * <code>JToolBar</code> instances to one of the four "sides" of a
  64  * container whose layout manager is a <code>BorderLayout</code>,
  65  * and do not add children to any of the other four "sides".
  66  * <p>
  67  * <strong>Warning:</strong> Swing is not thread safe. For more
  68  * information see <a
  69  * href="package-summary.html#threading">Swing's Threading
  70  * Policy</a>.
  71  * <p>
  72  * <strong>Warning:</strong>
  73  * Serialized objects of this class will not be compatible with
  74  * future Swing releases. The current serialization support is
  75  * appropriate for short term storage or RMI between applications running
  76  * the same version of Swing.  As of 1.4, support for long term storage
  77  * of all JavaBeans&trade;
  78  * has been added to the <code>java.beans</code> package.
  79  * Please see {@link java.beans.XMLEncoder}.
  80  *
  81  * @beaninfo
  82  *   attribute: isContainer true
  83  * description: A component which displays commonly used controls or Actions.
  84  *
  85  * @author Georges Saab
  86  * @author Jeff Shapiro
  87  * @see Action
  88  */
  89 public class JToolBar extends JComponent implements SwingConstants, Accessible
  90 {
  91     /**
  92      * @see #getUIClassID
  93      * @see #readObject
  94      */
  95     private static final String uiClassID = "ToolBarUI";
  96 
  97     private    boolean   paintBorder              = true;
  98     private    Insets    margin                   = null;
  99     private    boolean   floatable                = true;
 100     private    int       orientation              = HORIZONTAL;
 101 
 102     /**
 103      * Creates a new tool bar; orientation defaults to <code>HORIZONTAL</code>.
 104      */
 105     public JToolBar()
 106     {
 107         this( HORIZONTAL );
 108     }
 109 
 110     /**
 111      * Creates a new tool bar with the specified <code>orientation</code>.
 112      * The <code>orientation</code> must be either <code>HORIZONTAL</code>
 113      * or <code>VERTICAL</code>.
 114      *
 115      * @param orientation  the orientation desired
 116      */
 117     public JToolBar( int orientation )
 118     {
 119         this(null, orientation);
 120     }
 121 
 122     /**
 123      * Creates a new tool bar with the specified <code>name</code>.  The
 124      * name is used as the title of the undocked tool bar.  The default
 125      * orientation is <code>HORIZONTAL</code>.
 126      *
 127      * @param name the name of the tool bar
 128      * @since 1.3
 129      */
 130     public JToolBar( String name ) {
 131         this(name, HORIZONTAL);
 132     }
 133 
 134     /**
 135      * Creates a new tool bar with a specified <code>name</code> and
 136      * <code>orientation</code>.
 137      * All other constructors call this constructor.
 138      * If <code>orientation</code> is an invalid value, an exception will
 139      * be thrown.
 140      *
 141      * @param name  the name of the tool bar
 142      * @param orientation  the initial orientation -- it must be
 143      *          either <code>HORIZONTAL</code> or <code>VERTICAL</code>
 144      * @exception IllegalArgumentException if orientation is neither
 145      *          <code>HORIZONTAL</code> nor <code>VERTICAL</code>
 146      * @since 1.3
 147      */
 148     public JToolBar( String name , int orientation) {
 149         setName(name);
 150         checkOrientation( orientation );
 151 
 152         this.orientation = orientation;
 153         DefaultToolBarLayout layout =  new DefaultToolBarLayout( orientation );
 154         setLayout( layout );
 155 
 156         addPropertyChangeListener( layout );
 157 
 158         updateUI();
 159     }
 160 
 161     /**
 162      * Returns the tool bar's current UI.
 163      * @see #setUI
 164      */
 165     public ToolBarUI getUI() {
 166         return (ToolBarUI)ui;
 167     }
 168 
 169     /**
 170      * Sets the L&amp;F object that renders this component.
 171      *
 172      * @param ui  the <code>ToolBarUI</code> L&amp;F object
 173      * @see UIDefaults#getUI
 174      * @beaninfo
 175      *        bound: true
 176      *       hidden: true
 177      *    attribute: visualUpdate true
 178      *  description: The UI object that implements the Component's LookAndFeel.
 179      */
 180     public void setUI(ToolBarUI ui) {
 181         super.setUI(ui);
 182     }
 183 
 184     /**
 185      * Notification from the <code>UIFactory</code> that the L&amp;F has changed.
 186      * Called to replace the UI with the latest version from the
 187      * <code>UIFactory</code>.
 188      *
 189      * @see JComponent#updateUI
 190      */
 191     public void updateUI() {
 192         setUI((ToolBarUI)UIManager.getUI(this));
 193         // GTKLookAndFeel installs a different LayoutManager, and sets it
 194         // to null after changing the look and feel, so, install the default
 195         // if the LayoutManager is null.
 196         if (getLayout() == null) {
 197             setLayout(new DefaultToolBarLayout(getOrientation()));
 198         }
 199         invalidate();
 200     }
 201 
 202 
 203 
 204     /**
 205      * Returns the name of the L&amp;F class that renders this component.
 206      *
 207      * @return the string "ToolBarUI"
 208      * @see JComponent#getUIClassID
 209      * @see UIDefaults#getUI
 210      */
 211     public String getUIClassID() {
 212         return uiClassID;
 213     }
 214 
 215 
 216     /**
 217      * Returns the index of the specified component.
 218      * (Note: Separators occupy index positions.)
 219      *
 220      * @param c  the <code>Component</code> to find
 221      * @return an integer indicating the component's position,
 222      *          where 0 is first
 223      */
 224     public int getComponentIndex(Component c) {
 225         int ncomponents = this.getComponentCount();
 226         Component[] component = this.getComponents();
 227         for (int i = 0 ; i < ncomponents ; i++) {
 228             Component comp = component[i];
 229             if (comp == c)
 230                 return i;
 231         }
 232         return -1;
 233     }
 234 
 235     /**
 236      * Returns the component at the specified index.
 237      *
 238      * @param i  the component's position, where 0 is first
 239      * @return   the <code>Component</code> at that position,
 240      *          or <code>null</code> for an invalid index
 241      *
 242      */
 243     public Component getComponentAtIndex(int i) {
 244         int ncomponents = this.getComponentCount();
 245         if ( i >= 0 && i < ncomponents) {
 246             Component[] component = this.getComponents();
 247             return component[i];
 248         }
 249         return null;
 250     }
 251 
 252      /**
 253       * Sets the margin between the tool bar's border and
 254       * its buttons. Setting to <code>null</code> causes the tool bar to
 255       * use the default margins. The tool bar's default <code>Border</code>
 256       * object uses this value to create the proper margin.
 257       * However, if a non-default border is set on the tool bar,
 258       * it is that <code>Border</code> object's responsibility to create the
 259       * appropriate margin space (otherwise this property will
 260       * effectively be ignored).
 261       *
 262       * @param m an <code>Insets</code> object that defines the space
 263       *         between the border and the buttons
 264       * @see Insets
 265       * @beaninfo
 266       * description: The margin between the tool bar's border and contents
 267       *       bound: true
 268       *      expert: true
 269       */
 270      public void setMargin(Insets m)
 271      {
 272          Insets old = margin;
 273          margin = m;
 274          firePropertyChange("margin", old, m);
 275          revalidate();
 276          repaint();
 277      }
 278 
 279      /**
 280       * Returns the margin between the tool bar's border and
 281       * its buttons.
 282       *
 283       * @return an <code>Insets</code> object containing the margin values
 284       * @see Insets
 285       */
 286      public Insets getMargin()
 287      {
 288          if(margin == null) {
 289              return new Insets(0,0,0,0);
 290          } else {
 291              return margin;
 292          }
 293      }
 294 
 295      /**
 296       * Gets the <code>borderPainted</code> property.
 297       *
 298       * @return the value of the <code>borderPainted</code> property
 299       * @see #setBorderPainted
 300       */
 301      public boolean isBorderPainted()
 302      {
 303          return paintBorder;
 304      }
 305 
 306 
 307      /**
 308       * Sets the <code>borderPainted</code> property, which is
 309       * <code>true</code> if the border should be painted.
 310       * The default value for this property is <code>true</code>.
 311       * Some look and feels might not implement painted borders;
 312       * they will ignore this property.
 313       *
 314       * @param b if true, the border is painted
 315       * @see #isBorderPainted
 316       * @beaninfo
 317       * description: Does the tool bar paint its borders?
 318       *       bound: true
 319       *      expert: true
 320       */
 321      public void setBorderPainted(boolean b)
 322      {
 323          if ( paintBorder != b )
 324          {
 325              boolean old = paintBorder;
 326              paintBorder = b;
 327              firePropertyChange("borderPainted", old, b);
 328              revalidate();
 329              repaint();
 330          }
 331      }
 332 
 333      /**
 334       * Paints the tool bar's border if the <code>borderPainted</code> property
 335       * is <code>true</code>.
 336       *
 337       * @param g  the <code>Graphics</code> context in which the painting
 338       *         is done
 339       * @see JComponent#paint
 340       * @see JComponent#setBorder
 341       */
 342      protected void paintBorder(Graphics g)
 343      {
 344          if (isBorderPainted())
 345          {
 346              super.paintBorder(g);
 347          }
 348      }
 349 
 350     /**
 351      * Gets the <code>floatable</code> property.
 352      *
 353      * @return the value of the <code>floatable</code> property
 354      *
 355      * @see #setFloatable
 356      */
 357     public boolean isFloatable()
 358     {
 359         return floatable;
 360     }
 361 
 362      /**
 363       * Sets the <code>floatable</code> property,
 364       * which must be <code>true</code> for the user to move the tool bar.
 365       * Typically, a floatable tool bar can be
 366       * dragged into a different position within the same container
 367       * or out into its own window.
 368       * The default value of this property is <code>true</code>.
 369       * Some look and feels might not implement floatable tool bars;
 370       * they will ignore this property.
 371       *
 372       * @param b if <code>true</code>, the tool bar can be moved;
 373       *          <code>false</code> otherwise
 374       * @see #isFloatable
 375       * @beaninfo
 376       * description: Can the tool bar be made to float by the user?
 377       *       bound: true
 378       *   preferred: true
 379       */
 380     public void setFloatable( boolean b )
 381     {
 382         if ( floatable != b )
 383         {
 384             boolean old = floatable;
 385             floatable = b;
 386 
 387             firePropertyChange("floatable", old, b);
 388             revalidate();
 389             repaint();
 390         }
 391     }
 392 
 393     /**
 394      * Returns the current orientation of the tool bar.  The value is either
 395      * <code>HORIZONTAL</code> or <code>VERTICAL</code>.
 396      *
 397      * @return an integer representing the current orientation -- either
 398      *          <code>HORIZONTAL</code> or <code>VERTICAL</code>
 399      * @see #setOrientation
 400      */
 401     public int getOrientation()
 402     {
 403         return this.orientation;
 404     }
 405 
 406     /**
 407      * Sets the orientation of the tool bar.  The orientation must have
 408      * either the value <code>HORIZONTAL</code> or <code>VERTICAL</code>.
 409      * If <code>orientation</code> is
 410      * an invalid value, an exception will be thrown.
 411      *
 412      * @param o  the new orientation -- either <code>HORIZONTAL</code> or
 413      *                  <code>VERTICAL</code>
 414      * @exception IllegalArgumentException if orientation is neither
 415      *          <code>HORIZONTAL</code> nor <code>VERTICAL</code>
 416      * @see #getOrientation
 417      * @beaninfo
 418      * description: The current orientation of the tool bar
 419      *       bound: true
 420      *   preferred: true
 421      *        enum: HORIZONTAL SwingConstants.HORIZONTAL
 422      *              VERTICAL   SwingConstants.VERTICAL
 423      */
 424     public void setOrientation( int o )
 425     {
 426         checkOrientation( o );
 427 
 428         if ( orientation != o )
 429         {
 430             int old = orientation;
 431             orientation = o;
 432 
 433             firePropertyChange("orientation", old, o);
 434             revalidate();
 435             repaint();
 436         }
 437     }
 438 
 439     /**
 440      * Sets the rollover state of this toolbar. If the rollover state is true
 441      * then the border of the toolbar buttons will be drawn only when the
 442      * mouse pointer hovers over them. The default value of this property
 443      * is false.
 444      * <p>
 445      * The implementation of a look and feel may choose to ignore this
 446      * property.
 447      *
 448      * @param rollover true for rollover toolbar buttons; otherwise false
 449      * @since 1.4
 450      * @beaninfo
 451      *        bound: true
 452      *    preferred: true
 453      *    attribute: visualUpdate true
 454      *  description: Will draw rollover button borders in the toolbar.
 455      */
 456     public void setRollover(boolean rollover) {
 457         putClientProperty("JToolBar.isRollover",
 458                           rollover ? Boolean.TRUE : Boolean.FALSE);
 459     }
 460 
 461     /**
 462      * Returns the rollover state.
 463      *
 464      * @return true if rollover toolbar buttons are to be drawn; otherwise false
 465      * @see #setRollover(boolean)
 466      * @since 1.4
 467      */
 468     public boolean isRollover() {
 469         Boolean rollover = (Boolean)getClientProperty("JToolBar.isRollover");
 470         if (rollover != null) {
 471             return rollover.booleanValue();
 472         }
 473         return false;
 474     }
 475 
 476     private void checkOrientation( int orientation )
 477     {
 478         switch ( orientation )
 479         {
 480             case VERTICAL:
 481             case HORIZONTAL:
 482                 break;
 483             default:
 484                 throw new IllegalArgumentException( "orientation must be one of: VERTICAL, HORIZONTAL" );
 485         }
 486     }
 487 
 488     /**
 489      * Appends a separator of default size to the end of the tool bar.
 490      * The default size is determined by the current look and feel.
 491      */
 492     public void addSeparator()
 493     {
 494         addSeparator(null);
 495     }
 496 
 497     /**
 498      * Appends a separator of a specified size to the end
 499      * of the tool bar.
 500      *
 501      * @param size the <code>Dimension</code> of the separator
 502      */
 503     public void addSeparator( Dimension size )
 504     {
 505         JToolBar.Separator s = new JToolBar.Separator( size );
 506         add(s);
 507     }
 508 
 509     /**
 510      * Adds a new <code>JButton</code> which dispatches the action.
 511      *
 512      * @param a the <code>Action</code> object to add as a new menu item
 513      * @return the new button which dispatches the action
 514      */
 515     public JButton add(Action a) {
 516         JButton b = createActionComponent(a);
 517         b.setAction(a);
 518         add(b);
 519         return b;
 520     }
 521 
 522     /**
 523      * Factory method which creates the <code>JButton</code> for
 524      * <code>Action</code>s added to the <code>JToolBar</code>.
 525      * The default name is empty if a <code>null</code> action is passed.
 526      *
 527      * @param a the <code>Action</code> for the button to be added
 528      * @return the newly created button
 529      * @see Action
 530      * @since 1.3
 531      */
 532     protected JButton createActionComponent(Action a) {
 533         JButton b = new JButton() {
 534             protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
 535                 PropertyChangeListener pcl = createActionChangeListener(this);
 536                 if (pcl==null) {
 537                     pcl = super.createActionPropertyChangeListener(a);
 538                 }
 539                 return pcl;
 540             }
 541         };
 542         if (a != null && (a.getValue(Action.SMALL_ICON) != null ||
 543                           a.getValue(Action.LARGE_ICON_KEY) != null)) {
 544             b.setHideActionText(true);
 545         }
 546         b.setHorizontalTextPosition(JButton.CENTER);
 547         b.setVerticalTextPosition(JButton.BOTTOM);
 548         return b;
 549     }
 550 
 551     /**
 552      * Returns a properly configured <code>PropertyChangeListener</code>
 553      * which updates the control as changes to the <code>Action</code> occur,
 554      * or <code>null</code> if the default
 555      * property change listener for the control is desired.
 556      *
 557      * @return <code>null</code>
 558      */
 559     protected PropertyChangeListener createActionChangeListener(JButton b) {
 560         return null;
 561     }
 562 
 563     /**
 564      * If a <code>JButton</code> is being added, it is initially
 565      * set to be disabled.
 566      *
 567      * @param comp  the component to be enhanced
 568      * @param constraints  the constraints to be enforced on the component
 569      * @param index the index of the component
 570      *
 571      */
 572     protected void addImpl(Component comp, Object constraints, int index) {
 573         if (comp instanceof Separator) {
 574             if (getOrientation() == VERTICAL) {
 575                 ( (Separator)comp ).setOrientation(JSeparator.HORIZONTAL);
 576             } else {
 577                 ( (Separator)comp ).setOrientation(JSeparator.VERTICAL);
 578             }
 579         }
 580         super.addImpl(comp, constraints, index);
 581         if (comp instanceof JButton) {
 582             ((JButton)comp).setDefaultCapable(false);
 583         }
 584     }
 585 
 586 
 587     /**
 588      * A toolbar-specific separator. An object with dimension but
 589      * no contents used to divide buttons on a tool bar into groups.
 590      */
 591     static public class Separator extends JSeparator
 592     {
 593         private Dimension separatorSize;
 594 
 595         /**
 596          * Creates a new toolbar separator with the default size
 597          * as defined by the current look and feel.
 598          */
 599         public Separator()
 600         {
 601             this( null );  // let the UI define the default size
 602         }
 603 
 604         /**
 605          * Creates a new toolbar separator with the specified size.
 606          *
 607          * @param size the <code>Dimension</code> of the separator
 608          */
 609         public Separator( Dimension size )
 610         {
 611             super( JSeparator.HORIZONTAL );
 612             setSeparatorSize(size);
 613         }
 614 
 615         /**
 616          * Returns the name of the L&amp;F class that renders this component.
 617          *
 618          * @return the string "ToolBarSeparatorUI"
 619          * @see JComponent#getUIClassID
 620          * @see UIDefaults#getUI
 621          */
 622         public String getUIClassID()
 623         {
 624             return "ToolBarSeparatorUI";
 625         }
 626 
 627         /**
 628          * Sets the size of the separator.
 629          *
 630          * @param size the new <code>Dimension</code> of the separator
 631          */
 632         public void setSeparatorSize( Dimension size )
 633         {
 634             if (size != null) {
 635                 separatorSize = size;
 636             } else {
 637                 super.updateUI();
 638             }
 639             this.invalidate();
 640         }
 641 
 642         /**
 643          * Returns the size of the separator
 644          *
 645          * @return the <code>Dimension</code> object containing the separator's
 646          *         size (This is a reference, NOT a copy!)
 647          */
 648         public Dimension getSeparatorSize()
 649         {
 650             return separatorSize;
 651         }
 652 
 653         /**
 654          * Returns the minimum size for the separator.
 655          *
 656          * @return the <code>Dimension</code> object containing the separator's
 657          *         minimum size
 658          */
 659         public Dimension getMinimumSize()
 660         {
 661             if (separatorSize != null) {
 662                 return separatorSize.getSize();
 663             } else {
 664                 return super.getMinimumSize();
 665             }
 666         }
 667 
 668         /**
 669          * Returns the maximum size for the separator.
 670          *
 671          * @return the <code>Dimension</code> object containing the separator's
 672          *         maximum size
 673          */
 674         public Dimension getMaximumSize()
 675         {
 676             if (separatorSize != null) {
 677                 return separatorSize.getSize();
 678             } else {
 679                 return super.getMaximumSize();
 680             }
 681         }
 682 
 683         /**
 684          * Returns the preferred size for the separator.
 685          *
 686          * @return the <code>Dimension</code> object containing the separator's
 687          *         preferred size
 688          */
 689         public Dimension getPreferredSize()
 690         {
 691             if (separatorSize != null) {
 692                 return separatorSize.getSize();
 693             } else {
 694                 return super.getPreferredSize();
 695             }
 696         }
 697     }
 698 
 699 
 700     /**
 701      * See <code>readObject</code> and <code>writeObject</code> in
 702      * <code>JComponent</code> for more
 703      * information about serialization in Swing.
 704      */
 705     private void writeObject(ObjectOutputStream s) throws IOException {
 706         s.defaultWriteObject();
 707         if (getUIClassID().equals(uiClassID)) {
 708             byte count = JComponent.getWriteObjCounter(this);
 709             JComponent.setWriteObjCounter(this, --count);
 710             if (count == 0 && ui != null) {
 711                 ui.installUI(this);
 712             }
 713         }
 714     }
 715 
 716 
 717     /**
 718      * Returns a string representation of this <code>JToolBar</code>.
 719      * This method
 720      * is intended to be used only for debugging purposes, and the
 721      * content and format of the returned string may vary between
 722      * implementations. The returned string may be empty but may not
 723      * be <code>null</code>.
 724      *
 725      * @return  a string representation of this <code>JToolBar</code>.
 726      */
 727     protected String paramString() {
 728         String paintBorderString = (paintBorder ?
 729                                     "true" : "false");
 730         String marginString = (margin != null ?
 731                                margin.toString() : "");
 732         String floatableString = (floatable ?
 733                                   "true" : "false");
 734         String orientationString = (orientation == HORIZONTAL ?
 735                                     "HORIZONTAL" : "VERTICAL");
 736 
 737         return super.paramString() +
 738         ",floatable=" + floatableString +
 739         ",margin=" + marginString +
 740         ",orientation=" + orientationString +
 741         ",paintBorder=" + paintBorderString;
 742     }
 743 
 744 
 745     private class DefaultToolBarLayout
 746         implements LayoutManager2, Serializable, PropertyChangeListener, UIResource {
 747 
 748         BoxLayout lm;
 749 
 750         DefaultToolBarLayout(int orientation) {
 751             if (orientation == JToolBar.VERTICAL) {
 752                 lm = new BoxLayout(JToolBar.this, BoxLayout.PAGE_AXIS);
 753             } else {
 754                 lm = new BoxLayout(JToolBar.this, BoxLayout.LINE_AXIS);
 755             }
 756         }
 757 
 758         public void addLayoutComponent(String name, Component comp) {
 759             lm.addLayoutComponent(name, comp);
 760         }
 761 
 762         public void addLayoutComponent(Component comp, Object constraints) {
 763             lm.addLayoutComponent(comp, constraints);
 764         }
 765 
 766         public void removeLayoutComponent(Component comp) {
 767             lm.removeLayoutComponent(comp);
 768         }
 769 
 770         public Dimension preferredLayoutSize(Container target) {
 771             return lm.preferredLayoutSize(target);
 772         }
 773 
 774         public Dimension minimumLayoutSize(Container target) {
 775             return lm.minimumLayoutSize(target);
 776         }
 777 
 778         public Dimension maximumLayoutSize(Container target) {
 779             return lm.maximumLayoutSize(target);
 780         }
 781 
 782         public void layoutContainer(Container target) {
 783             lm.layoutContainer(target);
 784         }
 785 
 786         public float getLayoutAlignmentX(Container target) {
 787             return lm.getLayoutAlignmentX(target);
 788         }
 789 
 790         public float getLayoutAlignmentY(Container target) {
 791             return lm.getLayoutAlignmentY(target);
 792         }
 793 
 794         public void invalidateLayout(Container target) {
 795             lm.invalidateLayout(target);
 796         }
 797 
 798         public void propertyChange(PropertyChangeEvent e) {
 799             String name = e.getPropertyName();
 800             if( name.equals("orientation") ) {
 801                 int o = ((Integer)e.getNewValue()).intValue();
 802 
 803                 if (o == JToolBar.VERTICAL)
 804                     lm = new BoxLayout(JToolBar.this, BoxLayout.PAGE_AXIS);
 805                 else {
 806                     lm = new BoxLayout(JToolBar.this, BoxLayout.LINE_AXIS);
 807                 }
 808             }
 809         }
 810     }
 811 
 812 
 813     public void setLayout(LayoutManager mgr) {
 814         LayoutManager oldMgr = getLayout();
 815         if (oldMgr instanceof PropertyChangeListener) {
 816             removePropertyChangeListener((PropertyChangeListener)oldMgr);
 817         }
 818         super.setLayout(mgr);
 819     }
 820 
 821 /////////////////
 822 // Accessibility support
 823 ////////////////
 824 
 825     /**
 826      * Gets the AccessibleContext associated with this JToolBar.
 827      * For tool bars, the AccessibleContext takes the form of an
 828      * AccessibleJToolBar.
 829      * A new AccessibleJToolBar instance is created if necessary.
 830      *
 831      * @return an AccessibleJToolBar that serves as the
 832      *         AccessibleContext of this JToolBar
 833      */
 834     public AccessibleContext getAccessibleContext() {
 835         if (accessibleContext == null) {
 836             accessibleContext = new AccessibleJToolBar();
 837         }
 838         return accessibleContext;
 839     }
 840 
 841     /**
 842      * This class implements accessibility support for the
 843      * <code>JToolBar</code> class.  It provides an implementation of the
 844      * Java Accessibility API appropriate to toolbar user-interface elements.
 845      */
 846     protected class AccessibleJToolBar extends AccessibleJComponent {
 847 
 848         /**
 849          * Get the state of this object.
 850          *
 851          * @return an instance of AccessibleStateSet containing the current
 852          * state set of the object
 853          * @see AccessibleState
 854          */
 855         public AccessibleStateSet getAccessibleStateSet() {
 856             AccessibleStateSet states = super.getAccessibleStateSet();
 857             // FIXME:  [[[WDW - need to add orientation from BoxLayout]]]
 858             // FIXME:  [[[WDW - need to do SELECTABLE if SelectionModel is added]]]
 859             return states;
 860         }
 861 
 862         /**
 863          * Get the role of this object.
 864          *
 865          * @return an instance of AccessibleRole describing the role of the object
 866          */
 867         public AccessibleRole getAccessibleRole() {
 868             return AccessibleRole.TOOL_BAR;
 869         }
 870     } // inner class AccessibleJToolBar
 871 }