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