/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.swing;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.accessibility.*;
import sun.swing.SwingUtilities2;

import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * A component that lets the user switch between a group of components by
 * clicking on a tab with a given title and/or icon.
 * For examples and information on using tabbed panes see
 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/tabbedpane.html">How to Use Tabbed Panes</a>,
 * a section in <em>The Java Tutorial</em>.
 * <p>
 * Tabs/components are added to a <code>TabbedPane</code> object by using the
 * <code>addTab</code> and <code>insertTab</code> methods.
 * A tab is represented by an index corresponding
 * to the position it was added in, where the first tab has an index equal to 0
 * and the last tab has an index equal to the tab count minus 1.
 * <p>
 * The <code>TabbedPane</code> uses a <code>SingleSelectionModel</code>
 * to represent the set
 * of tab indices and the currently selected index.  If the tab count
 * is greater than 0, then there will always be a selected index, which
 * by default will be initialized to the first tab.  If the tab count is
 * 0, then the selected index will be -1.
 * <p>
 * The tab title can be rendered by a <code>Component</code>.
 * For example, the following produce similar results:
 * <pre>
 * // In this case the look and feel renders the title for the tab.
 * tabbedPane.addTab("Tab", myComponent);
 * // In this case the custom component is responsible for rendering the
 * // title of the tab.
 * tabbedPane.addTab(null, myComponent);
 * tabbedPane.setTabComponentAt(0, new JLabel("Tab"));
 * </pre>
 * The latter is typically used when you want a more complex user interaction
 * that requires custom components on the tab.  For example, you could
 * provide a custom component that animates or one that has widgets for
 * closing the tab.
 * <p>
 * If you specify a component for a tab, the <code>JTabbedPane</code>
 * will not render any text or icon you have specified for the tab.
 * <p>
 * <strong>Note:</strong>
 * Do not use <code>setVisible</code> directly on a tab component to make it visible,
 * use <code>setSelectedComponent</code> or <code>setSelectedIndex</code> methods instead.
 * <p>
 * <strong>Warning:</strong> Swing is not thread safe. For more
 * information see <a
 * href="package-summary.html#threading">Swing's Threading
 * Policy</a>.
 * <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.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @beaninfo
 *      attribute: isContainer true
 *    description: A component which provides a tab folder metaphor for
 *                 displaying one component from a set of components.
 *
 * @author Dave Moore
 * @author Philip Milne
 * @author Amy Fowler
 *
 * @see SingleSelectionModel
 */
