- /*
 - * @(#)JToolBar.java 1.88 00/04/06
 - *
 - * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package javax.swing;
 - import java.awt.Color;
 - import java.awt.Component;
 - import java.awt.Dimension;
 - import java.awt.Graphics;
 - import java.awt.Insets;
 - import java.awt.FlowLayout;
 - import java.awt.event.*;
 - import java.beans.*;
 - import javax.swing.border.Border;
 - import javax.swing.plaf.*;
 - import javax.accessibility.*;
 - import java.io.Serializable;
 - import java.io.ObjectOutputStream;
 - import java.io.ObjectInputStream;
 - import java.io.IOException;
 - import java.util.Hashtable;
 - /**
 - * <code>JToolBar</code> provides a component that is useful for
 - * displaying commonly used <code>Action</code>s or controls.
 - * For examples and information on using tool bars see
 - * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/toolbar.html">How to Use Tool Bars</a>,
 - * a section in <em>The Java Tutorial</em>.
 - *
 - * <p>
 - * A tool bar can be dragged out into a separate window
 - * by the user (unless the floatable property is set to false). In order
 - * for drag-out to work correctly, it is recommended that you add
 - * <code>JToolBar</code> instances to one of the four 'sides' of a
 - * container whose layout manager is a <code>BorderLayout</code>,
 - * and do not add children to any of the other four 'sides'.
 - * <p>
 - * For the keyboard keys used by this component in the standard Look and
 - * Feel (L&F) renditions, see the
 - * <a href="doc-files/Key-Index.html#JToolBar">JToolBar</a> key assignments.
 - * <p>
 - * <strong>Warning:</strong>
 - * Serialized objects of this class will not be compatible with
 - * future Swing releases. The current serialization support is appropriate
 - * for short term storage or RMI between applications running the same
 - * version of Swing. A future release of Swing will provide support for
 - * long term persistence.
 - *
 - * @beaninfo
 - * attribute: isContainer true
 - * description: A component which displays commonly used controls or Actions.
 - *
 - * @version 1.88 04/06/00
 - * @author Georges Saab
 - * @author Jeff Shapiro
 - * @see Action
 - */
 - public class JToolBar extends JComponent implements SwingConstants, Accessible
 - {
 - /**
 - * @see #getUIClassID
 - * @see #readObject
 - */
 - private static final String uiClassID = "ToolBarUI";
 - private boolean paintBorder = true;
 - private Insets margin = null;
 - private boolean floatable = true;
 - private int orientation = HORIZONTAL;
 - /**
 - * Creates a new toolbar; orientation defaults to <code>HORIZONTAL</code>.
 - */
 - public JToolBar()
 - {
 - this( HORIZONTAL );
 - }
 - /**
 - * Creates a new toolbar with the specified <code>orientation.
 - * The <code>orientation</code> must be either <code>HORIZONTAL</code>
 - * or <code>VERTICAL</code>.
 - *
 - * @param orientation the orientation desired
 - */
 - public JToolBar( int orientation )
 - {
 - this(null, orientation);
 - }
 - /**
 - * Creates a new toolbar with the specified <code>name</code>. The
 - * name is used as the title of the undocked toolbar. The default
 - * orientation is <code>HORIZONTAL</code>.
 - *
 - * @param name the name of the toolbar
 - * @since 1.3
 - */
 - public JToolBar( String name ) {
 - this(name, HORIZONTAL);
 - }
 - /**
 - * Creates a new toolbar with a specified <code>name</code> and
 - * <code>orientation</code>.
 - * All other constructors call this constructor.
 - * If <code>orientation</code> is an invalid value, an exception will
 - * be thrown.
 - *
 - * @param name the name of the toolbar
 - * @param orientation the initial orientation -- it must be
 - * either <code>HORIZONTAL</code> or <code>VERTICAL</code>
 - * @exception IllegalArgumentException if orientation is neither
 - * <code>HORIZONTAL</code> nor <code>VERTICAL</code>
 - * @since 1.3
 - */
 - public JToolBar( String name , int orientation) {
 - setName(name);
 - checkOrientation( orientation );
 - this.orientation = orientation;
 - if ( orientation == VERTICAL )
 - {
 - this.setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
 - }
 - else
 - {
 - if( SwingUtilities.isLeftToRight(this) ) {
 - this.setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
 - } else {
 - this.setLayout( new RightToLeftToolBarLayout() );
 - }
 - }
 - addPropertyChangeListener( new PropertyChangeHandler() );
 - updateUI();
 - }
 - /**
 - * Returns the toolbar's current UI.
 - * @see #setUI
 - */
 - public ToolBarUI getUI() {
 - return (ToolBarUI)ui;
 - }
 - /**
 - * Sets the L&F object that renders this component.
 - *
 - * @param ui the <code>ToolBarUI</code> L&F object
 - * @see UIDefaults#getUI
 - * @beaninfo
 - * description: The menu item's UI delegate
 - * bound: true
 - * expert: true
 - * hidden: true
 - */
 - public void setUI(ToolBarUI ui) {
 - super.setUI(ui);
 - }
 - /**
 - * Notification from the <code>UIFactory</code> that the L&F has changed.
 - * Called to replace the UI with the latest version from the
 - * <code>UIFactory</code>.
 - *
 - * @see JComponent#updateUI
 - */
 - public void updateUI() {
 - setUI((ToolBarUI)UIManager.getUI(this));
 - invalidate();
 - }
 - /**
 - * Returns the name of the L&F class that renders this component.
 - *
 - * @return the string "ToolBarUI"
 - * @see JComponent#getUIClassID
 - * @see UIDefaults#getUI
 - */
 - public String getUIClassID() {
 - return uiClassID;
 - }
 - /**
 - * Returns the index of the specified component.
 - * (Note: Separators occupy index positions.)
 - *
 - * @param c the <code>Component</code> to find
 - * @return an integer indicating the component's position,
 - * where 0 is first
 - */
 - public int getComponentIndex(Component c) {
 - int ncomponents = this.getComponentCount();
 - Component[] component = this.getComponents();
 - for (int i = 0 ; i < ncomponents ; i++) {
 - Component comp = component[i];
 - if (comp == c)
 - return i;
 - }
 - return -1;
 - }
 - /**
 - * Returns the component at the specified index.
 - *
 - * @param i the component's position, where 0 is first
 - * @return the <code>Component</code> at that position,
 - * or <code>null</code> for an invalid index
 - *
 - */
 - public Component getComponentAtIndex(int i) {
 - int ncomponents = this.getComponentCount();
 - if ( i >= 0 && i < ncomponents) {
 - Component[] component = this.getComponents();
 - return component[i];
 - }
 - return null;
 - }
 - /**
 - * Sets the margin between the toolbar's border and
 - * its buttons. Setting to <code>null</code> causes the toolbar to
 - * use the default margins. The toolbar's default <code>Border</code>
 - * object uses this value to create the proper margin.
 - * However, if a non-default border is set on the toolbar,
 - * it is that <code>Border</code> object's responsibility to create the
 - * appropriate margin space (otherwise this property will
 - * effectively be ignored).
 - *
 - * @param m an <code>Insets</code> object that defines the space
 - * between the border and the buttons
 - * @see Insets
 - * @beaninfo
 - * description: The margin between the toolbar's border and contents
 - * bound: true
 - * expert: true
 - */
 - public void setMargin(Insets m)
 - {
 - Insets old = margin;
 - margin = m;
 - firePropertyChange("margin", old, m);
 - revalidate();
 - repaint();
 - }
 - /**
 - * Returns the margin between the toolbar's border and
 - * its buttons.
 - *
 - * @return an <code>Insets</code> object containing the margin values
 - * @see Insets
 - */
 - public Insets getMargin()
 - {
 - if(margin == null) {
 - return new Insets(0,0,0,0);
 - } else {
 - return margin;
 - }
 - }
 - /**
 - * Checks whether the border should be painted.
 - *
 - * @return true if the border should be painted, else false
 - * @see #setBorderPainted
 - */
 - public boolean isBorderPainted()
 - {
 - return paintBorder;
 - }
 - /**
 - * Sets whether the border should be painted.
 - *
 - * @param b if true, the border is painted
 - * @see #isBorderPainted
 - * @beaninfo
 - * description: Does the toolbar paint its borders?
 - * bound: true
 - * expert: true
 - */
 - public void setBorderPainted(boolean b)
 - {
 - if ( paintBorder != b )
 - {
 - boolean old = paintBorder;
 - paintBorder = b;
 - firePropertyChange("borderPainted", old, b);
 - revalidate();
 - repaint();
 - }
 - }
 - /**
 - * Paint the toolbar's border if <code>BorderPainted</code> property
 - * is true.
 - *
 - * @param g the <code>Graphics</code> context in which the painting
 - * is done
 - * @see JComponent#paint
 - * @see JComponent#setBorder
 - */
 - protected void paintBorder(Graphics g)
 - {
 - if (isBorderPainted())
 - {
 - super.paintBorder(g);
 - }
 - }
 - /**
 - * Returns true if the <code>JToolbar</code> can be dragged out by the user.
 - *
 - * @return true if the <code>JToolbar</code> can be dragged
 - * out by the user, false otherwise
 - */
 - public boolean isFloatable()
 - {
 - return floatable;
 - }
 - /**
 - * Sets whether the toolbar can be made to float.
 - *
 - * @param b if true, the toolbar can be dragged out; false otherwise
 - * @see #isFloatable
 - * @beaninfo
 - * description: Can the toolbar be made to float by the user?
 - * bound: true
 - * preferred: true
 - */
 - public void setFloatable( boolean b )
 - {
 - if ( floatable != b )
 - {
 - boolean old = floatable;
 - floatable = b;
 - firePropertyChange("floatable", old, b);
 - revalidate();
 - repaint();
 - }
 - }
 - /**
 - * Returns the current orientation of the toolbar. The value is either
 - * <code>HORIZONTAL</code> or <code>VERTICAL</code>.
 - *
 - * @return an integer representing the current orientation -- either
 - * <code>HORIZONTAL</code> or <code>VERTICAL</code>
 - * @see #setOrientation
 - */
 - public int getOrientation()
 - {
 - return this.orientation;
 - }
 - /**
 - * Sets the orientation of the toolbar. The orientation must have
 - * either the value <code>HORIZONTAL</code> or <code>VERTICAL</code>.
 - * If <code>orientation</code> is
 - * an invalid value, an exception will be thrown.
 - *
 - * @param o the new orientation -- either <code>HORIZONTAL</code> or
 - * </code>VERTICAL</code>
 - * @exception IllegalArgumentException if orientation is neither
 - * <code>HORIZONTAL</code> nor <code>VERTICAL</code>
 - * @see #getOrientation
 - * @beaninfo
 - * description: The current orientation of the toolbar
 - * bound: true
 - * preferred: true
 - */
 - public void setOrientation( int o )
 - {
 - checkOrientation( o );
 - if ( orientation != o )
 - {
 - int old = orientation;
 - orientation = o;
 - if ( o == VERTICAL )
 - setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
 - else {
 - if( SwingUtilities.isLeftToRight(this) ) {
 - setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
 - } else {
 - setLayout( new RightToLeftToolBarLayout() );
 - }
 - }
 - firePropertyChange("orientation", old, o);
 - revalidate();
 - repaint();
 - }
 - }
 - private void checkOrientation( int orientation )
 - {
 - switch ( orientation )
 - {
 - case VERTICAL:
 - case HORIZONTAL:
 - break;
 - default:
 - throw new IllegalArgumentException( "orientation must be one of: VERTICAL, HORIZONTAL" );
 - }
 - }
 - /**
 - * Appends a toolbar separator of default size to the end of the toolbar.
 - * The default size is determined by the current look and feel.
 - */
 - public void addSeparator()
 - {
 - JToolBar.Separator s = new JToolBar.Separator();
 - add(s);
 - }
 - /**
 - * Appends a toolbar separator of a specified size to the end
 - * of the toolbar.
 - *
 - * @param size the <code>Dimension</code> of the separator
 - */
 - public void addSeparator( Dimension size )
 - {
 - JToolBar.Separator s = new JToolBar.Separator( size );
 - add(s);
 - }
 - /**
 - * Adds a new <code>JButton</code> which dispatches the action.
 - *
 - * <p>
 - * As of 1.3, this is no longer the preferred method for adding
 - * <code>Action</code>s to a container. Instead it is recommended
 - * to configure a control with an action using
 - * using <code>setAction</code>, and then add that control directly
 - * to the <code>Container</code>.
 - *
 - * @param a the <code>Action</code> object to add as a new menu item
 - * @return the new button which dispatches the action
 - */
 - public JButton add(Action a) {
 - JButton b = createActionComponent(a);
 - b.setAction(a);
 - add(b);
 - return b;
 - }
 - /**
 - * Factory method which creates the <code>JButton</code> for
 - * <code>Action</code>s added to the <code>JToolBar</code>.
 - * The default name is empty if a <code>null</code> action is passed.
 - *
 - * <p>
 - * As of 1.3, this is no longer the preferred method for adding
 - * <code>Action</code>s to a <code>Container</code>.
 - * Instead it is recommended to configure a control with an action
 - * using <code>setAction</code>, and then add that control directly
 - * to the <code>Container</code>.
 - *
 - * @param a the <code>Action</code> for the button to be added
 - * @return the newly created button
 - * @see Action
 - */
 - protected JButton createActionComponent(Action a) {
 - String text = (String)a.getValue(Action.NAME);
 - Icon icon = (Icon)a.getValue(Action.SMALL_ICON);
 - JButton b = new JButton(text, icon) {
 - protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
 - PropertyChangeListener pcl = createActionChangeListener(this);
 - if (pcl==null) {
 - pcl = super.createActionPropertyChangeListener(a);
 - }
 - return pcl;
 - }
 - };
 - if (icon !=null) {
 - b.putClientProperty("hideActionText", Boolean.TRUE);
 - }
 - b.setHorizontalTextPosition(JButton.CENTER);
 - b.setVerticalTextPosition(JButton.BOTTOM);
 - b.setEnabled(a.isEnabled());
 - b.setToolTipText((String)a.getValue(Action.SHORT_DESCRIPTION));
 - return b;
 - }
 - /**
 - * Returns a properly configured <code>PropertyChangeListener</code>
 - * which updates the control as changes to the <code>Action</code> occur,
 - * or <code>null</code> if the default
 - * property change listener for the control is desired.
 - *
 - * <p>
 - * As of 1.3, this is no longer the preferred method for adding
 - * <code>Action</code>s to a <code>Container</code>.
 - * Instead it is recommended to configure a control with an action
 - * using <code>setAction</code>, and then add that control directly
 - * to the <code>Container</code>.
 - * @return <code>null</code>
 - */
 - protected PropertyChangeListener createActionChangeListener(JButton b) {
 - return null;
 - }
 - /**
 - * If a <code>JButton</code> is being added, it is initially
 - * set to be disabled.
 - *
 - * @param comp the component to be enhanced
 - * @param constraints the constraints to be enforced on the component
 - * @param index the index of the component
 - *
 - */
 - protected void addImpl(Component comp, Object constraints, int index) {
 - super.addImpl(comp, constraints, index);
 - if (comp instanceof JButton) {
 - ((JButton)comp).setDefaultCapable(false);
 - }
 - }
 - /**
 - * A toolbar-specific separator. An object with dimension but
 - * no contents used to divide buttons on a toolbar into groups.
 - */
 - static public class Separator extends JSeparator
 - {
 - private Dimension separatorSize;
 - /**
 - * Creates a new toolbar separator with the default size
 - * as defined by the current look and feel.
 - */
 - public Separator()
 - {
 - this( null ); // let the UI define the default size
 - }
 - /**
 - * Creates a new toolbar separator with the specified size.
 - *
 - * @param size the <code>Dimension</code> of the separator
 - */
 - public Separator( Dimension size )
 - {
 - super( JSeparator.HORIZONTAL );
 - setSeparatorSize(size);
 - }
 - /**
 - * Returns the name of the L&F class that renders this component.
 - *
 - * @return the string "ToolBarSeparatorUI"
 - * @see JComponent#getUIClassID
 - * @see UIDefaults#getUI
 - */
 - public String getUIClassID()
 - {
 - return "ToolBarSeparatorUI";
 - }
 - /**
 - * Sets the size of the separator.
 - *
 - * @param size the new <code>Dimension</code> of the separator
 - */
 - public void setSeparatorSize( Dimension size )
 - {
 - if (size != null) {
 - separatorSize = size;
 - } else {
 - super.updateUI();
 - }
 - this.invalidate();
 - }
 - /**
 - * Returns the size of the separator
 - *
 - * @return the <code>Dimension</code> object containing the separator's
 - * size (This is a reference, NOT a copy!)
 - */
 - public Dimension getSeparatorSize()
 - {
 - return separatorSize;
 - }
 - /**
 - * Returns the minimum size for the separator.
 - *
 - * @return the <code>Dimension</code> object containing the separator's
 - * minimum size
 - */
 - public Dimension getMinimumSize()
 - {
 - return getPreferredSize();
 - }
 - /**
 - * Returns the maximum size for the separator.
 - *
 - * @return the <code>Dimension</code> object containing the separator's
 - * maximum size
 - */
 - public Dimension getMaximumSize()
 - {
 - return getPreferredSize();
 - }
 - /**
 - * Returns the preferred size for the separator.
 - *
 - * @return the <code>Dimension</code> object containing the separator's
 - * preferred size
 - */
 - public Dimension getPreferredSize()
 - {
 - return separatorSize.getSize();
 - }
 - }
 - /**
 - * See <code>readObject</code> and <code>writeObject</code> in
 - * <code>JComponent</code> for more
 - * information about serialization in Swing.
 - */
 - private void writeObject(ObjectOutputStream s) throws IOException {
 - s.defaultWriteObject();
 - if ((ui != null) && (getUIClassID().equals(uiClassID))) {
 - ui.installUI(this);
 - }
 - }
 - /**
 - * Returns a string representation of this <code>JToolBar</code>.
 - * This method
 - * is intended to be used only for debugging purposes, and the
 - * content and format of the returned string may vary between
 - * implementations. The returned string may be empty but may not
 - * be <code>null</code>.
 - *
 - * @return a string representation of this <code>JToolBar</code>.
 - */
 - protected String paramString() {
 - String paintBorderString = (paintBorder ?
 - "true" : "false");
 - String marginString = (margin != null ?
 - margin.toString() : "");
 - String floatableString = (floatable ?
 - "true" : "false");
 - String orientationString = (orientation == HORIZONTAL ?
 - "HORIZONTAL" : "VERTICAL");
 - return super.paramString() +
 - ",floatable=" + floatableString +
 - ",margin=" + marginString +
 - ",orientation=" + orientationString +
 - ",paintBorder=" + paintBorderString;
 - }
 - /*
 - * This <code>PropertyChangeListener</code> is used to adjust the
 - * default layout
 - * manger when the toolBar is given a right-to-left ComponentOrientation.
 - * This is a hack to work around the fact that the DefaultMenuLayout
 - * (BoxLayout) isn't aware of ComponentOrientation. When BoxLayout is
 - * made aware of ComponentOrientation, this listener will no longer be
 - * necessary.
 - */
 - private class PropertyChangeHandler implements PropertyChangeListener {
 - public void propertyChange(PropertyChangeEvent e) {
 - String name = e.getPropertyName();
 - if( name.equals("componentOrientation") ) {
 - if( SwingUtilities.isLeftToRight(JToolBar.this) ) {
 - setLayout(new BoxLayout(JToolBar.this, BoxLayout.X_AXIS));
 - } else {
 - setLayout(new RightToLeftToolBarLayout());
 - }
 - }
 - }
 - }
 - private static class RightToLeftToolBarLayout
 - extends FlowLayout implements UIResource
 - {
 - private RightToLeftToolBarLayout() {
 - super(3/*FlowLayout.LEADING*/, 0, 0);
 - }
 - }
 - /////////////////
 - // Accessibility support
 - ////////////////
 - /**
 - * Gets the AccessibleContext associated with this JToolBar.
 - * For tool bars, the AccessibleContext takes the form of an
 - * AccessibleJToolBar.
 - * A new AccessibleJToolBar instance is created if necessary.
 - *
 - * @return an AccessibleJToolBar that serves as the
 - * AccessibleContext of this JToolBar
 - */
 - public AccessibleContext getAccessibleContext() {
 - if (accessibleContext == null) {
 - accessibleContext = new AccessibleJToolBar();
 - }
 - return accessibleContext;
 - }
 - /**
 - * This class implements accessibility support for the
 - * <code>JToolBar</code> class. It provides an implementation of the
 - * Java Accessibility API appropriate to tool bar user-interface elements.
 - */
 - protected class AccessibleJToolBar extends AccessibleJComponent {
 - /**
 - * Get the state of this object.
 - *
 - * @return an instance of AccessibleStateSet containing the current
 - * state set of the object
 - * @see AccessibleState
 - */
 - public AccessibleStateSet getAccessibleStateSet() {
 - AccessibleStateSet states = super.getAccessibleStateSet();
 - // FIXME: [[[WDW - need to add orientation from BoxLayout]]]
 - // FIXME: [[[WDW - need to do SELECTABLE if SelectionModel is added]]]
 - return states;
 - }
 - /**
 - * Get the role of this object.
 - *
 - * @return an instance of AccessibleRole describing the role of the object
 - */
 - public AccessibleRole getAccessibleRole() {
 - return AccessibleRole.TOOL_BAR;
 - }
 - } // inner class AccessibleJToolBar
 - }