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