public class JTabbedPane extends JComponent
       implements Serializable, Accessible, SwingConstants {

   /**
    * The tab layout policy for wrapping tabs in multiple runs when all
    * tabs will not fit within a single run.
    */
    public static final int WRAP_TAB_LAYOUT = 0;

   /**
    * Tab layout policy for providing a subset of available tabs when all
    * the tabs will not fit within a single run.  If all the tabs do
    * not fit within a single run the look and feel will provide a way
    * to navigate to hidden tabs.
    */
    public static final int SCROLL_TAB_LAYOUT = 1;


    /**
     * @see #getUIClassID
     * @see #readObject
     */
    private static final String uiClassID = "TabbedPaneUI";

    /**
     * Where the tabs are placed.
     * @see #setTabPlacement
     */
    protected int tabPlacement = TOP;

    private int tabLayoutPolicy;

    /** The default selection model */
    protected SingleSelectionModel model;

    private boolean haveRegistered;

    /**
     * The <code>changeListener</code> is the listener we add to the
     * model.
     */
    protected ChangeListener changeListener = null;

    private final java.util.List<Page> pages;

    /* The component that is currently visible */
    private Component visComp = null;

    /**
     * Only one <code>ChangeEvent</code> is needed per <code>TabPane</code>
     * instance since the
     * event's only (read-only) state is the source property.  The source
     * of events generated here is always "this".
     */
    protected transient ChangeEvent changeEvent = null;

    /**
     * Creates an empty <code>TabbedPane</code> with a default
     * tab placement of <code>JTabbedPane.TOP</code>.
     * @see #addTab
     */
    public JTabbedPane() {
        this(TOP, WRAP_TAB_LAYOUT);
    }

    /**
     * Creates an empty <code>TabbedPane</code> with the specified tab placement
     * of either: <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>,
     * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>.
     *
     * @param tabPlacement the placement for the tabs relative to the content
     * @see #addTab
     */
    public JTabbedPane(int tabPlacement) {
        this(tabPlacement, WRAP_TAB_LAYOUT);
    }

    /**
     * Creates an empty <code>TabbedPane</code> with the specified tab placement
     * and tab layout policy.  Tab placement may be either:
     * <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>,
     * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>.
     * Tab layout policy may be either: <code>JTabbedPane.WRAP_TAB_LAYOUT</code>
     * or <code>JTabbedPane.SCROLL_TAB_LAYOUT</code>.
     *
     * @param tabPlacement the placement for the tabs relative to the content
     * @param tabLayoutPolicy the policy for laying out tabs when all tabs will not fit on one run
     * @exception IllegalArgumentException if tab placement or tab layout policy are not
     *            one of the above supported values
     * @see #addTab
     * @since 1.4
     */
    public JTabbedPane(int tabPlacement, int tabLayoutPolicy) {
        setTabPlacement(tabPlacement);
        setTabLayoutPolicy(tabLayoutPolicy);
        pages = new ArrayList<Page>(1);
        setModel(new DefaultSingleSelectionModel());
        updateUI();
    }

    /**
     * Returns the UI object which implements the L&F for this component.
     *
     * @return a <code>TabbedPaneUI</code> object
     * @see #setUI
     */
    public TabbedPaneUI getUI() {
        return (TabbedPaneUI)ui;
    }

    /**
     * Sets the UI object which implements the L&F for this component.
     *
     * @param ui the new UI object
     * @see UIDefaults#getUI
     * @beaninfo
     *        bound: true
     *       hidden: true
     *    attribute: visualUpdate true
     *  description: The UI object that implements the tabbedpane's LookAndFeel
     */
    public void setUI(TabbedPaneUI ui) {
        super.setUI(ui);
        // disabled icons are generated by LF so they should be unset here
        for (int i = 0; i < getTabCount(); i++) {
            Icon icon = pages.get(i).disabledIcon;
            if (icon instanceof UIResource) {
                setDisabledIconAt(i, null);
            }
        }
    }

    /**
     * Resets the UI property to a value from the current look and feel.
     *
     * @see JComponent#updateUI
     */
    public void updateUI() {
        setUI((TabbedPaneUI)UIManager.getUI(this));
    }


    /**
     * Returns the name of the UI class that implements the
     * L&F for this component.
     *
     * @return the string "TabbedPaneUI"
     * @see JComponent#getUIClassID
     * @see UIDefaults#getUI
     */
    public String getUIClassID() {
        return uiClassID;
    }


    /**
     * We pass <code>ModelChanged</code> events along to the listeners with
     * the tabbedpane (instead of the model itself) as the event source.
     */
    protected class ModelListener implements ChangeListener, Serializable {
        public void stateChanged(ChangeEvent e) {
            fireStateChanged();
        }
    }

    /**
     * Subclasses that want to handle <code>ChangeEvents</code> differently
     * can override this to return a subclass of <code>ModelListener</code> or
     * another <code>ChangeListener</code> implementation.
     *
     * @see #fireStateChanged
     */
    protected ChangeListener createChangeListener() {
        return new ModelListener();
    }

    /**
     * Adds a <code>ChangeListener</code> to this tabbedpane.
     *
     * @param l the <code>ChangeListener</code> to add
     * @see #fireStateChanged
     * @see #removeChangeListener
     */
    public void addChangeListener(ChangeListener l) {
        listenerList.add(ChangeListener.class, l);
    }

    /**
     * Removes a <code>ChangeListener</code> from this tabbedpane.
     *
     * @param l the <code>ChangeListener</code> to remove
     * @see #fireStateChanged
     * @see #addChangeListener
     */
    public void removeChangeListener(ChangeListener l) {
        listenerList.remove(ChangeListener.class, l);
    }

   /**
     * Returns an array of all the <code>ChangeListener</code>s added
     * to this <code>JTabbedPane</code> with <code>addChangeListener</code>.
     *
     * @return all of the <code>ChangeListener</code>s added or an empty
     *         array if no listeners have been added
     * @since 1.4
     */
    public ChangeListener[] getChangeListeners() {
        return (ChangeListener[])listenerList.getListeners(
                ChangeListener.class);
    }

    /**
     * Sends a {@code ChangeEvent}, with this {@code JTabbedPane} as the source,
     * to each registered listener. This method is called each time there is
     * a change to either the selected index or the selected tab in the
     * {@code JTabbedPane}. Usually, the selected index and selected tab change
     * together. However, there are some cases, such as tab addition, where the
     * selected index changes and the same tab remains selected. There are other
     * cases, such as deleting the selected tab, where the index remains the
     * same, but a new tab moves to that index. Events are fired for all of
     * these cases.
     *
     * @see #addChangeListener
     * @see EventListenerList
     */
    protected void fireStateChanged() {
        /* --- Begin code to deal with visibility --- */

        /* This code deals with changing the visibility of components to
         * hide and show the contents for the selected tab. It duplicates
         * logic already present in BasicTabbedPaneUI, logic that is
         * processed during the layout pass. This code exists to allow
         * developers to do things that are quite difficult to accomplish
         * with the previous model of waiting for the layout pass to process
         * visibility changes; such as requesting focus on the new visible
         * component.
         *
         * For the average code, using the typical JTabbedPane methods,
         * all visibility changes will now be processed here. However,
         * the code in BasicTabbedPaneUI still exists, for the purposes
         * of backward compatibility. Therefore, when making changes to
         * this code, ensure that the BasicTabbedPaneUI code is kept in
         * synch.
         */

        int selIndex = getSelectedIndex();

        /* if the selection is now nothing */
        if (selIndex < 0) {
            /* if there was a previous visible component */
            if (visComp != null && visComp.isVisible()) {
                /* make it invisible */
                visComp.setVisible(false);
            }

            /* now there's no visible component */
            visComp = null;

        /* else - the selection is now something */
        } else {
            /* Fetch the component for the new selection */
            Component newComp = getComponentAt(selIndex);

            /* if the new component is non-null and different */
            if (newComp != null && newComp != visComp) {
                boolean shouldChangeFocus = false;

                /* Note: the following (clearing of the old visible component)
                 * is inside this if-statement for good reason: Tabbed pane
                 * should continue to show the previously visible component
                 * if there is no component for the chosen tab.
                 */

                /* if there was a previous visible component */
                if (visComp != null) {
                    shouldChangeFocus =
                        (SwingUtilities.findFocusOwner(visComp) != null);

                    /* if it's still visible */
                    if (visComp.isVisible()) {
                        /* make it invisible */
                        visComp.setVisible(false);
                    }
                }

                if (!newComp.isVisible()) {
                    newComp.setVisible(true);
                }

                if (shouldChangeFocus) {
                    SwingUtilities2.tabbedPaneChangeFocusTo(newComp);
                }

                visComp = newComp;
            } /* else - the visible component shouldn't changed */
        }

        /* --- End code to deal with visibility --- */

        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length-2; i>=0; i-=2) {
            if (listeners[i]==ChangeListener.class) {
                // Lazily create the event:
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
            }
        }
    }

    /**
     * Returns the model associated with this tabbedpane.
     *
     * @see #setModel
     */
    public SingleSelectionModel getModel() {
        return model;
    }

    /**
     * Sets the model to be used with this tabbedpane.
     *
     * @param model the model to be used
     * @see #getModel
     * @beaninfo
     *       bound: true
     * description: The tabbedpane's SingleSelectionModel.
     */
    public void setModel(SingleSelectionModel model) {
        SingleSelectionModel oldModel = getModel();

        if (oldModel != null) {
            oldModel.removeChangeListener(changeListener);
            changeListener = null;
        }

        this.model = model;

        if (model != null) {
            changeListener = createChangeListener();
            model.addChangeListener(changeListener);
        }

        firePropertyChange("model", oldModel, model);
        repaint();
    }

    /**
     * Returns the placement of the tabs for this tabbedpane.
     * @see #setTabPlacement
     */
    public int getTabPlacement() {
        return tabPlacement;
    }

    /**
     * Sets the tab placement for this tabbedpane.
     * Possible values are:<ul>
     * <li><code>JTabbedPane.TOP</code>
     * <li><code>JTabbedPane.BOTTOM</code>
     * <li><code>JTabbedPane.LEFT</code>
     * <li><code>JTabbedPane.RIGHT</code>
     * </ul>
     * The default value, if not set, is <code>SwingConstants.TOP</code>.
     *
     * @param tabPlacement the placement for the tabs relative to the content
     * @exception IllegalArgumentException if tab placement value isn't one
     *                          of the above valid values
     *
     * @beaninfo
     *    preferred: true
     *        bound: true
     *    attribute: visualUpdate true
     *         enum: TOP JTabbedPane.TOP
     *               LEFT JTabbedPane.LEFT
     *               BOTTOM JTabbedPane.BOTTOM
     *               RIGHT JTabbedPane.RIGHT
     *  description: The tabbedpane's tab placement.
     *
     */
    public void setTabPlacement(int tabPlacement) {
        if (tabPlacement != TOP && tabPlacement != LEFT &&
            tabPlacement != BOTTOM && tabPlacement != RIGHT) {
            throw new IllegalArgumentException("illegal tab placement: must be TOP, BOTTOM, LEFT, or RIGHT");
        }
        if (this.tabPlacement != tabPlacement) {
            int oldValue = this.tabPlacement;
            this.tabPlacement = tabPlacement;
            firePropertyChange("tabPlacement", oldValue, tabPlacement);
            revalidate();
            repaint();
        }
    }

    /**
     * Returns the policy used by the tabbedpane to layout the tabs when all the
     * tabs will not fit within a single run.
     * @see #setTabLayoutPolicy
     * @since 1.4
     */
    public int getTabLayoutPolicy() {
        return tabLayoutPolicy;
    }

   /**
     * Sets the policy which the tabbedpane will use in laying out the tabs
     * when all the tabs will not fit within a single run.
     * Possible values are:
     * <ul>
     * <li><code>JTabbedPane.WRAP_TAB_LAYOUT</code>
     * <li><code>JTabbedPane.SCROLL_TAB_LAYOUT</code>
     * </ul>
     *
     * The default value, if not set by the UI, is <code>JTabbedPane.WRAP_TAB_LAYOUT</code>.
     * <p>
     * Some look and feels might only support a subset of the possible
     * layout policies, in which case the value of this property may be
     * ignored.
     *
     * @param tabLayoutPolicy the policy used to layout the tabs
     * @exception IllegalArgumentException if layoutPolicy value isn't one
     *                          of the above valid values
     * @see #getTabLayoutPolicy
     * @since 1.4
     *
     * @beaninfo
     *    preferred: true
     *        bound: true
     *    attribute: visualUpdate true
     *         enum: WRAP_TAB_LAYOUT JTabbedPane.WRAP_TAB_LAYOUT
     *               SCROLL_TAB_LAYOUT JTabbedPane.SCROLL_TAB_LAYOUT
     *  description: The tabbedpane's policy for laying out the tabs
     *
     */
    public void setTabLayoutPolicy(int tabLayoutPolicy) {
        if (tabLayoutPolicy != WRAP_TAB_LAYOUT && tabLayoutPolicy != SCROLL_TAB_LAYOUT) {
            throw new IllegalArgumentException("illegal tab layout policy: must be WRAP_TAB_LAYOUT or SCROLL_TAB_LAYOUT");
        }
        if (this.tabLayoutPolicy != tabLayoutPolicy) {
            int oldValue = this.tabLayoutPolicy;
            this.tabLayoutPolicy = tabLayoutPolicy;
            firePropertyChange("tabLayoutPolicy", oldValue, tabLayoutPolicy);
            revalidate();
            repaint();
        }
    }

    /**
     * Returns the currently selected index for this tabbedpane.
     * Returns -1 if there is no currently selected tab.
     *
     * @return the index of the selected tab
     * @see #setSelectedIndex
     */
    public int getSelectedIndex() {
        return model.getSelectedIndex();
    }

    /**
     * Sets the selected index for this tabbedpane. The index must be
     * a valid tab index or -1, which indicates that no tab should be selected
     * (can also be used when there are no tabs in the tabbedpane).  If a -1
     * value is specified when the tabbedpane contains one or more tabs, then
     * the results will be implementation defined.
     *
     * @param index  the index to be selected
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < -1 || index >= tab count)
     *
     * @see #getSelectedIndex
     * @see SingleSelectionModel#setSelectedIndex
     * @beaninfo
     *   preferred: true
     * description: The tabbedpane's selected tab index.
     */
    public void setSelectedIndex(int index) {
        if (index != -1) {
            checkIndex(index);
        }
        setSelectedIndexImpl(index, true);
    }


    private void setSelectedIndexImpl(int index, boolean doAccessibleChanges) {
        int oldIndex = model.getSelectedIndex();
        Page oldPage = null, newPage = null;
        String oldName = null;

        doAccessibleChanges = doAccessibleChanges && (oldIndex != index);

        if (doAccessibleChanges) {
            if (accessibleContext != null) {
                oldName = accessibleContext.getAccessibleName();
            }

            if (oldIndex >= 0) {
                oldPage = pages.get(oldIndex);
            }

            if (index >= 0) {
                newPage = pages.get(index);
            }
        }

        model.setSelectedIndex(index);

        if (doAccessibleChanges) {
            changeAccessibleSelection(oldPage, oldName, newPage);
        }
    }

    private void changeAccessibleSelection(Page oldPage, String oldName, Page newPage) {
        if (accessibleContext == null) {
            return;
        }

        if (oldPage != null) {
            oldPage.firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
                                       AccessibleState.SELECTED, null);
        }

        if (newPage != null) {
            newPage.firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
                                       null, AccessibleState.SELECTED);
        }

        accessibleContext.firePropertyChange(
            AccessibleContext.ACCESSIBLE_NAME_PROPERTY,
            oldName,
            accessibleContext.getAccessibleName());
    }

    /**
     * Returns the currently selected component for this tabbedpane.
     * Returns <code>null</code> if there is no currently selected tab.
     *
     * @return the component corresponding to the selected tab
     * @see #setSelectedComponent
     */
    public Component getSelectedComponent() {
        int index = getSelectedIndex();
        if (index == -1) {
            return null;
        }
        return getComponentAt(index);
    }

    /**
     * Sets the selected component for this tabbedpane.  This
     * will automatically set the <code>selectedIndex</code> to the index
     * corresponding to the specified component.
     *
     * @exception IllegalArgumentException if component not found in tabbed
     *          pane
     * @see #getSelectedComponent
     * @beaninfo
     *   preferred: true
     * description: The tabbedpane's selected component.
     */
    public void setSelectedComponent(Component c) {
        int index = indexOfComponent(c);
        if (index != -1) {
            setSelectedIndex(index);
        } else {
            throw new IllegalArgumentException("component not found in tabbed pane");
        }
    }

    /**
     * Inserts a new tab for the given component, at the given index,
     * represented by the given title and/or icon, either of which may
     * be {@code null}.
     *
     * @param title the title to be displayed on the tab
     * @param icon the icon to be displayed on the tab
     * @param component the component to be displayed when this tab is clicked.
     * @param tip the tooltip to be displayed for this tab
     * @param index the position to insert this new tab
     *       ({@code > 0 and <= getTabCount()})
     *
     * @throws IndexOutOfBoundsException if the index is out of range
     *         ({@code < 0 or > getTabCount()})
     *
     * @see #addTab
     * @see #removeTabAt
     */
    public void insertTab(String title, Icon icon, Component component, String tip, int index) {
        int newIndex = index;

        // If component already exists, remove corresponding
        // tab so that new tab gets added correctly
        // Note: we are allowing component=null because of compatibility,
        // but we really should throw an exception because much of the
        // rest of the JTabbedPane implementation isn't designed to deal
        // with null components for tabs.
        int removeIndex = indexOfComponent(component);
        if (component != null && removeIndex != -1) {
            removeTabAt(removeIndex);
            if (newIndex > removeIndex) {
                newIndex--;
            }
        }

        int selectedIndex = getSelectedIndex();

        pages.add(
            newIndex,
            new Page(this, title != null? title : "", icon, null, component, tip));


        if (component != null) {
            addImpl(component, null, -1);
            component.setVisible(false);
        } else {
            firePropertyChange("indexForNullComponent", -1, index);
        }

        if (pages.size() == 1) {
            setSelectedIndex(0);
        }

        if (selectedIndex >= newIndex) {
            setSelectedIndexImpl(selectedIndex + 1, false);
        }

        if (!haveRegistered && tip != null) {
            ToolTipManager.sharedInstance().registerComponent(this);
            haveRegistered = true;
        }

        if (accessibleContext != null) {
            accessibleContext.firePropertyChange(
                    AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
                    null, component);
        }
        revalidate();
        repaint();
    }

    /**
     * Adds a <code>component</code> and <code>tip</code>
     * represented by a <code>title</code> and/or <code>icon</code>,
     * either of which can be <code>null</code>.
     * Cover method for <code>insertTab</code>.
     *
     * @param title the title to be displayed in this tab
     * @param icon the icon to be displayed in this tab
     * @param component the component to be displayed when this tab is clicked
     * @param tip the tooltip to be displayed for this tab
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public void addTab(String title, Icon icon, Component component, String tip) {
        insertTab(title, icon, component, tip, pages.size());
    }

    /**
     * Adds a <code>component</code> represented by a <code>title</code>
     * and/or <code>icon</code>, either of which can be <code>null</code>.
     * Cover method for <code>insertTab</code>.
     *
     * @param title the title to be displayed in this tab
     * @param icon the icon to be displayed in this tab
     * @param component the component to be displayed when this tab is clicked
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public void addTab(String title, Icon icon, Component component) {
        insertTab(title, icon, component, null, pages.size());
    }

    /**
     * Adds a <code>component</code> represented by a <code>title</code>
     * and no icon.
     * Cover method for <code>insertTab</code>.
     *
     * @param title the title to be displayed in this tab
     * @param component the component to be displayed when this tab is clicked
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public void addTab(String title, Component component) {
        insertTab(title, null, component, null, pages.size());
    }

    /**
     * Adds a <code>component</code> with a tab title defaulting to
     * the name of the component which is the result of calling
     * <code>component.getName</code>.
     * Cover method for <code>insertTab</code>.
     *
     * @param component the component to be displayed when this tab is clicked
     * @return the component
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public Component add(Component component) {
        if (!(component instanceof UIResource)) {
            addTab(component.getName(), component);
        } else {
            super.add(component);
        }
        return component;
    }

    /**
     * Adds a <code>component</code> with the specified tab title.
     * Cover method for <code>insertTab</code>.
     *
     * @param title the title to be displayed in this tab
     * @param component the component to be displayed when this tab is clicked
     * @return the component
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public Component add(String title, Component component) {
        if (!(component instanceof UIResource)) {
            addTab(title, component);
        } else {
            super.add(title, component);
        }
        return component;
    }

    /**
     * Adds a <code>component</code> at the specified tab index with a tab
     * title defaulting to the name of the component.
     * Cover method for <code>insertTab</code>.
     *
     * @param component the component to be displayed when this tab is clicked
     * @param index the position to insert this new tab
     * @return the component
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public Component add(Component component, int index) {
        if (!(component instanceof UIResource)) {
            // Container.add() interprets -1 as "append", so convert
            // the index appropriately to be handled by the vector
            insertTab(component.getName(), null, component, null,
                      index == -1? getTabCount() : index);
        } else {
            super.add(component, index);
        }
        return component;
    }

    /**
     * Adds a <code>component</code> to the tabbed pane.
     * If <code>constraints</code> is a <code>String</code> or an
     * <code>Icon</code>, it will be used for the tab title,
     * otherwise the component's name will be used as the tab title.
     * Cover method for <code>insertTab</code>.
     *
     * @param component the component to be displayed when this tab is clicked
     * @param constraints the object to be displayed in the tab
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public void add(Component component, Object constraints) {
        if (!(component instanceof UIResource)) {
            if (constraints instanceof String) {
                addTab((String)constraints, component);
            } else if (constraints instanceof Icon) {
                addTab(null, (Icon)constraints, component);
            } else {
                add(component);
            }
        } else {
            super.add(component, constraints);
        }
    }

    /**
     * Adds a <code>component</code> at the specified tab index.
     * If <code>constraints</code> is a <code>String</code> or an
     * <code>Icon</code>, it will be used for the tab title,
     * otherwise the component's name will be used as the tab title.
     * Cover method for <code>insertTab</code>.
     *
     * @param component the component to be displayed when this tab is clicked
     * @param constraints the object to be displayed in the tab
     * @param index the position to insert this new tab
     *
     * @see #insertTab
     * @see #removeTabAt
     */
    public void add(Component component, Object constraints, int index) {
        if (!(component instanceof UIResource)) {

            Icon icon = constraints instanceof Icon? (Icon)constraints : null;
            String title = constraints instanceof String? (String)constraints : null;
            // Container.add() interprets -1 as "append", so convert
            // the index appropriately to be handled by the vector
            insertTab(title, icon, component, null, index == -1? getTabCount() : index);
        } else {
            super.add(component, constraints, index);
        }
    }

    /**
     * Removes the tab at <code>index</code>.
     * After the component associated with <code>index</code> is removed,
     * its visibility is reset to true to ensure it will be visible
     * if added to other containers.
     * @param index the index of the tab to be removed
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #addTab
     * @see #insertTab
     */
    public void removeTabAt(int index) {
        checkIndex(index);

        Component component = getComponentAt(index);
        boolean shouldChangeFocus = false;
        int selected = getSelectedIndex();
        String oldName = null;

        /* if we're about to remove the visible component */
        if (component == visComp) {
            shouldChangeFocus = (SwingUtilities.findFocusOwner(visComp) != null);
            visComp = null;
        }

        if (accessibleContext != null) {
            /* if we're removing the selected page */
            if (index == selected) {
                /* fire an accessible notification that it's unselected */
                pages.get(index).firePropertyChange(
                    AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
                    AccessibleState.SELECTED, null);

                oldName = accessibleContext.getAccessibleName();
            }

            accessibleContext.firePropertyChange(
                    AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
                    component, null);
        }

        // Force the tabComponent to be cleaned up.
        setTabComponentAt(index, null);
        pages.remove(index);

        // NOTE 4/15/2002 (joutwate):
        // This fix is implemented using client properties since there is
        // currently no IndexPropertyChangeEvent.  Once
        // IndexPropertyChangeEvents have been added this code should be
        // modified to use it.
        putClientProperty("__index_to_remove__", new Integer(index));

        /* if the selected tab is after the removal */
        if (selected > index) {
            setSelectedIndexImpl(selected - 1, false);

        /* if the selected tab is the last tab */
        } else if (selected >= getTabCount()) {
            setSelectedIndexImpl(selected - 1, false);
            Page newSelected = (selected != 0)
                ? pages.get(selected - 1)
                : null;

            changeAccessibleSelection(null, oldName, newSelected);

        /* selected index hasn't changed, but the associated tab has */
        } else if (index == selected) {
            fireStateChanged();
            changeAccessibleSelection(null, oldName, pages.get(index));
        }

        // We can't assume the tab indices correspond to the
        // container's children array indices, so make sure we
        // remove the correct child!
        if (component != null) {
            Component components[] = getComponents();
            for (int i = components.length; --i >= 0; ) {
                if (components[i] == component) {
                    super.remove(i);
                    component.setVisible(true);
                    break;
                }
            }
        }

        if (shouldChangeFocus) {
            SwingUtilities2.tabbedPaneChangeFocusTo(getSelectedComponent());
        }

        revalidate();
        repaint();
    }

    /**
     * Removes the specified <code>Component</code> from the
     * <code>JTabbedPane</code>. The method does nothing
     * if the <code>component</code> is null.
     *
     * @param component the component to remove from the tabbedpane
     * @see #addTab
     * @see #removeTabAt
     */
    public void remove(Component component) {
        int index = indexOfComponent(component);
        if (index != -1) {
            removeTabAt(index);
        } else {
            // Container#remove(comp) invokes Container#remove(int)
            // so make sure JTabbedPane#remove(int) isn't called here
            Component children[] = getComponents();
            for (int i=0; i < children.length; i++) {
                if (component == children[i]) {
                    super.remove(i);
                    break;
                }
            }
        }
    }

    /**
     * Removes the tab and component which corresponds to the specified index.
     *
     * @param index the index of the component to remove from the
     *          <code>tabbedpane</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     * @see #addTab
     * @see #removeTabAt
     */
    public void remove(int index) {
        removeTabAt(index);
    }

    /**
     * Removes all the tabs and their corresponding components
     * from the <code>tabbedpane</code>.
     *
     * @see #addTab
     * @see #removeTabAt
     */
    public void removeAll() {
        setSelectedIndexImpl(-1, true);

        int tabCount = getTabCount();
        // We invoke removeTabAt for each tab, otherwise we may end up
        // removing Components added by the UI.
        while (tabCount-- > 0) {
            removeTabAt(tabCount);
        }
    }

    /**
     * Returns the number of tabs in this <code>tabbedpane</code>.
     *
     * @return an integer specifying the number of tabbed pages
     */
    public int getTabCount() {
        return pages.size();
    }

    /**
     * Returns the number of tab runs currently used to display
     * the tabs.
     * @return an integer giving the number of rows if the
     *          <code>tabPlacement</code>
     *          is <code>TOP</code> or <code>BOTTOM</code>
     *          and the number of columns if
     *          <code>tabPlacement</code>
     *          is <code>LEFT</code> or <code>RIGHT</code>,
     *          or 0 if there is no UI set on this <code>tabbedpane</code>
     */
    public int getTabRunCount() {
        if (ui != null) {
            return ((TabbedPaneUI)ui).getTabRunCount(this);
        }
        return 0;
    }


