- /*
- * @(#)JTabbedPane.java 1.140 04/04/02
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- 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 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>
- * <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.
- *
- * @version 1.140 04/02/04
- * @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;
-
- Vector pages;
-
- /**
- * 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 Vector(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 = ((Page)pages.elementAt(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</code>, whose source is this tabbedpane,
- * to each listener. This method method is called each time
- * a <code>ChangeEvent</code> is received from the model.
- *
- * @see #addChangeListener
- * @see EventListenerList
- */
- protected void fireStateChanged() {
- // 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);
- }
-
-
- private void setSelectedIndexImpl(int index) {
- int oldIndex = model.getSelectedIndex();
- Page oldPage = null, newPage = null;
- if ((oldIndex >= 0) && (oldIndex != index)) {
- oldPage = (Page) pages.elementAt(oldIndex);
- }
- if ((index >= 0) && (oldIndex != index)) {
- newPage = (Page) pages.elementAt(index);
- }
-
- model.setSelectedIndex(index);
-
- String oldName = null;
- String newName = null;
-
- if (oldPage != null) {
- oldPage.firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- AccessibleState.SELECTED, null);
- // TIGER - 4840667
- AccessibleContext ac = oldPage.getAccessibleContext();
- if (ac != null) {
- oldName = ac.getAccessibleName();
- }
-
- }
- if (newPage != null) {
- newPage.firePropertyChange(
- AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
- null, AccessibleState.SELECTED);
- // TIGER - 4840667
- AccessibleContext ac = newPage.getAccessibleContext();
- if (ac != null) {
- newName = ac.getAccessibleName();
- }
-
- }
-
- // TIGER - 4840667
- if (newName != null) {
- getAccessibleContext().firePropertyChange(
- AccessibleContext.ACCESSIBLE_NAME_PROPERTY, oldName, newName);
- }
-
- }
-
- /**
- * 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 <code>component</code>, at <code>index</code>,
- * represented by a <code>title</code> and/or <code>icon</code>,
- * either of which may be <code>null</code>.
- * Uses java.util.Vector internally, see <code>insertElementAt</code>
- * for details of insertion conventions.
- *
- * @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
- * @param index the position to insert this new tab
- *
- * @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.insertElementAt(new Page(this, title != null? title : "", icon, null,
- component, tip), newIndex);
-
-
- if (component != null) {
- addImpl(component, null, -1);
- component.setVisible(false);
- }
-
- if (pages.size() == 1) {
- setSelectedIndex(0);
- }
-
- if (selectedIndex >= newIndex) {
- setSelectedIndex(selectedIndex + 1);
- }
-
- 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);
-
- // If we are removing the currently selected tab AND
- // it happens to be the last tab in the bunch, then
- // select the previous tab
- int tabCount = getTabCount();
- int selected = getSelectedIndex();
- if (selected >= (tabCount - 1)) {
- setSelectedIndexImpl(selected - 1);
- }
-
- Component component = getComponentAt(index);
-
- if (accessibleContext != null) {
- accessibleContext.firePropertyChange(
- AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
- component, null);
- }
-
- pages.removeElementAt(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));
-
- // 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;
- }
- }
- }
-
- 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);
-
- 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 ((Page)pages.elementAt(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 ((Page)pages.elementAt(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 = ((Page)pages.elementAt(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
- */
- public String getToolTipTextAt(int index) {
- return ((Page)pages.elementAt(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 ((Page)pages.elementAt(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 ((Page)pages.elementAt(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 ((Page)pages.elementAt(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 ((Page)pages.elementAt(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> < 0 ||
- * <code>tabIndex</code> >= tab count)
- * @see #setDisplayedMnemonicIndexAt(int,int)
- * @see #setMnemonicAt(int,int)
- */
- public int getMnemonicAt(int tabIndex) {
- checkIndex(tabIndex);
-
- Page page = (Page)pages.elementAt(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> < 0 ||
- * <code>tabIndex</code> >= tab count)
- * @see #setDisplayedMnemonicIndexAt(int,int)
- * @see #setMnemonicAt(int,int)
- */
- public int getDisplayedMnemonicIndexAt(int tabIndex) {
- checkIndex(tabIndex);
-
- Page page = (Page)pages.elementAt(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 < 0 || index >= 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>.
- * 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 < 0 || index >= tab count)
- *
- * @see #getTitleAt
- * @beaninfo
- * preferred: true
- * attribute: visualUpdate true
- * description: The title at the specified tab index.
- */
- public void setTitleAt(int index, String title) {
- Page page = (Page)pages.elementAt(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>.
- * 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
- * @beaninfo
- * preferred: true
- * attribute: visualUpdate true
- * description: The icon at the specified tab index.
- */
- public void setIconAt(int index, Icon icon) {
- Page page = (Page)pages.elementAt(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 < 0 || index >= 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 = ((Page)pages.elementAt(index)).disabledIcon;
- ((Page)pages.elementAt(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 < 0 || index >= tab count)
- *
- * @see #getToolTipTextAt
- * @beaninfo
- * preferred: true
- * description: The tooltip text at the specified tab index.
- */
- public void setToolTipTextAt(int index, String toolTipText) {
- String oldToolTipText =((Page)pages.elementAt(index)).tip;
- ((Page)pages.elementAt(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 < 0 || index >= 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 = ((Page)pages.elementAt(index)).background;
- ((Page)pages.elementAt(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 < 0 || index >= 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 = ((Page)pages.elementAt(index)).foreground;
- ((Page)pages.elementAt(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 < 0 || index >= tab count)
- *
- * @see #isEnabledAt
- */
- public void setEnabledAt(int index, boolean enabled) {
- boolean oldEnabled = ((Page)pages.elementAt(index)).isEnabled();
- ((Page)pages.elementAt(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 < 0 || index >= 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 = (Page)pages.elementAt(index);
- if (component != page.component) {
- if (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;
- component.setVisible(getSelectedIndex() == index);
- addImpl(component, null, -1);
-
- 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 >= length of the tab
- * title , or < -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 = (Page)pages.elementAt(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 = (Page)pages.elementAt(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 ((Page)pages.elementAt(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();
- }
- 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 {
-
- /**
- * 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 (Accessible) pages.elementAt(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 (Accessible) pages.elementAt(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;
-
- 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;
- if (component instanceof Accessible) {
- 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;
- }
- }
- }
- }