| /* JTabbedPane.java -- |
| Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.swing; |
| |
| import java.awt.Color; |
| import java.awt.Component; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.event.MouseEvent; |
| import java.io.Serializable; |
| import java.util.Locale; |
| import java.util.Vector; |
| |
| import javax.accessibility.Accessible; |
| import javax.accessibility.AccessibleContext; |
| import javax.accessibility.AccessibleRole; |
| import javax.accessibility.AccessibleSelection; |
| import javax.accessibility.AccessibleState; |
| import javax.accessibility.AccessibleStateSet; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import javax.swing.plaf.TabbedPaneUI; |
| import javax.swing.plaf.UIResource; |
| |
| /** |
| * This is a container for components where only one component is displayed at |
| * a given time and the displayed component can be switched by clicking on |
| * tabs. |
| * |
| * <p> |
| * Tabs can be oriented in several ways. They can be above, below, left and |
| * right of the component. Tabs can either wrap around (by creating multiple |
| * rows of tabs) or they can be scrolled (where only a subset of the tabs |
| * can be seen at once). More tabs can be added by calling the |
| * add/addTab/insertTab methods. |
| * </p> |
| */ |
| public class JTabbedPane extends JComponent implements Serializable, |
| Accessible, |
| SwingConstants |
| { |
| /** |
| * Accessibility support for <code>JTabbedPane</code>. |
| */ |
| protected class AccessibleJTabbedPane extends JComponent.AccessibleJComponent |
| implements AccessibleSelection, ChangeListener |
| { |
| /** |
| * The serialization UID. |
| */ |
| private static final long serialVersionUID = 7610530885966830483L; |
| |
| /** |
| * Creates a new AccessibleJTabbedPane object. |
| */ |
| public AccessibleJTabbedPane() |
| { |
| super(); |
| } |
| |
| /** |
| * Receives notification when the selection state of the |
| * <code>JTabbedPane</code> changes and fires appropriate property change |
| * events to interested listeners. |
| * |
| * @param e the change event describing the change |
| */ |
| public void stateChanged(ChangeEvent e) |
| { |
| // I couldn't figure out what else should be done here. |
| Object source = e.getSource(); |
| firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, |
| null, source); |
| } |
| |
| /** |
| * Returns the accessible role of the <code>JTabbedPane</code>, which is |
| * {@link AccessibleRole#PAGE_TAB_LIST}. |
| * |
| * @return the accessible role of the <code>JTabbedPane</code> |
| */ |
| public AccessibleRole getAccessibleRole() |
| { |
| return AccessibleRole.PAGE_TAB_LIST; |
| } |
| |
| /** |
| * Returns the number of accessible child components of the |
| * <code>JTabbedPane</code>. |
| * |
| * @return the number of accessible child components of the |
| * <code>JTabbedPane</code> |
| */ |
| public int getAccessibleChildrenCount() |
| { |
| return getTabCount(); |
| } |
| |
| /** |
| * Returns the accessible child component at the specified index. |
| * |
| * @param i the index of the child component to fetch |
| * |
| * @return the accessible child component at the specified index |
| */ |
| public Accessible getAccessibleChild(int i) |
| { |
| // Testing shows that the reference implementation returns instances |
| // of page here. |
| Accessible child = null; |
| if (i >= 0 && i < tabs.size()) |
| child = (Page) tabs.get(i); |
| return child; |
| } |
| |
| /** |
| * Returns the current selection state of the <code>JTabbedPane</code> |
| * as AccessibleSelection object. |
| * |
| * @return the current selection state of the <code>JTabbedPane</code> |
| */ |
| public AccessibleSelection getAccessibleSelection() |
| { |
| return this; |
| } |
| |
| /** |
| * Returns the accessible child component at the specified coordinates. |
| * If there is no child component at this location, then return the |
| * currently selected tab. |
| * |
| * @param p the coordinates at which to look up the child component |
| * |
| * @return the accessible child component at the specified coordinates or |
| * the currently selected tab if there is no child component at |
| * this location |
| */ |
| public Accessible getAccessibleAt(Point p) |
| { |
| int tabIndex = indexAtLocation(p.x, p.y); |
| if (tabIndex >= 0) |
| return getAccessibleChild(tabIndex); |
| else |
| return getAccessibleSelection(0); |
| } |
| |
| /** |
| * Returns the number of selected child components of the |
| * <code>JTabbedPane</code>. The reference implementation appears |
| * to return <code>1</code> always and we do the same. |
| * |
| * @return <code>1</code> |
| */ |
| public int getAccessibleSelectionCount() |
| { |
| return 1; |
| } |
| |
| /** |
| * Returns the selected tab, or <code>null</code> if there is no |
| * selection. |
| * |
| * @param i the selection index (ignored here). |
| * |
| * @return The selected tab, or <code>null</code>. |
| */ |
| public Accessible getAccessibleSelection(int i) |
| { |
| Accessible result = null; |
| int selected = getSelectedIndex(); |
| if (selected >= 0) |
| result = (Page) tabs.get(selected); |
| return result; |
| } |
| |
| /** |
| * Returns <code>true</code> if the specified child is selected, |
| * and <code>false</code> otherwise. |
| * |
| * @param i the child index. |
| * |
| * @return A boolean. |
| */ |
| public boolean isAccessibleChildSelected(int i) |
| { |
| return i == getSelectedIndex(); |
| } |
| |
| /** |
| * Selects the specified tab. |
| * |
| * @param i the index of the item to select. |
| */ |
| public void addAccessibleSelection(int i) |
| { |
| setSelectedIndex(i); |
| } |
| |
| /** |
| * Does nothing - it makes no sense to remove a selection for a |
| * tabbed pane, since one tab must always be selected. |
| * |
| * @param i the item index. |
| * |
| * @see #addAccessibleSelection(int) |
| */ |
| public void removeAccessibleSelection(int i) |
| { |
| // do nothing |
| } |
| |
| /** |
| * Does nothing - it makes no sense to clear the selection for |
| * a tabbed pane, since one tab must always be selected. |
| * |
| * @see #addAccessibleSelection(int) |
| */ |
| public void clearAccessibleSelection() |
| { |
| // do nothing |
| } |
| |
| /** |
| * Does nothing - it makes no sense to select all for a tabbed |
| * pane, since only one tab can be selected at a time. |
| * |
| * @see #addAccessibleSelection(int) |
| */ |
| public void selectAllAccessibleSelection() |
| { |
| // do nothing |
| } |
| } |
| |
| /** |
| * A helper class that listens for changes to the model. |
| */ |
| protected class ModelListener implements ChangeListener, Serializable |
| { |
| private static final long serialVersionUID = 497359819958114132L; |
| |
| /** |
| * Creates a new ModelListener object. |
| */ |
| protected ModelListener() |
| { |
| // Nothing to do here. |
| } |
| |
| /** |
| * This method is called whenever the model is changed. |
| * |
| * @param e The ChangeEvent that is passed from the model. |
| */ |
| public void stateChanged(ChangeEvent e) |
| { |
| // Propagate to our listeners. |
| fireStateChanged(); |
| } |
| } |
| |
| /** |
| * A private class that holds all the information for each tab. |
| */ |
| private class Page |
| extends AccessibleContext |
| implements Accessible |
| { |
| /** The tooltip string. */ |
| private String tip; |
| |
| /** The component associated with the tab. */ |
| private Component component; |
| |
| /** The active icon associated with the tab. */ |
| private transient Icon icon; |
| |
| /** The disabled icon associated with the tab. */ |
| private transient Icon disabledIcon; |
| |
| /** The tab's enabled status. */ |
| private transient boolean enabled = true; |
| |
| /** The string painted on the tab. */ |
| private transient String title; |
| |
| /** The background color of the tab. */ |
| private transient Color bg; |
| |
| /** The foreground color of the tab. */ |
| private transient Color fg; |
| |
| /** The mnemonic associated with the tab. */ |
| private transient int mnemonicKey; |
| |
| /** The index of the underlined character in the string. */ |
| private transient int underlinedChar = -1; |
| |
| /** |
| * Creates a new data storage for the tab. |
| * |
| * @param title The string displayed on the tab. |
| * @param icon The active icon displayed on the tab. |
| * @param component The component associated with the tab. |
| * @param tip The tooltip associated with the tab. |
| */ |
| protected Page(String title, Icon icon, Component component, String tip) |
| { |
| this.title = title; |
| this.icon = icon; |
| this.component = component; |
| this.tip = tip; |
| } |
| |
| /** |
| * This method returns the component associated with the tab. |
| * |
| * @return The component associated with the tab. |
| */ |
| public Component getComponent() |
| { |
| return component; |
| } |
| |
| /** |
| * This method sets the component associated with the tab. |
| * |
| * @param c The component associated with the tab. |
| */ |
| public void setComponent(Component c) |
| { |
| int i = indexOfComponent(component); |
| insertTab(title, icon, c, tip, i); |
| component = c; |
| removeTabAt(i); |
| } |
| |
| /** |
| * This method returns the tooltip string. |
| * |
| * @return The tooltip string. |
| */ |
| public String getTip() |
| { |
| return tip; |
| } |
| |
| /** |
| * This method sets the tooltip string. |
| * |
| * @param tip The tooltip string. |
| */ |
| public void setTip(String tip) |
| { |
| this.tip = tip; |
| } |
| |
| /** |
| * This method returns the background color. |
| * |
| * @return The background color. |
| */ |
| public Color getBackground() |
| { |
| Color background; |
| if (bg == null) |
| background = JTabbedPane.this.getBackground(); |
| else |
| background = bg; |
| return background; |
| } |
| |
| /** |
| * This method sets the background color. |
| * |
| * @param background The background color. |
| */ |
| public void setBackground(Color background) |
| { |
| bg = background; |
| } |
| |
| /** |
| * This method returns the foreground color. |
| * |
| * @return The foreground color. |
| */ |
| public Color getForeground() |
| { |
| Color foreground; |
| if (fg == null) |
| foreground = JTabbedPane.this.getForeground(); |
| else |
| foreground = fg; |
| return foreground; |
| } |
| |
| /** |
| * This method sets the foreground color. |
| * |
| * @param foreground The foreground color. |
| */ |
| public void setForeground(Color foreground) |
| { |
| fg = foreground; |
| } |
| |
| /** |
| * This method returns the title associated with the tab. |
| * |
| * @return The title of the tab. |
| */ |
| public String getTitle() |
| { |
| return title; |
| } |
| |
| private static final long serialVersionUID = 1614381073220130939L; |
| |
| /** |
| * This method sets the title of the tab. |
| * |
| * @param text The title of the tab. |
| */ |
| public void setTitle(String text) |
| { |
| title = text; |
| if (title != null && title.length() <= underlinedChar) |
| setDisplayedMnemonicIndex(title.length() - 1); |
| } |
| |
| /** |
| * This method returns the active icon. |
| * |
| * @return The active icon. |
| */ |
| public Icon getIcon() |
| { |
| return icon; |
| } |
| |
| /** |
| * This method sets the active icon. |
| * |
| * @param icon The active icon. |
| */ |
| public void setIcon(Icon icon) |
| { |
| this.icon = icon; |
| } |
| |
| /** |
| * This method returns the disabled icon. |
| * |
| * @return The disabled icon. |
| */ |
| public Icon getDisabledIcon() |
| { |
| if (disabledIcon == null && icon instanceof ImageIcon) |
| setDisabledIcon(icon); |
| return disabledIcon; |
| } |
| |
| /** |
| * This method sets the disabled icon. |
| * |
| * @param disabledIcon The disabled icon. |
| */ |
| public void setDisabledIcon(Icon disabledIcon) |
| { |
| this.disabledIcon = disabledIcon; |
| } |
| |
| /** |
| * This method returns whether the tab is enabled. |
| * |
| * @return Whether the tab is enabled. |
| */ |
| public boolean isEnabled() |
| { |
| return enabled; |
| } |
| |
| /** |
| * This method sets whether the tab is enabled. |
| * |
| * @param enabled Whether this tab is enabled. |
| */ |
| public void setEnabled(boolean enabled) |
| { |
| this.enabled = enabled; |
| } |
| |
| /** |
| * This method returns the mnemonic. |
| * |
| * @return The mnemonic. |
| */ |
| public int getMnemonic() |
| { |
| return mnemonicKey; |
| } |
| |
| /** |
| * This method sets the mnemonic. If the title is set, it will update the |
| * mnemonicIndex. |
| * |
| * @param key The mnemonic. |
| */ |
| public void setMnemonic(int key) |
| { |
| setMnemonic((char) key); |
| } |
| |
| /** |
| * This method sets the mnemonic. If the title is set, it will update the |
| * mnemonicIndex. |
| * |
| * @param aChar The mnemonic. |
| */ |
| public void setMnemonic(char aChar) |
| { |
| mnemonicKey = aChar; |
| if (title != null) |
| setDisplayedMnemonicIndex(title.indexOf(mnemonicKey)); |
| } |
| |
| /** |
| * This method returns the mnemonicIndex. |
| * |
| * @return The mnemonicIndex. |
| */ |
| public int getDisplayedMnemonicIndex() |
| { |
| return underlinedChar; |
| } |
| |
| /** |
| * This method sets the mnemonicIndex. |
| * |
| * @param index The mnemonicIndex. |
| * |
| * @throws IllegalArgumentException If index less than -1 || index greater |
| * or equal to title.length. |
| */ |
| public void setDisplayedMnemonicIndex(int index) |
| throws IllegalArgumentException |
| { |
| if (index < -1 || title != null && index >= title.length()) |
| throw new IllegalArgumentException(); |
| |
| if (title == null || mnemonicKey == 0 || (index > -1 && title.charAt(index) != mnemonicKey)) |
| index = -1; |
| |
| underlinedChar = index; |
| } |
| |
| /** |
| * Returns the accessible context, which is this object itself. |
| * |
| * @return the accessible context, which is this object itself |
| */ |
| public AccessibleContext getAccessibleContext() |
| { |
| return this; |
| } |
| |
| /** |
| * Returns the accessible name for this tab. |
| * |
| * @return The accessible name. |
| */ |
| public String getAccessibleName() |
| { |
| if (accessibleName != null) |
| return accessibleName; |
| else |
| return title; |
| } |
| |
| /** |
| * Returns the accessible role of this tab, which is always |
| * {@link AccessibleRole#PAGE_TAB}. |
| * |
| * @return the accessible role of this tab |
| */ |
| public AccessibleRole getAccessibleRole() |
| { |
| return AccessibleRole.PAGE_TAB; |
| } |
| |
| /** |
| * Returns the accessible state set of this object. |
| * |
| * @return the accessible state set of this object |
| */ |
| public AccessibleStateSet getAccessibleStateSet() |
| { |
| AccessibleContext parentCtx = JTabbedPane.this.getAccessibleContext(); |
| AccessibleStateSet state = parentCtx.getAccessibleStateSet(); |
| state.add(AccessibleState.SELECTABLE); |
| if (component == getSelectedComponent()) |
| state.add(AccessibleState.SELECTED); |
| return state; |
| } |
| |
| /** |
| * Returns the index of this tab inside its parent. |
| * |
| * @return the index of this tab inside its parent |
| */ |
| public int getAccessibleIndexInParent() |
| { |
| // TODO: Not sure if the title is unambiguous, but I can't figure |
| // another way of doing this. |
| return indexOfTab(title); |
| } |
| |
| /** |
| * Returns the number of accessible children, which is always one (the |
| * component of this tab). |
| * |
| * @return the number of accessible children |
| */ |
| public int getAccessibleChildrenCount() |
| { |
| return 1; |
| } |
| |
| /** |
| * Returns the accessible child of this tab, which is the component |
| * displayed by the tab. |
| * |
| * @return the accessible child of this tab |
| */ |
| public Accessible getAccessibleChild(int i) |
| { |
| // A quick test shows that this method always returns the component |
| // displayed by the tab, regardless of the index. |
| return (Accessible) component; |
| } |
| |
| /** |
| * Returns the locale of this accessible object. |
| * |
| * @return the locale of this accessible object |
| */ |
| public Locale getLocale() |
| { |
| // TODO: Is this ok? |
| return Locale.getDefault(); |
| } |
| } |
| |
| private static final long serialVersionUID = 1614381073220130939L; |
| |
| /** The changeEvent used to fire changes to listeners. */ |
| protected ChangeEvent changeEvent; |
| |
| /** The listener that listens to the model. */ |
| protected ChangeListener changeListener; |
| |
| /** The model that describes this JTabbedPane. */ |
| protected SingleSelectionModel model; |
| |
| /** Indicates that the TabbedPane is in scrolling mode. */ |
| public static final int SCROLL_TAB_LAYOUT = 1; |
| |
| /** Indicates that the TabbedPane is in wrap mode. */ |
| public static final int WRAP_TAB_LAYOUT = 0; |
| |
| /** The current tabPlacement of the TabbedPane. */ |
| protected int tabPlacement = SwingConstants.TOP; |
| |
| /** The current tabLayoutPolicy of the TabbedPane. */ |
| private transient int layoutPolicy; |
| |
| /** The list of tabs associated with the TabbedPane. */ |
| transient Vector tabs = new Vector(); |
| |
| /** |
| * Creates a new JTabbedPane object with tabs on top and using wrap tab |
| * layout. |
| */ |
| public JTabbedPane() |
| { |
| this(SwingConstants.TOP, WRAP_TAB_LAYOUT); |
| } |
| |
| /** |
| * Creates a new JTabbedPane object using wrap tab layout and the given |
| * <code>tabPlacement</code>, where <code>tabPlacement</code> can be one |
| * of the following values: {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} or |
| * {@link #RIGHT}. |
| * |
| * @param tabPlacement where the tabs will be placed |
| */ |
| public JTabbedPane(int tabPlacement) |
| { |
| this(tabPlacement, WRAP_TAB_LAYOUT); |
| } |
| |
| /** |
| * Creates a new JTabbedPane object with the given <code>tabPlacement</code> |
| * and <code>tabLayoutPolicy</code>. The <code>tabPlacement</code> can be one |
| * of the following values: {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} or |
| * {@link #RIGHT}. The <code>tabLayoutPolicy</code> can be either |
| * {@link #SCROLL_TAB_LAYOUT} or {@link #WRAP_TAB_LAYOUT}. |
| * |
| * @param tabPlacement where the tabs will be placed |
| * @param tabLayoutPolicy the way tabs will be placed |
| * |
| * @throws IllegalArgumentException If tabLayoutPolicy or tabPlacement are |
| * not valid. |
| */ |
| public JTabbedPane(int tabPlacement, int tabLayoutPolicy) |
| { |
| if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT |
| && tabPlacement != LEFT) |
| throw new IllegalArgumentException("tabPlacement is not valid."); |
| if (tabLayoutPolicy != SCROLL_TAB_LAYOUT |
| && tabLayoutPolicy != WRAP_TAB_LAYOUT) |
| throw new IllegalArgumentException("tabLayoutPolicy is not valid."); |
| this.tabPlacement = tabPlacement; |
| layoutPolicy = tabLayoutPolicy; |
| |
| changeEvent = new ChangeEvent(this); |
| changeListener = createChangeListener(); |
| |
| model = new DefaultSingleSelectionModel(); |
| model.addChangeListener(changeListener); |
| |
| updateUI(); |
| } |
| |
| /** |
| * This method returns the UI used to display the JTabbedPane. |
| * |
| * @return The UI used to display the JTabbedPane. |
| */ |
| public TabbedPaneUI getUI() |
| { |
| return (TabbedPaneUI) ui; |
| } |
| |
| /** |
| * This method sets the UI used to display the JTabbedPane. |
| * |
| * @param ui The UI used to display the JTabbedPane. |
| */ |
| public void setUI(TabbedPaneUI ui) |
| { |
| super.setUI(ui); |
| } |
| |
| /** |
| * This method restores the UI to the defaults given by the UIManager. |
| */ |
| public void updateUI() |
| { |
| setUI((TabbedPaneUI) UIManager.getUI(this)); |
| } |
| |
| /** |
| * This method returns a string identifier that is used to determine which |
| * UI will be used with the JTabbedPane. |
| * |
| * @return A string identifier for the UI. |
| */ |
| public String getUIClassID() |
| { |
| return "TabbedPaneUI"; |
| } |
| |
| /** |
| * This method creates a ChangeListener that is used to listen to the model |
| * for events. |
| * |
| * @return A ChangeListener to listen to the model. |
| */ |
| protected ChangeListener createChangeListener() |
| { |
| return new ModelListener(); |
| } |
| |
| /** |
| * This method adds a ChangeListener to the JTabbedPane. |
| * |
| * @param l The ChangeListener to add. |
| */ |
| public void addChangeListener(ChangeListener l) |
| { |
| listenerList.add(ChangeListener.class, l); |
| } |
| |
| /** |
| * This method removes a ChangeListener to the JTabbedPane. |
| * |
| * @param l The ChangeListener to remove. |
| */ |
| public void removeChangeListener(ChangeListener l) |
| { |
| listenerList.remove(ChangeListener.class, l); |
| } |
| |
| /** |
| * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners. |
| */ |
| protected void fireStateChanged() |
| { |
| Object[] changeListeners = listenerList.getListenerList(); |
| if (changeEvent == null) |
| changeEvent = new ChangeEvent(this); |
| for (int i = changeListeners.length - 2; i >= 0; i -= 2) |
| { |
| if (changeListeners[i] == ChangeListener.class) |
| ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent); |
| } |
| } |
| |
| /** |
| * This method returns all ChangeListeners registered with the JTabbedPane. |
| * |
| * @return The ChangeListeners registered with the JTabbedPane. |
| */ |
| public ChangeListener[] getChangeListeners() |
| { |
| return (ChangeListener[]) super.getListeners(ChangeListener.class); |
| } |
| |
| /** |
| * This method returns the model used with the JTabbedPane. |
| * |
| * @return The JTabbedPane's model. |
| */ |
| public SingleSelectionModel getModel() |
| { |
| return model; |
| } |
| |
| /** |
| * This method changes the model property of the JTabbedPane. |
| * |
| * @param model The new model to use with the JTabbedPane. |
| */ |
| public void setModel(SingleSelectionModel model) |
| { |
| if (model != this.model) |
| { |
| SingleSelectionModel oldModel = this.model; |
| this.model.removeChangeListener(changeListener); |
| this.model = model; |
| this.model.addChangeListener(changeListener); |
| firePropertyChange("model", oldModel, this.model); |
| } |
| } |
| |
| /** |
| * This method returns the tabPlacement. |
| * |
| * @return The tabPlacement used with the JTabbedPane. |
| */ |
| public int getTabPlacement() |
| { |
| return tabPlacement; |
| } |
| |
| /** |
| * This method changes the tabPlacement property of the JTabbedPane. |
| * |
| * @param tabPlacement The tabPlacement to use. |
| * |
| * @throws IllegalArgumentException If tabPlacement is not one of TOP, |
| * BOTTOM, LEFT, or RIGHT. |
| */ |
| public void setTabPlacement(int tabPlacement) |
| { |
| if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT |
| && tabPlacement != LEFT) |
| throw new IllegalArgumentException("tabPlacement is not valid."); |
| if (tabPlacement != this.tabPlacement) |
| { |
| int oldPlacement = this.tabPlacement; |
| this.tabPlacement = tabPlacement; |
| firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement); |
| } |
| } |
| |
| /** |
| * This method returns the tabLayoutPolicy. |
| * |
| * @return The tabLayoutPolicy. |
| */ |
| public int getTabLayoutPolicy() |
| { |
| return layoutPolicy; |
| } |
| |
| /** |
| * This method changes the tabLayoutPolicy property of the JTabbedPane. |
| * |
| * @param tabLayoutPolicy The tabLayoutPolicy to use. |
| * |
| * @throws IllegalArgumentException If tabLayoutPolicy is not one of |
| * SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT. |
| */ |
| public void setTabLayoutPolicy(int tabLayoutPolicy) |
| { |
| if (tabLayoutPolicy != SCROLL_TAB_LAYOUT |
| && tabLayoutPolicy != WRAP_TAB_LAYOUT) |
| throw new IllegalArgumentException("tabLayoutPolicy is not valid."); |
| if (tabLayoutPolicy != layoutPolicy) |
| { |
| int oldPolicy = layoutPolicy; |
| layoutPolicy = tabLayoutPolicy; |
| firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy); |
| } |
| } |
| |
| /** |
| * This method returns the index of the tab that is currently selected. |
| * |
| * @return The index of the selected tab. |
| */ |
| public int getSelectedIndex() |
| { |
| return model.getSelectedIndex(); |
| } |
| |
| /** |
| * This method checks the index. |
| * |
| * @param index The index to check. |
| * @param start DOCUMENT ME! |
| * @param end DOCUMENT ME! |
| * |
| * @throws IndexOutOfBoundsException DOCUMENT ME! |
| */ |
| private void checkIndex(int index, int start, int end) |
| { |
| if (index < start || index >= end) |
| throw new IndexOutOfBoundsException("Index < " + start + " || Index >= " |
| + end); |
| } |
| |
| /** |
| * This method sets the selected index. This method will hide the old |
| * component and show the new component. |
| * |
| * @param index The index to set it at. |
| */ |
| public void setSelectedIndex(int index) |
| { |
| checkIndex(index, -1, tabs.size()); |
| if (index != getSelectedIndex()) |
| { |
| // Hiding and showing the involved components |
| // is done by the JTabbedPane's UI. |
| model.setSelectedIndex(index); |
| } |
| } |
| |
| /** |
| * This method returns the component at the selected index. |
| * |
| * @return The component at the selected index. |
| */ |
| public Component getSelectedComponent() |
| { |
| int selectedIndex = getSelectedIndex(); |
| Component selected = null; |
| if (selectedIndex >= 0) |
| selected = getComponentAt(selectedIndex); |
| return selected; |
| } |
| |
| /** |
| * This method sets the component at the selected index. |
| * |
| * @param c The component associated with the selected index. |
| */ |
| public void setSelectedComponent(Component c) |
| { |
| if (c.getParent() == this) |
| setSelectedIndex(indexOfComponent(c)); |
| else |
| setComponentAt(getSelectedIndex(), c); |
| } |
| |
| /** |
| * This method inserts tabs into JTabbedPane. This includes adding the |
| * component to the JTabbedPane and hiding it. |
| * |
| * @param title the title of the tab; may be <code>null</code> |
| * @param icon the tab's icon; may be <code>null</code> |
| * @param component the component associated with the tab |
| * @param tip the tooltip for the tab |
| * @param index the index to insert the tab at |
| */ |
| public void insertTab(String title, Icon icon, Component component, |
| String tip, int index) |
| { |
| if (title == null) |
| title = ""; |
| Page p = new Page(title, icon, component, tip); |
| tabs.insertElementAt(p, index); |
| |
| // Hide the component so we don't see it. Do it before we parent it |
| // so we don't trigger a repaint. |
| if (component != null) |
| { |
| component.hide(); |
| super.add(component); |
| } |
| |
| if (getSelectedIndex() == -1) |
| setSelectedIndex(0); |
| |
| revalidate(); |
| repaint(); |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. |
| * |
| * @param title the title of the tab; may be <code>null</code> |
| * @param icon the icon for the tab; may be <code>null</code> |
| * @param component the associated component |
| * @param tip the associated tooltip |
| */ |
| public void addTab(String title, Icon icon, Component component, String tip) |
| { |
| insertTab(title, icon, component, tip, tabs.size()); |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. |
| * |
| * @param title the title of the tab; may be <code>null</code> |
| * @param icon the icon for the tab; may be <code>null</code> |
| * @param component the associated component |
| */ |
| public void addTab(String title, Icon icon, Component component) |
| { |
| insertTab(title, icon, component, null, tabs.size()); |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. |
| * |
| * @param title the title of the tab; may be <code>null</code> |
| * @param component the associated component |
| */ |
| public void addTab(String title, Component component) |
| { |
| insertTab(title, null, component, null, tabs.size()); |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. The title of the tab is the |
| * Component's name. If the Component is an instance of UIResource, it |
| * doesn't add the tab and instead add the component directly to the |
| * JTabbedPane. |
| * |
| * @param component The associated component. |
| * |
| * @return The Component that was added. |
| */ |
| public Component add(Component component) |
| { |
| if (component instanceof UIResource) |
| super.add(component); |
| else |
| insertTab(component.getName(), null, component, null, tabs.size()); |
| |
| return component; |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. If the Component is an |
| * instance of UIResource, it doesn't add the tab and instead add the |
| * component directly to the JTabbedPane. |
| * |
| * @param title the title of the tab; may be <code>null</code> |
| * @param component the associated component |
| * |
| * @return The Component that was added. |
| */ |
| public Component add(String title, Component component) |
| { |
| if (component instanceof UIResource) |
| super.add(component); |
| else |
| insertTab(title, null, component, null, tabs.size()); |
| return component; |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. If the Component is an |
| * instance of UIResource, it doesn't add the tab and instead add the |
| * component directly to the JTabbedPane. |
| * |
| * @param component The associated component. |
| * @param index The index to insert the tab at. |
| * |
| * @return The Component that was added. |
| */ |
| public Component add(Component component, int index) |
| { |
| if (component instanceof UIResource) |
| super.add(component); |
| else |
| insertTab(component.getName(), null, component, null, index); |
| return component; |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. If the Component is an |
| * instance of UIResource, it doesn't add the tab and instead add the |
| * component directly to the JTabbedPane. If the constraints object is an |
| * icon, it will be used as the tab's icon. If the constraints object is a |
| * string, we will use it as the title. |
| * |
| * @param component The associated component. |
| * @param constraints The constraints object. |
| */ |
| public void add(Component component, Object constraints) |
| { |
| add(component, constraints, tabs.size()); |
| } |
| |
| /** |
| * This method adds a tab to the JTabbedPane. If the Component is an |
| * instance of UIResource, it doesn't add the tab and instead add the |
| * component directly to the JTabbedPane. If the constraints object is an |
| * icon, it will be used as the tab's icon. If the constraints object is a |
| * string, we will use it as the title. |
| * |
| * @param component The associated component. |
| * @param constraints The constraints object. |
| * @param index The index to insert the tab at. |
| */ |
| public void add(Component component, Object constraints, int index) |
| { |
| if (component instanceof UIResource) |
| super.add(component); |
| else |
| { |
| if (constraints instanceof String) |
| insertTab((String) constraints, null, component, null, index); |
| else |
| insertTab(component.getName(), |
| (constraints instanceof Icon) ? (Icon) constraints : null, |
| component, null, index); |
| } |
| } |
| |
| /** |
| * Removes the tab at index. After the component associated with |
| * index 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 remove. |
| */ |
| public void removeTabAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| |
| // We need to adjust the selection if we remove a tab that comes |
| // before the selected tab or if the selected tab is removed. |
| // This decrements the selected index by 1 if any of this is the case. |
| // Note that this covers all cases: |
| // - When the selected tab comes after the removed tab, this simply |
| // adjusts the selection so that after the removal the selected tab |
| // is still the same. |
| // - When we remove the currently selected tab, then the tab before the |
| // selected tab gets selected. |
| // - When the last tab is removed, then we have an index==0, which gets |
| // decremented to -1, which means no selection, which is 100% perfect. |
| int selectedIndex = getSelectedIndex(); |
| if (selectedIndex >= index) |
| setSelectedIndex(selectedIndex - 1); |
| |
| Component comp = getComponentAt(index); |
| |
| // Remove the tab object. |
| tabs.remove(index); |
| |
| // Remove the component. I think we cannot assume that the tab order |
| // is equal to the component order, so we iterate over the children |
| // here to find the and remove the correct component. |
| if (comp != null) |
| { |
| Component[] children = getComponents(); |
| for (int i = children.length - 1; i >= 0; --i) |
| { |
| if (children[i] == comp) |
| { |
| super.remove(i); |
| comp.setVisible(true); |
| break; |
| } |
| } |
| } |
| revalidate(); |
| repaint(); |
| } |
| |
| /** |
| * Removes the specified Component from the JTabbedPane. |
| * |
| * @param component The Component to remove. |
| */ |
| public void remove(Component component) |
| { |
| // Since components implementing UIResource |
| // are not added as regular tabs by the add() |
| // methods we have to take special care when |
| // removing these object. Especially |
| // Container.remove(Component) cannot be used |
| // because it will call JTabbedPane.remove(int) |
| // later which is overridden and can only |
| // handle tab components. |
| // This implementation can even cope with a |
| // situation that someone called insertTab() |
| // with a component that implements UIResource. |
| int index = indexOfComponent(component); |
| |
| // If the component is not a tab component |
| // find out its Container-given index |
| // and call that class' implementation |
| // directly. |
| if (index == -1) |
| { |
| Component[] cs = getComponents(); |
| for (int i = 0; i< cs.length; i++) |
| if (cs[i] == component) |
| super.remove(i); |
| } |
| else |
| removeTabAt(index); |
| } |
| |
| /** |
| * Removes the tab and component which corresponds to the specified index. |
| * |
| * @param index The index of the tab to remove. |
| */ |
| public void remove(int index) |
| { |
| removeTabAt(index); |
| } |
| |
| /** |
| * This method removes all tabs and associated components from the |
| * JTabbedPane. |
| */ |
| public void removeAll() |
| { |
| setSelectedIndex(-1); |
| for (int i = getTabCount() - 1; i >= 0; i--) |
| removeTabAt(i); |
| } |
| |
| /** |
| * This method returns how many tabs are in the JTabbedPane. |
| * |
| * @return The number of tabs in the JTabbedPane. |
| */ |
| public int getTabCount() |
| { |
| return tabs.size(); |
| } |
| |
| /** |
| * This method returns the number of runs used to paint the JTabbedPane. |
| * |
| * @return The number of runs. |
| */ |
| public int getTabRunCount() |
| { |
| return ((TabbedPaneUI) ui).getTabRunCount(this); |
| } |
| |
| /** |
| * This method returns the tab title given the index. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The title for the tab. |
| */ |
| public String getTitleAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getTitle(); |
| } |
| |
| /** |
| * This method returns the active icon given the index. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The active icon for the tab. |
| */ |
| public Icon getIconAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getIcon(); |
| } |
| |
| /** |
| * This method returns the disabled icon given the index. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The disabled icon for the tab. |
| */ |
| public Icon getDisabledIconAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getDisabledIcon(); |
| } |
| |
| /** |
| * This method returns the tooltip string for the tab. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The tooltip string for the tab. |
| */ |
| public String getToolTipTextAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getTip(); |
| } |
| |
| /** |
| * This method returns the foreground color for the tab. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The foreground color for the tab. |
| */ |
| public Color getForegroundAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getForeground(); |
| } |
| |
| /** |
| * This method returns the background color for the tab. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The background color for the tab. |
| */ |
| public Color getBackgroundAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getBackground(); |
| } |
| |
| /** |
| * This method returns the component associated with the tab. |
| * |
| * @param index The index of the tab. |
| * |
| * @return The component associated with the tab. |
| */ |
| public Component getComponentAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).getComponent(); |
| } |
| |
| /** |
| * This method returns whether this tab is enabled. Disabled tabs cannot be |
| * selected. |
| * |
| * @param index The index of the tab. |
| * |
| * @return Whether the tab is enabled. |
| */ |
| public boolean isEnabledAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((Page) tabs.elementAt(index)).isEnabled(); |
| } |
| |
| /** |
| * This method returns the mnemonic for the tab. |
| * |
| * @param tabIndex The index of the tab. |
| * |
| * @return The mnemonic for the tab. |
| */ |
| public int getMnemonicAt(int tabIndex) |
| { |
| checkIndex(tabIndex, 0, tabs.size()); |
| return ((Page) tabs.elementAt(tabIndex)).getMnemonic(); |
| } |
| |
| /** |
| * This method returns the mnemonic index for the tab. |
| * |
| * @param tabIndex The index of the tab. |
| * |
| * @return The mnemonic index for the tab. |
| */ |
| public int getDisplayedMnemonicIndexAt(int tabIndex) |
| { |
| checkIndex(tabIndex, 0, tabs.size()); |
| return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex(); |
| } |
| |
| /** |
| * This method returns the bounds of the tab given the index. |
| * |
| * @param index The index of the tab. |
| * |
| * @return A rectangle describing the bounds of the tab. |
| */ |
| public Rectangle getBoundsAt(int index) |
| { |
| checkIndex(index, 0, tabs.size()); |
| return ((TabbedPaneUI) ui).getTabBounds(this, index); |
| } |
| |
| /** |
| * This method sets the title of the tab. |
| * |
| * @param index The index of the tab. |
| * @param title The new title. |
| */ |
| public void setTitleAt(int index, String title) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setTitle(title); |
| } |
| |
| /** |
| * This method sets the icon of the tab. |
| * |
| * @param index The index of the tab. |
| * @param icon The new icon. |
| */ |
| public void setIconAt(int index, Icon icon) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setIcon(icon); |
| } |
| |
| /** |
| * This method sets the disabled icon of the tab. |
| * |
| * @param index The index of the tab. |
| * @param disabledIcon The new disabled icon. |
| */ |
| public void setDisabledIconAt(int index, Icon disabledIcon) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon); |
| } |
| |
| /** |
| * This method sets the tooltip text of the tab. |
| * |
| * @param index The index of the tab. |
| * @param toolTipText The tooltip text. |
| */ |
| public void setToolTipTextAt(int index, String toolTipText) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setTip(toolTipText); |
| } |
| |
| /** |
| * This method sets the background color of the tab. |
| * |
| * @param index The index of the tab. |
| * @param background The background color of the tab. |
| */ |
| public void setBackgroundAt(int index, Color background) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setBackground(background); |
| } |
| |
| /** |
| * This method sets the foreground color of the tab. |
| * |
| * @param index The index of the tab. |
| * @param foreground The foreground color of the tab. |
| */ |
| public void setForegroundAt(int index, Color foreground) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setForeground(foreground); |
| } |
| |
| /** |
| * This method sets whether the tab is enabled. |
| * |
| * @param index The index of the tab. |
| * @param enabled Whether the tab is enabled. |
| */ |
| public void setEnabledAt(int index, boolean enabled) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setEnabled(enabled); |
| } |
| |
| /** |
| * This method sets the component associated with the tab. |
| * |
| * @param index The index of the tab. |
| * @param component The component associated with the tab. |
| */ |
| public void setComponentAt(int index, Component component) |
| { |
| checkIndex(index, 0, tabs.size()); |
| ((Page) tabs.elementAt(index)).setComponent(component); |
| } |
| |
| /** |
| * This method sets the displayed mnemonic index of the tab. |
| * |
| * @param tabIndex The index of the tab. |
| * @param mnemonicIndex The mnemonic index. |
| */ |
| public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex) |
| { |
| checkIndex(tabIndex, 0, tabs.size()); |
| ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex); |
| } |
| |
| /** |
| * This method sets the mnemonic for the tab. |
| * |
| * @param tabIndex The index of the tab. |
| * @param mnemonic The mnemonic. |
| */ |
| public void setMnemonicAt(int tabIndex, int mnemonic) |
| { |
| checkIndex(tabIndex, 0, tabs.size()); |
| ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic); |
| } |
| |
| /** |
| * This method finds the index of a tab given the title. |
| * |
| * @param title The title that belongs to a tab. |
| * |
| * @return The index of the tab that has the title or -1 if not found. |
| */ |
| public int indexOfTab(String title) |
| { |
| int index = -1; |
| for (int i = 0; i < tabs.size(); i++) |
| { |
| if (((Page) tabs.elementAt(i)).getTitle().equals(title)) |
| { |
| index = i; |
| break; |
| } |
| } |
| return index; |
| } |
| |
| /** |
| * This method finds the index of a tab given the icon. |
| * |
| * @param icon The icon that belongs to a tab. |
| * |
| * @return The index of the tab that has the icon or -1 if not found. |
| */ |
| public int indexOfTab(Icon icon) |
| { |
| int index = -1; |
| for (int i = 0; i < tabs.size(); i++) |
| { |
| if (((Page) tabs.elementAt(i)).getIcon() == icon) |
| { |
| index = i; |
| break; |
| } |
| } |
| return index; |
| } |
| |
| /** |
| * This method finds the index of a tab given the component. |
| * |
| * @param component A component associated with a tab. |
| * |
| * @return The index of the tab that has this component or -1 if not found. |
| */ |
| public int indexOfComponent(Component component) |
| { |
| int index = -1; |
| for (int i = 0; i < tabs.size(); i++) |
| { |
| if (((Page) tabs.elementAt(i)).getComponent() == component) |
| { |
| index = i; |
| break; |
| } |
| } |
| return index; |
| } |
| |
| /** |
| * This method returns a tab index given an (x,y) location. The origin of |
| * the (x,y) pair will be the JTabbedPane's top left position. The tab |
| * returned will be the one that contains the point. This method is |
| * delegated to the UI. |
| * |
| * @param x The x coordinate of the point. |
| * @param y The y coordinate of the point. |
| * |
| * @return The index of the tab that contains the point. |
| */ |
| public int indexAtLocation(int x, int y) |
| { |
| return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y); |
| } |
| |
| /** |
| * This method returns the tooltip text given a mouse event. |
| * |
| * @param event The mouse event. |
| * |
| * @return The tool tip text that is associated with this mouse event. |
| */ |
| public String getToolTipText(MouseEvent event) |
| { |
| int index = indexAtLocation(event.getX(), event.getY()); |
| return ((Page) tabs.elementAt(index)).getTip(); |
| } |
| |
| /** |
| * Returns a string describing the attributes for the |
| * <code>JTabbedPane</code> component, for use in debugging. The return |
| * value is guaranteed to be non-<code>null</code>, but the format of the |
| * string may vary between implementations. |
| * |
| * @return A string describing the attributes of the |
| * <code>JTabbedPane</code>. |
| */ |
| protected String paramString() |
| { |
| StringBuffer sb = new StringBuffer(super.paramString()); |
| sb.append(",tabPlacement="); |
| if (tabPlacement == TOP) |
| sb.append("TOP"); |
| if (tabPlacement == BOTTOM) |
| sb.append("BOTTOM"); |
| if (tabPlacement == LEFT) |
| sb.append("LEFT"); |
| if (tabPlacement == RIGHT) |
| sb.append("RIGHT"); |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the object that provides accessibility features for this |
| * <code>JTabbedPane</code> component. |
| * |
| * @return The accessible context (an instance of |
| * {@link AccessibleJTabbedPane}). |
| */ |
| public AccessibleContext getAccessibleContext() |
| { |
| if (accessibleContext == null) |
| { |
| AccessibleJTabbedPane ctx = new AccessibleJTabbedPane(); |
| addChangeListener(ctx); |
| accessibleContext = ctx; |
| } |
| |
| return accessibleContext; |
| } |
| } |