// Getters for the Pages

    /**
     * Returns the tab title at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the title at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     * @see #setTitleAt
     */
    public String getTitleAt(int index) {
        return pages.get(index).title;
    }

    /**
     * Returns the tab icon at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the icon at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setIconAt
     */
    public Icon getIconAt(int index) {
        return pages.get(index).icon;
    }

    /**
     * Returns the tab disabled icon at <code>index</code>.
     * If the tab disabled icon doesn't exist at <code>index</code>
     * this will forward the call to the look and feel to construct
     * an appropriate disabled Icon from the corresponding enabled
     * Icon. Some look and feels might not render the disabled Icon,
     * in which case it won't be created.
     *
     * @param index  the index of the item being queried
     * @return the icon at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setDisabledIconAt
     */
    public Icon getDisabledIconAt(int index) {
        Page page = pages.get(index);
        if (page.disabledIcon == null) {
            page.disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, page.icon);
        }
        return page.disabledIcon;
    }

    /**
     * Returns the tab tooltip text at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return a string containing the tool tip text at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setToolTipTextAt
     * @since 1.3
     */
    public String getToolTipTextAt(int index) {
        return pages.get(index).tip;
    }

    /**
     * Returns the tab background color at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the <code>Color</code> of the tab background at
     *          <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setBackgroundAt
     */
    public Color getBackgroundAt(int index) {
        return pages.get(index).getBackground();
    }

    /**
     * Returns the tab foreground color at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the <code>Color</code> of the tab foreground at
     *          <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setForegroundAt
     */
    public Color getForegroundAt(int index) {
        return pages.get(index).getForeground();
    }

    /**
     * Returns whether or not the tab at <code>index</code> is
     * currently enabled.
     *
     * @param index  the index of the item being queried
     * @return true if the tab at <code>index</code> is enabled;
     *          false otherwise
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setEnabledAt
     */
    public boolean isEnabledAt(int index) {
        return pages.get(index).isEnabled();
    }

    /**
     * Returns the component at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the <code>Component</code> at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setComponentAt
     */
    public Component getComponentAt(int index) {
        return pages.get(index).component;
    }

    /**
     * Returns the keyboard mnemonic for accessing the specified tab.
     * The mnemonic is the key which when combined with the look and feel's
     * mouseless modifier (usually Alt) will activate the specified
     * tab.
     *
     * @since 1.4
     * @param tabIndex the index of the tab that the mnemonic refers to
     * @return the key code which represents the mnemonic;
     *         -1 if a mnemonic is not specified for the tab
     * @exception IndexOutOfBoundsException if index is out of range
     *            (<code>tabIndex</code> &lt; 0 ||
     *              <code>tabIndex</code> &gt;= tab count)
     * @see #setDisplayedMnemonicIndexAt(int,int)
     * @see #setMnemonicAt(int,int)
     */
    public int getMnemonicAt(int tabIndex) {
        checkIndex(tabIndex);

        Page page = pages.get(tabIndex);
        return page.getMnemonic();
    }

    /**
     * Returns the character, as an index, that the look and feel should
     * provide decoration for as representing the mnemonic character.
     *
     * @since 1.4
     * @param tabIndex the index of the tab that the mnemonic refers to
     * @return index representing mnemonic character if one exists;
     *    otherwise returns -1
     * @exception IndexOutOfBoundsException if index is out of range
     *            (<code>tabIndex</code> &lt; 0 ||
     *              <code>tabIndex</code> &gt;= tab count)
     * @see #setDisplayedMnemonicIndexAt(int,int)
     * @see #setMnemonicAt(int,int)
     */
    public int getDisplayedMnemonicIndexAt(int tabIndex) {
        checkIndex(tabIndex);

        Page page = pages.get(tabIndex);
        return page.getDisplayedMnemonicIndex();
    }

    /**
     * Returns the tab bounds at <code>index</code>.  If the tab at
     * this index is not currently visible in the UI, then returns
     * <code>null</code>.
     * If there is no UI set on this <code>tabbedpane</code>,
     * then returns <code>null</code>.
     *
     * @param index the index to be queried
     * @return a <code>Rectangle</code> containing the tab bounds at
     *          <code>index</code>, or <code>null</code> if tab at
     *          <code>index</code> is not currently visible in the UI,
     *          or if there is no UI set on this <code>tabbedpane</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     */
    public Rectangle getBoundsAt(int index) {
        checkIndex(index);
        if (ui != null) {
            return ((TabbedPaneUI)ui).getTabBounds(this, index);
        }
        return null;
    }


// Setters for the Pages

    /**
     * Sets the title at <code>index</code> to <code>title</code> which
     * can be <code>null</code>.
     * The title is not shown if a tab component for this tab was specified.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where the title should be set
     * @param title the title to be displayed in the tab
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getTitleAt
     * @see #setTabComponentAt
     * @beaninfo
     *    preferred: true
     *    attribute: visualUpdate true
     *  description: The title at the specified tab index.
     */
    public void setTitleAt(int index, String title) {
        Page page = pages.get(index);
        String oldTitle =page.title;
        page.title = title;

        if (oldTitle != title) {
            firePropertyChange("indexForTitle", -1, index);
        }
        page.updateDisplayedMnemonicIndex();
        if ((oldTitle != title) && (accessibleContext != null)) {
            accessibleContext.firePropertyChange(
                    AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
                    oldTitle, title);
        }
        if (title == null || oldTitle == null ||
            !title.equals(oldTitle)) {
            revalidate();
            repaint();
        }
    }

    /**
     * Sets the icon at <code>index</code> to <code>icon</code> which can be
     * <code>null</code>. This does not set disabled icon at <code>icon</code>.
     * If the new Icon is different than the current Icon and disabled icon
     * is not explicitly set, the LookAndFeel will be asked to generate a disabled
     * Icon. To explicitly set disabled icon, use <code>setDisableIconAt()</code>.
     * The icon is not shown if a tab component for this tab was specified.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where the icon should be set
     * @param icon the icon to be displayed in the tab
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setDisabledIconAt
     * @see #getIconAt
     * @see #getDisabledIconAt
     * @see #setTabComponentAt
     * @beaninfo
     *    preferred: true
     *    attribute: visualUpdate true
     *  description: The icon at the specified tab index.
     */
    public void setIconAt(int index, Icon icon) {
        Page page = pages.get(index);
        Icon oldIcon = page.icon;
        if (icon != oldIcon) {
            page.icon = icon;

            /* If the default icon has really changed and we had
             * generated the disabled icon for this page, then
             * clear the disabledIcon field of the page.
             */
            if (page.disabledIcon instanceof UIResource) {
                page.disabledIcon = null;
            }

            // Fire the accessibility Visible data change
            if (accessibleContext != null) {
                accessibleContext.firePropertyChange(
                        AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
                        oldIcon, icon);
            }
            revalidate();
            repaint();
        }
    }

    /**
     * Sets the disabled icon at <code>index</code> to <code>icon</code>
     * which can be <code>null</code>.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where the disabled icon should be set
     * @param disabledIcon the icon to be displayed in the tab when disabled
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getDisabledIconAt
     * @beaninfo
     *    preferred: true
     *    attribute: visualUpdate true
     *  description: The disabled icon at the specified tab index.
     */
    public void setDisabledIconAt(int index, Icon disabledIcon) {
        Icon oldIcon = pages.get(index).disabledIcon;
        pages.get(index).disabledIcon = disabledIcon;
        if (disabledIcon != oldIcon && !isEnabledAt(index)) {
            revalidate();
            repaint();
        }
    }

    /**
     * Sets the tooltip text at <code>index</code> to <code>toolTipText</code>
     * which can be <code>null</code>.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where the tooltip text should be set
     * @param toolTipText the tooltip text to be displayed for the tab
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getToolTipTextAt
     * @beaninfo
     *    preferred: true
     *  description: The tooltip text at the specified tab index.
     * @since 1.3
     */
    public void setToolTipTextAt(int index, String toolTipText) {
        String oldToolTipText = pages.get(index).tip;
        pages.get(index).tip = toolTipText;

        if ((oldToolTipText != toolTipText) && (accessibleContext != null)) {
            accessibleContext.firePropertyChange(
                    AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
                    oldToolTipText, toolTipText);
        }
        if (!haveRegistered && toolTipText != null) {
            ToolTipManager.sharedInstance().registerComponent(this);
            haveRegistered = true;
        }
    }

    /**
     * Sets the background color at <code>index</code> to
     * <code>background</code>
     * which can be <code>null</code>, in which case the tab's background color
     * will default to the background color of the <code>tabbedpane</code>.
     * An internal exception is raised if there is no tab at that index.
     * @param index the tab index where the background should be set
     * @param background the color to be displayed in the tab's background
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getBackgroundAt
     * @beaninfo
     *    preferred: true
     *    attribute: visualUpdate true
     *  description: The background color at the specified tab index.
     */
    public void setBackgroundAt(int index, Color background) {
        Color oldBg = pages.get(index).background;
        pages.get(index).setBackground(background);
        if (background == null || oldBg == null ||
            !background.equals(oldBg)) {
            Rectangle tabBounds = getBoundsAt(index);
            if (tabBounds != null) {
                repaint(tabBounds);
            }
        }
    }

    /**
     * Sets the foreground color at <code>index</code> to
     * <code>foreground</code> which can be
     * <code>null</code>, in which case the tab's foreground color
     * will default to the foreground color of this <code>tabbedpane</code>.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where the foreground should be set
     * @param foreground the color to be displayed as the tab's foreground
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getForegroundAt
     * @beaninfo
     *    preferred: true
     *    attribute: visualUpdate true
     *  description: The foreground color at the specified tab index.
     */
    public void setForegroundAt(int index, Color foreground) {
        Color oldFg = pages.get(index).foreground;
        pages.get(index).setForeground(foreground);
        if (foreground == null || oldFg == null ||
            !foreground.equals(oldFg)) {
            Rectangle tabBounds = getBoundsAt(index);
            if (tabBounds != null) {
                repaint(tabBounds);
            }
        }
    }

    /**
     * Sets whether or not the tab at <code>index</code> is enabled.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index which should be enabled/disabled
     * @param enabled whether or not the tab should be enabled
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #isEnabledAt
     */
    public void setEnabledAt(int index, boolean enabled) {
        boolean oldEnabled = pages.get(index).isEnabled();
        pages.get(index).setEnabled(enabled);
        if (enabled != oldEnabled) {
            revalidate();
            repaint();
        }
    }

    /**
     * Sets the component at <code>index</code> to <code>component</code>.
     * An internal exception is raised if there is no tab at that index.
     *
     * @param index the tab index where this component is being placed
     * @param component the component for the tab
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index &lt; 0 || index &gt;= tab count)
     *
     * @see #getComponentAt
     * @beaninfo
     *    attribute: visualUpdate true
     *  description: The component at the specified tab index.
     */
    public void setComponentAt(int index, Component component) {
        Page page = pages.get(index);
        if (component != page.component) {
            boolean shouldChangeFocus = false;

            if (page.component != null) {
                shouldChangeFocus =
                    (SwingUtilities.findFocusOwner(page.component) != null);

                // REMIND(aim): this is really silly;
                // why not if (page.component.getParent() == this) remove(component)
                synchronized(getTreeLock()) {
                    int count = getComponentCount();
                    Component children[] = getComponents();
                    for (int i = 0; i < count; i++) {
                        if (children[i] == page.component) {
                            super.remove(i);
                        }
                    }
                }
            }

            page.component = component;
            boolean selectedPage = (getSelectedIndex() == index);

            if (selectedPage) {
                this.visComp = component;
            }

            if (component != null) {
                component.setVisible(selectedPage);
                addImpl(component, null, -1);

                if (shouldChangeFocus) {
                    SwingUtilities2.tabbedPaneChangeFocusTo(component);
                }
            } else {
                repaint();
            }

            revalidate();
        }
    }

    /**
     * Provides a hint to the look and feel as to which character in the
     * text should be decorated to represent the mnemonic. Not all look and
     * feels may support this. A value of -1 indicates either there is
     * no mnemonic for this tab, or you do not wish the mnemonic to be
     * displayed for this tab.
     * <p>
     * The value of this is updated as the properties relating to the
     * mnemonic change (such as the mnemonic itself, the text...).
     * You should only ever have to call this if
     * you do not wish the default character to be underlined. For example, if
     * the text at tab index 3 was 'Apple Price', with a mnemonic of 'p',
     * and you wanted the 'P'
     * to be decorated, as 'Apple <u>P</u>rice', you would have to invoke
     * <code>setDisplayedMnemonicIndex(3, 6)</code> after invoking
     * <code>setMnemonicAt(3, KeyEvent.VK_P)</code>.
     * <p>Note that it is the programmer's responsibility to ensure
     * that each tab has a unique mnemonic or unpredictable results may
     * occur.
     *
     * @since 1.4
     * @param tabIndex the index of the tab that the mnemonic refers to
     * @param mnemonicIndex index into the <code>String</code> to underline
     * @exception IndexOutOfBoundsException if <code>tabIndex</code> is
     *            out of range (<code>tabIndex < 0 || tabIndex >= tab
     *            count</code>)
     * @exception IllegalArgumentException will be thrown if
     *            <code>mnemonicIndex</code> is &gt;= length of the tab
     *            title , or &lt; -1
     * @see #setMnemonicAt(int,int)
     * @see #getDisplayedMnemonicIndexAt(int)
     *
     * @beaninfo
     *        bound: true
     *    attribute: visualUpdate true
     *  description: the index into the String to draw the keyboard character
     *               mnemonic at
     */
    public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex) {
        checkIndex(tabIndex);

        Page page = pages.get(tabIndex);

        page.setDisplayedMnemonicIndex(mnemonicIndex);
    }

    /**
     * Sets the keyboard mnemonic for accessing the specified tab.
     * The mnemonic is the key which when combined with the look and feel's
     * mouseless modifier (usually Alt) will activate the specified
     * tab.
     * <p>
     * A mnemonic must correspond to a single key on the keyboard
     * and should be specified using one of the <code>VK_XXX</code>
     * keycodes defined in <code>java.awt.event.KeyEvent</code>.
     * Mnemonics are case-insensitive, therefore a key event
     * with the corresponding keycode would cause the button to be
     * activated whether or not the Shift modifier was pressed.
     * <p>
     * This will update the displayed mnemonic property for the specified
     * tab.
     *
     * @since 1.4
     * @param tabIndex the index of the tab that the mnemonic refers to
     * @param mnemonic the key code which represents the mnemonic
     * @exception IndexOutOfBoundsException if <code>tabIndex</code> is out
     *            of range (<code>tabIndex < 0 || tabIndex >= tab count</code>)
     * @see #getMnemonicAt(int)
     * @see #setDisplayedMnemonicIndexAt(int,int)
     *
     * @beaninfo
     *        bound: true
     *    attribute: visualUpdate true
     *  description: The keyboard mnenmonic, as a KeyEvent VK constant,
     *               for the specified tab
     */
    public void setMnemonicAt(int tabIndex, int mnemonic) {
        checkIndex(tabIndex);

        Page page = pages.get(tabIndex);
        page.setMnemonic(mnemonic);

        firePropertyChange("mnemonicAt", null, null);
    }

// end of Page setters

    /**
     * Returns the first tab index with a given <code>title</code>,  or
     * -1 if no tab has this title.
     *
     * @param title the title for the tab
     * @return the first tab index which matches <code>title</code>, or
     *          -1 if no tab has this title
     */
    public int indexOfTab(String title) {
        for(int i = 0; i < getTabCount(); i++) {
            if (getTitleAt(i).equals(title == null? "" : title)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns the first tab index with a given <code>icon</code>,
     * or -1 if no tab has this icon.
     *
     * @param icon the icon for the tab
     * @return the first tab index which matches <code>icon</code>,
     *          or -1 if no tab has this icon
     */
    public int indexOfTab(Icon icon) {
        for(int i = 0; i < getTabCount(); i++) {
            Icon tabIcon = getIconAt(i);
            if ((tabIcon != null && tabIcon.equals(icon)) ||
                (tabIcon == null && tabIcon == icon)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns the index of the tab for the specified component.
     * Returns -1 if there is no tab for this component.
     *
     * @param component the component for the tab
     * @return the first tab which matches this component, or -1
     *          if there is no tab for this component
     */
    public int indexOfComponent(Component component) {
        for(int i = 0; i < getTabCount(); i++) {
            Component c = getComponentAt(i);
            if ((c != null && c.equals(component)) ||
                (c == null && c == component)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns the tab index corresponding to the tab whose bounds
     * intersect the specified location.  Returns -1 if no tab
     * intersects the location.
     *
     * @param x the x location relative to this tabbedpane
     * @param y the y location relative to this tabbedpane
     * @return the tab index which intersects the location, or
     *         -1 if no tab intersects the location
     * @since 1.4
     */
    public int indexAtLocation(int x, int y) {
        if (ui != null) {
            return ((TabbedPaneUI)ui).tabForCoordinate(this, x, y);
        }
        return -1;
    }


    /**
     * Returns the tooltip text for the component determined by the
     * mouse event location.
     *
     * @param event  the <code>MouseEvent</code> that tells where the
     *          cursor is lingering
     * @return the <code>String</code> containing the tooltip text
     */
    public String getToolTipText(MouseEvent event) {
        if (ui != null) {
            int index = ((TabbedPaneUI)ui).tabForCoordinate(this, event.getX(), event.getY());

            if (index != -1) {
                return pages.get(index).tip;
            }
        }
        return super.getToolTipText(event);
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= pages.size()) {
            throw new IndexOutOfBoundsException("Index: "+index+", Tab count: "+pages.size());
        }
    }


    /**
     * 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 (getUIClassID().equals(uiClassID)) {
            byte count = JComponent.getWriteObjCounter(this);
            JComponent.setWriteObjCounter(this, --count);
            if (count == 0 && ui != null) {
                ui.installUI(this);
            }
        }
    }

    /* Called from the <code>JComponent</code>'s
     * <code>EnableSerializationFocusListener</code> to
     * do any Swing-specific pre-serialization configuration.
     */
    void compWriteObjectNotify() {
        super.compWriteObjectNotify();
        // If ToolTipText != null, then the tooltip has already been
        // unregistered by JComponent.compWriteObjectNotify()
        if (getToolTipText() == null && haveRegistered) {
            ToolTipManager.sharedInstance().unregisterComponent(this);
        }
    }

    /**
     * See <code>readObject</code> and <code>writeObject</code> in
     * <code>JComponent</code> for more
     * information about serialization in Swing.
     */
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException
    {
        s.defaultReadObject();
        if ((ui != null) && (getUIClassID().equals(uiClassID))) {
            ui.installUI(this);
        }
        // If ToolTipText != null, then the tooltip has already been
        // registered by JComponent.readObject()
        if (getToolTipText() == null && haveRegistered) {
            ToolTipManager.sharedInstance().registerComponent(this);
        }
    }


    /**
     * Returns a string representation of this <code>JTabbedPane</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 JTabbedPane.
     */
    protected String paramString() {
        String tabPlacementString;
        if (tabPlacement == TOP) {
            tabPlacementString = "TOP";
        } else if (tabPlacement == BOTTOM) {
            tabPlacementString = "BOTTOM";
        } else if (tabPlacement == LEFT) {
            tabPlacementString = "LEFT";
        } else if (tabPlacement == RIGHT) {
            tabPlacementString = "RIGHT";
        } else tabPlacementString = "";
        String haveRegisteredString = (haveRegistered ?
                                       "true" : "false");

        return super.paramString() +
        ",haveRegistered=" + haveRegisteredString +
        ",tabPlacement=" + tabPlacementString;
    }

/////////////////
// Accessibility support
////////////////

    /**
     * Gets the AccessibleContext associated with this JTabbedPane.
     * For tabbed panes, the AccessibleContext takes the form of an
     * AccessibleJTabbedPane.
     * A new AccessibleJTabbedPane instance is created if necessary.
     *
     * @return an AccessibleJTabbedPane that serves as the
     *         AccessibleContext of this JTabbedPane
     */
    public AccessibleContext getAccessibleContext() {
        if (accessibleContext == null) {
            accessibleContext = new AccessibleJTabbedPane();

            // initialize AccessibleContext for the existing pages
            int count = getTabCount();
            for (int i = 0; i < count; i++) {
                pages.get(i).initAccessibleContext();
            }
        }
        return accessibleContext;
    }

    /**
     * This class implements accessibility support for the
     * <code>JTabbedPane</code> class.  It provides an implementation of the
     * Java Accessibility API appropriate to tabbed pane user-interface
     * elements.
     * <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.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    protected class AccessibleJTabbedPane extends AccessibleJComponent
        implements AccessibleSelection, ChangeListener {

        /**
         * Returns the accessible name of this object, or {@code null} if
         * there is no accessible name.
         *
         * @return the accessible name of this object, nor {@code null}.
         * @since 1.6
         */
        public String getAccessibleName() {
            if (accessibleName != null) {
                return accessibleName;
            }

            String cp = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);

            if (cp != null) {
                return cp;
            }

            int index = getSelectedIndex();

            if (index >= 0) {
                return pages.get(index).getAccessibleName();
            }

            return super.getAccessibleName();
        }

        /**
         *  Constructs an AccessibleJTabbedPane
         */
        public AccessibleJTabbedPane() {
            super();
            JTabbedPane.this.model.addChangeListener(this);
        }

        public void stateChanged(ChangeEvent e) {
            Object o = e.getSource();
            firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
                               null, o);
        }

        /**
         * Get the role of this object.
         *
         * @return an instance of AccessibleRole describing the role of
         *          the object
         */
        public AccessibleRole getAccessibleRole() {
            return AccessibleRole.PAGE_TAB_LIST;
        }

        /**
         * Returns the number of accessible children in the object.
         *
         * @return the number of accessible children in the object.
         */
        public int getAccessibleChildrenCount() {
            return getTabCount();
        }

        /**
         * Return the specified Accessible child of the object.
         *
         * @param i zero-based index of child
         * @return the Accessible child of the object
         * @exception IllegalArgumentException if index is out of bounds
         */
        public Accessible getAccessibleChild(int i) {
            if (i < 0 || i >= getTabCount()) {
                return null;
            }
            return pages.get(i);
        }

        /**
         * Gets the <code>AccessibleSelection</code> associated with
         * this object.  In the implementation of the Java
         * Accessibility API for this class,
         * returns this object, which is responsible for implementing the
         * <code>AccessibleSelection</code> interface on behalf of itself.
         *
         * @return this object
         */
        public AccessibleSelection getAccessibleSelection() {
           return this;
        }

        /**
         * Returns the <code>Accessible</code> child contained at
         * the local coordinate <code>Point</code>, if one exists.
         * Otherwise returns the currently selected tab.
         *
         * @return the <code>Accessible</code> at the specified
         *    location, if it exists
         */
        public Accessible getAccessibleAt(Point p) {
            int tab = ((TabbedPaneUI) ui).tabForCoordinate(JTabbedPane.this,
                                                           p.x, p.y);
            if (tab == -1) {
                tab = getSelectedIndex();
            }
            return getAccessibleChild(tab);
        }

        public int getAccessibleSelectionCount() {
            return 1;
        }

        public Accessible getAccessibleSelection(int i) {
            int index = getSelectedIndex();
            if (index == -1) {
                return null;
            }
            return pages.get(index);
        }

        public boolean isAccessibleChildSelected(int i) {
            return (i == getSelectedIndex());
        }

        public void addAccessibleSelection(int i) {
           setSelectedIndex(i);
        }

        public void removeAccessibleSelection(int i) {
           // can't do
        }

        public void clearAccessibleSelection() {
           // can't do
        }

        public void selectAllAccessibleSelection() {
           // can't do
        }
    }

    private class Page extends AccessibleContext
        implements Serializable, Accessible, AccessibleComponent {
        String title;
        Color background;
        Color foreground;
        Icon icon;
        Icon disabledIcon;
        JTabbedPane parent;
        Component component;
        String tip;
        boolean enabled = true;
        boolean needsUIUpdate;
        int mnemonic = -1;
        int mnemonicIndex = -1;
        Component tabComponent;

        Page(JTabbedPane parent,
             String title, Icon icon, Icon disabledIcon, Component component, String tip) {
            this.title = title;
            this.icon = icon;
            this.disabledIcon = disabledIcon;
            this.parent = parent;
            this.setAccessibleParent(parent);
            this.component = component;
            this.tip = tip;

            initAccessibleContext();
        }

        /*
         * initializes the AccessibleContext for the page
         */
        void initAccessibleContext() {
            if (JTabbedPane.this.accessibleContext != null &&
                component instanceof Accessible) {
                /*
                 * Do initialization if the AccessibleJTabbedPane
                 * has been instantiated. We do not want to load
                 * Accessibility classes unnecessarily.
                 */
                AccessibleContext ac;
                ac = ((Accessible) component).getAccessibleContext();
                if (ac != null) {
                    ac.setAccessibleParent(this);
                }
            }
        }

        void setMnemonic(int mnemonic) {
            this.mnemonic = mnemonic;
            updateDisplayedMnemonicIndex();
        }

        int getMnemonic() {
            return mnemonic;
        }

        /*
         * Sets the page displayed mnemonic index
         */
        void setDisplayedMnemonicIndex(int mnemonicIndex) {
            if (this.mnemonicIndex != mnemonicIndex) {
                if (mnemonicIndex != -1 && (title == null ||
                        mnemonicIndex < 0 ||
                        mnemonicIndex >= title.length())) {
                    throw new IllegalArgumentException(
                                "Invalid mnemonic index: " + mnemonicIndex);
                }
                this.mnemonicIndex = mnemonicIndex;
                JTabbedPane.this.firePropertyChange("displayedMnemonicIndexAt",
                                                    null, null);
            }
        }

        /*
         * Returns the page displayed mnemonic index
         */
        int getDisplayedMnemonicIndex() {
            return this.mnemonicIndex;
        }

        void updateDisplayedMnemonicIndex() {
            setDisplayedMnemonicIndex(
                SwingUtilities.findDisplayedMnemonicIndex(title, mnemonic));
        }

        /////////////////
        // Accessibility support
        ////////////////

        public AccessibleContext getAccessibleContext() {
            return this;
        }


        // AccessibleContext methods

        public String getAccessibleName() {
            if (accessibleName != null) {
                return accessibleName;
            } else if (title != null) {
                return title;
            }
            return null;
        }

        public String getAccessibleDescription() {
            if (accessibleDescription != null) {
                return accessibleDescription;
            } else if (tip != null) {
                return tip;
            }
            return null;
        }

        public AccessibleRole getAccessibleRole() {
            return AccessibleRole.PAGE_TAB;
        }

        public AccessibleStateSet getAccessibleStateSet() {
            AccessibleStateSet states;
            states = parent.getAccessibleContext().getAccessibleStateSet();
            states.add(AccessibleState.SELECTABLE);
            int i = parent.indexOfTab(title);
            if (i == parent.getSelectedIndex()) {
                states.add(AccessibleState.SELECTED);
            }
            return states;
        }

        public int getAccessibleIndexInParent() {
            return parent.indexOfTab(title);
        }

        public int getAccessibleChildrenCount() {
            if (component instanceof Accessible) {
                return 1;
            } else {
                return 0;
            }
        }

        public Accessible getAccessibleChild(int i) {
            if (component instanceof Accessible) {
                return (Accessible) component;
            } else {
                return null;
            }
        }

        public Locale getLocale() {
            return parent.getLocale();
        }

        public AccessibleComponent getAccessibleComponent() {
            return this;
        }


        // AccessibleComponent methods

        public Color getBackground() {
            return background != null? background : parent.getBackground();
        }

        public void setBackground(Color c) {
            background = c;
        }

        public Color getForeground() {
            return foreground != null? foreground : parent.getForeground();
        }

        public void setForeground(Color c) {
            foreground = c;
        }

        public Cursor getCursor() {
            return parent.getCursor();
        }

        public void setCursor(Cursor c) {
            parent.setCursor(c);
        }

        public Font getFont() {
            return parent.getFont();
        }

        public void setFont(Font f) {
            parent.setFont(f);
        }

        public FontMetrics getFontMetrics(Font f) {
            return parent.getFontMetrics(f);
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean b) {
            enabled = b;
        }

        public boolean isVisible() {
            return parent.isVisible();
        }

        public void setVisible(boolean b) {
            parent.setVisible(b);
        }

        public boolean isShowing() {
            return parent.isShowing();
        }

        public boolean contains(Point p) {
            Rectangle r = getBounds();
            return r.contains(p);
        }

        public Point getLocationOnScreen() {
             Point parentLocation = parent.getLocationOnScreen();
             Point componentLocation = getLocation();
             componentLocation.translate(parentLocation.x, parentLocation.y);
             return componentLocation;
        }

        public Point getLocation() {
             Rectangle r = getBounds();
             return new Point(r.x, r.y);
        }

        public void setLocation(Point p) {
            // do nothing
        }

        public Rectangle getBounds() {
            return parent.getUI().getTabBounds(parent,
                                               parent.indexOfTab(title));
        }

        public void setBounds(Rectangle r) {
            // do nothing
        }

        public Dimension getSize() {
            Rectangle r = getBounds();
            return new Dimension(r.width, r.height);
        }

        public void setSize(Dimension d) {
            // do nothing
        }

        public Accessible getAccessibleAt(Point p) {
            if (component instanceof Accessible) {
                return (Accessible) component;
            } else {
                return null;
            }
        }

        public boolean isFocusTraversable() {
            return false;
        }

        public void requestFocus() {
            // do nothing
        }

        public void addFocusListener(FocusListener l) {
            // do nothing
        }

        public void removeFocusListener(FocusListener l) {
            // do nothing
        }

        // TIGER - 4732339
        /**
         * Returns an AccessibleIcon
         *
         * @return the enabled icon if one exists and the page
         * is enabled. Otherwise, returns the disabled icon if
         * one exists and the page is disabled.  Otherwise, null
         * is returned.
         */
        public AccessibleIcon [] getAccessibleIcon() {
            AccessibleIcon accessibleIcon = null;
            if (enabled && icon instanceof ImageIcon) {
                AccessibleContext ac =
                    ((ImageIcon)icon).getAccessibleContext();
                accessibleIcon = (AccessibleIcon)ac;
            } else if (!enabled && disabledIcon instanceof ImageIcon) {
                AccessibleContext ac =
                    ((ImageIcon)disabledIcon).getAccessibleContext();
                accessibleIcon = (AccessibleIcon)ac;
            }
            if (accessibleIcon != null) {
                AccessibleIcon [] returnIcons = new AccessibleIcon[1];
                returnIcons[0] = accessibleIcon;
                return returnIcons;
            } else {
                return null;
            }
        }
    }

    /**
    * Sets the component that is responsible for rendering the
    * title for the specified tab.  A null value means
    * <code>JTabbedPane</code> will render the title and/or icon for
    * the specified tab.  A non-null value means the component will
    * render the title and <code>JTabbedPane</code> will not render
    * the title and/or icon.
    * <p>
    * Note: The component must not be one that the developer has
    *       already added to the tabbed pane.
    *
    * @param index the tab index where the component should be set
    * @param component the component to render the title for the
    *                  specified tab
    * @exception IndexOutOfBoundsException if index is out of range
    *            (index < 0 || index >= tab count)
    * @exception IllegalArgumentException if component has already been
    *            added to this <code>JTabbedPane</code>
    *
    * @see #getTabComponentAt
    * @beaninfo
    *    preferred: true
    *    attribute: visualUpdate true
    *  description: The tab component at the specified tab index.
    * @since 1.6
    */
    public void setTabComponentAt(int index, Component component) {
        if (component != null && indexOfComponent(component) != -1) {
            throw new IllegalArgumentException("Component is already added to this JTabbedPane");
        }
        Component oldValue = getTabComponentAt(index);
        if (component != oldValue) {
            int tabComponentIndex = indexOfTabComponent(component);
            if (tabComponentIndex != -1) {
                setTabComponentAt(tabComponentIndex, null);
            }
            pages.get(index).tabComponent = component;
            firePropertyChange("indexForTabComponent", -1, index);
        }
    }

    /**
     * Returns the tab component at <code>index</code>.
     *
     * @param index  the index of the item being queried
     * @return the tab component at <code>index</code>
     * @exception IndexOutOfBoundsException if index is out of range
     *            (index < 0 || index >= tab count)
     *
     * @see #setTabComponentAt
     * @since 1.6
     */
    public Component getTabComponentAt(int index) {
        return pages.get(index).tabComponent;
    }

    /**
     * Returns the index of the tab for the specified tab component.
     * Returns -1 if there is no tab for this tab component.
     *
     * @param tabComponent the tab component for the tab
     * @return the first tab which matches this tab component, or -1
     *          if there is no tab for this tab component
     * @see #setTabComponentAt
     * @see #getTabComponentAt
     * @since 1.6
     */
     public int indexOfTabComponent(Component tabComponent) {
        for(int i = 0; i < getTabCount(); i++) {
            Component c = getTabComponentAt(i);
            if (c == tabComponent) {
                return i;
            }
        }
        return -1;
    }
}
