/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing; import java.awt.*;import java.awt.event.*;import java.beans.Transient;import java.util.*;import javax.swing.event.*;import javax.swing.plaf.*;import javax.accessibility.*;import sun.swing.SwingUtilities2; import java.io.Serializable;import java.io.ObjectOutputStream;import java.io.ObjectInputStream;import java.io.IOException; /** * A component that lets the user switch between a group of components by * clicking on a tab with a given title and/or icon. * For examples and information on using tabbed panes see * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/tabbedpane.html">How to Use Tabbed Panes</a>, * a section in <em>The Java Tutorial</em>. * <p> * Tabs/components are added to a <code>TabbedPane</code> object by using the * <code>addTab</code> and <code>insertTab</code> methods. * A tab is represented by an index corresponding * to the position it was added in, where the first tab has an index equal to 0 * and the last tab has an index equal to the tab count minus 1. * <p> * The <code>TabbedPane</code> uses a <code>SingleSelectionModel</code> * to represent the set * of tab indices and the currently selected index. If the tab count * is greater than 0, then there will always be a selected index, which * by default will be initialized to the first tab. If the tab count is * 0, then the selected index will be -1. * <p> * The tab title can be rendered by a <code>Component</code>. * For example, the following produce similar results: * <pre> * // In this case the look and feel renders the title for the tab. * tabbedPane.addTab("Tab", myComponent); * // In this case the custom component is responsible for rendering the * // title of the tab. * tabbedPane.addTab(null, myComponent); * tabbedPane.setTabComponentAt(0, new JLabel("Tab")); * </pre> * The latter is typically used when you want a more complex user interaction * that requires custom components on the tab. For example, you could * provide a custom component that animates or one that has widgets for * closing the tab. * <p> * If you specify a component for a tab, the <code>JTabbedPane</code> * will not render any text or icon you have specified for the tab. * <p> * <strong>Note:</strong> * Do not use <code>setVisible</code> directly on a tab component to make it visible, * use <code>setSelectedComponent</code> or <code>setSelectedIndex</code> methods instead. * <p> * <strong>Warning:</strong> Swing is not thread safe. For more * information see <a * href="package-summary.html#threading">Swing's Threading * Policy</a>. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @beaninfo * attribute: isContainer true * description: A component which provides a tab folder metaphor for * displaying one component from a set of components. * * @author Dave Moore * @author Philip Milne * @author Amy Fowler * * @see SingleSelectionModel */public class JTabbedPane extends JComponent implements Serializable, Accessible, SwingConstants { /** * The tab layout policy for wrapping tabs in multiple runs when all * tabs will not fit within a single run. */ public static final int WRAP_TAB_LAYOUT = 0; /** * Tab layout policy for providing a subset of available tabs when all * the tabs will not fit within a single run. If all the tabs do * not fit within a single run the look and feel will provide a way * to navigate to hidden tabs. */ public static final int SCROLL_TAB_LAYOUT = 1; /** * @see #getUIClassID * @see #readObject */ private static final String uiClassID = "TabbedPaneUI"; /** * Where the tabs are placed. * @see #setTabPlacement */ protected int tabPlacement = TOP; private int tabLayoutPolicy; /** The default selection model */ protected SingleSelectionModel model; private boolean haveRegistered; /** * The <code>changeListener</code> is the listener we add to the * model. */ protected ChangeListener changeListener = null; private final java.util.List<Page> pages; /* The component that is currently visible */ private Component visComp = null; /** * Only one <code>ChangeEvent</code> is needed per <code>TabPane</code> * instance since the * event's only (read-only) state is the source property. The source * of events generated here is always "this". */ protected transient ChangeEvent changeEvent = null; /** * Creates an empty <code>TabbedPane</code> with a default * tab placement of <code>JTabbedPane.TOP</code>. * @see #addTab */ public JTabbedPane() { this(TOP, WRAP_TAB_LAYOUT); } /** * Creates an empty <code>TabbedPane</code> with the specified tab placement * of either: <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>, * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>. * * @param tabPlacement the placement for the tabs relative to the content * @see #addTab */ public JTabbedPane(int tabPlacement) { this(tabPlacement, WRAP_TAB_LAYOUT); } /** * Creates an empty <code>TabbedPane</code> with the specified tab placement * and tab layout policy. Tab placement may be either: * <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>, * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>. * Tab layout policy may be either: <code>JTabbedPane.WRAP_TAB_LAYOUT</code> * or <code>JTabbedPane.SCROLL_TAB_LAYOUT</code>. * * @param tabPlacement the placement for the tabs relative to the content * @param tabLayoutPolicy the policy for laying out tabs when all tabs will not fit on one run * @exception IllegalArgumentException if tab placement or tab layout policy are not * one of the above supported values * @see #addTab * @since 1.4 */ public JTabbedPane(int tabPlacement, int tabLayoutPolicy) { setTabPlacement(tabPlacement); setTabLayoutPolicy(tabLayoutPolicy); pages = new ArrayList<Page>(1); setModel(new DefaultSingleSelectionModel()); updateUI(); } /** * Returns the UI object which implements the L&F for this component. * * @return a <code>TabbedPaneUI</code> object * @see #setUI */ public TabbedPaneUI getUI() { return (TabbedPaneUI)ui; } /** * Sets the UI object which implements the L&F for this component. * * @param ui the new UI object * @see UIDefaults#getUI * @beaninfo * bound: true * hidden: true * attribute: visualUpdate true * description: The UI object that implements the tabbedpane's LookAndFeel */ public void setUI(TabbedPaneUI ui) { super.setUI(ui); // disabled icons are generated by LF so they should be unset here for (int i = 0; i < getTabCount(); i++) { Icon icon = pages.get(i).disabledIcon; if (icon instanceof UIResource) { setDisabledIconAt(i, null); } } } /** * Resets the UI property to a value from the current look and feel. * * @see JComponent#updateUI */ public void updateUI() { setUI((TabbedPaneUI)UIManager.getUI(this)); } /** * Returns the name of the UI class that implements the * L&F for this component. * * @return the string "TabbedPaneUI" * @see JComponent#getUIClassID * @see UIDefaults#getUI */ public String getUIClassID() { return uiClassID; } /** * We pass <code>ModelChanged</code> events along to the listeners with * the tabbedpane (instead of the model itself) as the event source. */ protected class ModelListener implements ChangeListener, Serializable { public void stateChanged(ChangeEvent e) { fireStateChanged(); } } /** * Subclasses that want to handle <code>ChangeEvents</code> differently * can override this to return a subclass of <code>ModelListener</code> or * another <code>ChangeListener</code> implementation. * * @see #fireStateChanged */ protected ChangeListener createChangeListener() { return new ModelListener(); } /** * Adds a <code>ChangeListener</code> to this tabbedpane. * * @param l the <code>ChangeListener</code> to add * @see #fireStateChanged * @see #removeChangeListener */ public void addChangeListener(ChangeListener l) { listenerList.add(ChangeListener.class, l); } /** * Removes a <code>ChangeListener</code> from this tabbedpane. * * @param l the <code>ChangeListener</code> to remove * @see #fireStateChanged * @see #addChangeListener */ public void removeChangeListener(ChangeListener l) { listenerList.remove(ChangeListener.class, l); } /** * Returns an array of all the <code>ChangeListener</code>s added * to this <code>JTabbedPane</code> with <code>addChangeListener</code>. * * @return all of the <code>ChangeListener</code>s added or an empty * array if no listeners have been added * @since 1.4 */ public ChangeListener[] getChangeListeners() { return listenerList.getListeners(ChangeListener.class); } /** * Sends a {@code ChangeEvent}, with this {@code JTabbedPane} as the source, * to each registered listener. This method is called each time there is * a change to either the selected index or the selected tab in the * {@code JTabbedPane}. Usually, the selected index and selected tab change * together. However, there are some cases, such as tab addition, where the * selected index changes and the same tab remains selected. There are other * cases, such as deleting the selected tab, where the index remains the * same, but a new tab moves to that index. Events are fired for all of * these cases. * * @see #addChangeListener * @see EventListenerList */ protected void fireStateChanged() { /* --- Begin code to deal with visibility --- */ /* This code deals with changing the visibility of components to * hide and show the contents for the selected tab. It duplicates * logic already present in BasicTabbedPaneUI, logic that is * processed during the layout pass. This code exists to allow * developers to do things that are quite difficult to accomplish * with the previous model of waiting for the layout pass to process * visibility changes; such as requesting focus on the new visible * component. * * For the average code, using the typical JTabbedPane methods, * all visibility changes will now be processed here. However, * the code in BasicTabbedPaneUI still exists, for the purposes * of backward compatibility. Therefore, when making changes to * this code, ensure that the BasicTabbedPaneUI code is kept in * synch. */ int selIndex = getSelectedIndex(); /* if the selection is now nothing */ if (selIndex < 0) { /* if there was a previous visible component */ if (visComp != null && visComp.isVisible()) { /* make it invisible */ visComp.setVisible(false); } /* now there's no visible component */ visComp = null; /* else - the selection is now something */ } else { /* Fetch the component for the new selection */ Component newComp = getComponentAt(selIndex); /* if the new component is non-null and different */ if (newComp != null && newComp != visComp) { boolean shouldChangeFocus = false; /* Note: the following (clearing of the old visible component) * is inside this if-statement for good reason: Tabbed pane * should continue to show the previously visible component * if there is no component for the chosen tab. */ /* if there was a previous visible component */ if (visComp != null) { shouldChangeFocus = (SwingUtilities.findFocusOwner(visComp) != null); /* if it's still visible */ if (visComp.isVisible()) { /* make it invisible */ visComp.setVisible(false); } } if (!newComp.isVisible()) { newComp.setVisible(true); } if (shouldChangeFocus) { SwingUtilities2.tabbedPaneChangeFocusTo(newComp); } visComp = newComp; } /* else - the visible component shouldn't changed */ } /* --- End code to deal with visibility --- */ // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==ChangeListener.class) { // Lazily create the event: if (changeEvent == null) changeEvent = new ChangeEvent(this); ((ChangeListener)listeners[i+1]).stateChanged(changeEvent); } } } /** * Returns the model associated with this tabbedpane. * * @see #setModel */ public SingleSelectionModel getModel() { return model; } /** * Sets the model to be used with this tabbedpane. * * @param model the model to be used * @see #getModel * @beaninfo * bound: true * description: The tabbedpane's SingleSelectionModel. */ public void setModel(SingleSelectionModel model) { SingleSelectionModel oldModel = getModel(); if (oldModel != null) { oldModel.removeChangeListener(changeListener); changeListener = null; } this.model = model; if (model != null) { changeListener = createChangeListener(); model.addChangeListener(changeListener); } firePropertyChange("model", oldModel, model); repaint(); } /** * Returns the placement of the tabs for this tabbedpane. * @see #setTabPlacement */ public int getTabPlacement() { return tabPlacement; } /** * Sets the tab placement for this tabbedpane. * Possible values are:<ul> * <li><code>JTabbedPane.TOP</code> * <li><code>JTabbedPane.BOTTOM</code> * <li><code>JTabbedPane.LEFT</code> * <li><code>JTabbedPane.RIGHT</code> * </ul> * The default value, if not set, is <code>SwingConstants.TOP</code>. * * @param tabPlacement the placement for the tabs relative to the content * @exception IllegalArgumentException if tab placement value isn't one * of the above valid values * * @beaninfo * preferred: true * bound: true * attribute: visualUpdate true * enum: TOP JTabbedPane.TOP * LEFT JTabbedPane.LEFT * BOTTOM JTabbedPane.BOTTOM * RIGHT JTabbedPane.RIGHT * description: The tabbedpane's tab placement. * */ public void setTabPlacement(int tabPlacement) { if (tabPlacement != TOP && tabPlacement != LEFT && tabPlacement != BOTTOM && tabPlacement != RIGHT) { throw new IllegalArgumentException("illegal tab placement: must be TOP, BOTTOM, LEFT, or RIGHT"); } if (this.tabPlacement != tabPlacement) { int oldValue = this.tabPlacement; this.tabPlacement = tabPlacement; firePropertyChange("tabPlacement", oldValue, tabPlacement); revalidate();Lines 1–500 of 2418. Load more
/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing; import java.awt.*; import java.awt.event.*; import java.beans.Transient; import java.util.*; import javax.swing.event.*; import javax.swing.plaf.*; import javax.accessibility.*; import sun.swing.SwingUtilities2; import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; /** * A component that lets the user switch between a group of components by * clicking on a tab with a given title and/or icon. * For examples and information on using tabbed panes see * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/tabbedpane.html">How to Use Tabbed Panes</a>, * a section in <em>The Java Tutorial</em>. * <p> * Tabs/components are added to a <code>TabbedPane</code> object by using the * <code>addTab</code> and <code>insertTab</code> methods. * A tab is represented by an index corresponding * to the position it was added in, where the first tab has an index equal to 0 * and the last tab has an index equal to the tab count minus 1. * <p> * The <code>TabbedPane</code> uses a <code>SingleSelectionModel</code> * to represent the set * of tab indices and the currently selected index. If the tab count * is greater than 0, then there will always be a selected index, which * by default will be initialized to the first tab. If the tab count is * 0, then the selected index will be -1. * <p> * The tab title can be rendered by a <code>Component</code>. * For example, the following produce similar results: * <pre> * // In this case the look and feel renders the title for the tab. * tabbedPane.addTab("Tab", myComponent); * // In this case the custom component is responsible for rendering the * // title of the tab. * tabbedPane.addTab(null, myComponent); * tabbedPane.setTabComponentAt(0, new JLabel("Tab")); * </pre> * The latter is typically used when you want a more complex user interaction * that requires custom components on the tab. For example, you could * provide a custom component that animates or one that has widgets for * closing the tab. * <p> * If you specify a component for a tab, the <code>JTabbedPane</code> * will not render any text or icon you have specified for the tab. * <p> * <strong>Note:</strong> * Do not use <code>setVisible</code> directly on a tab component to make it visible, * use <code>setSelectedComponent</code> or <code>setSelectedIndex</code> methods instead. * <p> * <strong>Warning:</strong> Swing is not thread safe. For more * information see <a * href="package-summary.html#threading">Swing's Threading * Policy</a>. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @beaninfo * attribute: isContainer true * description: A component which provides a tab folder metaphor for * displaying one component from a set of components. * * @author Dave Moore * @author Philip Milne * @author Amy Fowler * * @see SingleSelectionModel */ public class JTabbedPane extends JComponent implements Serializable, Accessible, SwingConstants { /** * The tab layout policy for wrapping tabs in multiple runs when all * tabs will not fit within a single run. */ public static final int WRAP_TAB_LAYOUT = 0; /** * Tab layout policy for providing a subset of available tabs when all * the tabs will not fit within a single run. If all the tabs do * not fit within a single run the look and feel will provide a way * to navigate to hidden tabs. */ public static final int SCROLL_TAB_LAYOUT = 1; /** * @see #getUIClassID * @see #readObject */ private static final String uiClassID = "TabbedPaneUI"; /** * Where the tabs are placed. * @see #setTabPlacement */ protected int tabPlacement = TOP; private int tabLayoutPolicy; /** The default selection model */ protected SingleSelectionModel model; private boolean haveRegistered; /** * The <code>changeListener</code> is the listener we add to the * model. */ protected ChangeListener changeListener = null; private final java.util.List<Page> pages; /* The component that is currently visible */ private Component visComp = null; /** * Only one <code>ChangeEvent</code> is needed per <code>TabPane</code> * instance since the * event's only (read-only) state is the source property. The source * of events generated here is always "this". */ protected transient ChangeEvent changeEvent = null; /** * Creates an empty <code>TabbedPane</code> with a default * tab placement of <code>JTabbedPane.TOP</code>. * @see #addTab */ public JTabbedPane() { this(TOP, WRAP_TAB_LAYOUT); } /** * Creates an empty <code>TabbedPane</code> with the specified tab placement * of either: <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>, * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>. * * @param tabPlacement the placement for the tabs relative to the content * @see #addTab */ public JTabbedPane(int tabPlacement) { this(tabPlacement, WRAP_TAB_LAYOUT); } /** * Creates an empty <code>TabbedPane</code> with the specified tab placement * and tab layout policy. Tab placement may be either: * <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>, * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>. * Tab layout policy may be either: <code>JTabbedPane.WRAP_TAB_LAYOUT</code> * or <code>JTabbedPane.SCROLL_TAB_LAYOUT</code>. * * @param tabPlacement the placement for the tabs relative to the content * @param tabLayoutPolicy the policy for laying out tabs when all tabs will not fit on one run * @exception IllegalArgumentException if tab placement or tab layout policy are not * one of the above supported values * @see #addTab * @since 1.4 */ public JTabbedPane(int tabPlacement, int tabLayoutPolicy) { setTabPlacement(tabPlacement); setTabLayoutPolicy(tabLayoutPolicy); pages = new ArrayList<Page>(1); setModel(new DefaultSingleSelectionModel()); updateUI(); } /** * Returns the UI object which implements the L&F for this component. * * @return a <code>TabbedPaneUI</code> object * @see #setUI */ public TabbedPaneUI getUI() { return (TabbedPaneUI)ui; } /** * Sets the UI object which implements the L&F for this component. * * @param ui the new UI object * @see UIDefaults#getUI * @beaninfo * bound: true * hidden: true * attribute: visualUpdate true * description: The UI object that implements the tabbedpane's LookAndFeel */ public void setUI(TabbedPaneUI ui) { super.setUI(ui); // disabled icons are generated by LF so they should be unset here for (int i = 0; i < getTabCount(); i++) { Icon icon = pages.get(i).disabledIcon; if (icon instanceof UIResource) { setDisabledIconAt(i, null); } } } /** * Resets the UI property to a value from the current look and feel. * * @see JComponent#updateUI */ public void updateUI() { setUI((TabbedPaneUI)UIManager.getUI(this)); } /** * Returns the name of the UI class that implements the * L&F for this component. * * @return the string "TabbedPaneUI" * @see JComponent#getUIClassID * @see UIDefaults#getUI */ public String getUIClassID() { return uiClassID; } /** * We pass <code>ModelChanged</code> events along to the listeners with * the tabbedpane (instead of the model itself) as the event source. */ protected class ModelListener implements ChangeListener, Serializable { public void stateChanged(ChangeEvent e) { fireStateChanged(); } } /** * Subclasses that want to handle <code>ChangeEvents</code> differently * can override this to return a subclass of <code>ModelListener</code> or * another <code>ChangeListener</code> implementation. * * @see #fireStateChanged */ protected ChangeListener createChangeListener() { return new ModelListener(); } /** * Adds a <code>ChangeListener</code> to this tabbedpane. * * @param l the <code>ChangeListener</code> to add * @see #fireStateChanged * @see #removeChangeListener */ public void addChangeListener(ChangeListener l) { listenerList.add(ChangeListener.class, l); } /** * Removes a <code>ChangeListener</code> from this tabbedpane. * * @param l the <code>ChangeListener</code> to remove * @see #fireStateChanged * @see #addChangeListener */ public void removeChangeListener(ChangeListener l) { listenerList.remove(ChangeListener.class, l); } /** * Returns an array of all the <code>ChangeListener</code>s added * to this <code>JTabbedPane</code> with <code>addChangeListener</code>. * * @return all of the <code>ChangeListener</code>s added or an empty * array if no listeners have been added * @since 1.4 */ public ChangeListener[] getChangeListeners() { return listenerList.getListeners(ChangeListener.class); } /** * Sends a {@code ChangeEvent}, with this {@code JTabbedPane} as the source, * to each registered listener. This method is called each time there is * a change to either the selected index or the selected tab in the * {@code JTabbedPane}. Usually, the selected index and selected tab change * together. However, there are some cases, such as tab addition, where the * selected index changes and the same tab remains selected. There are other * cases, such as deleting the selected tab, where the index remains the * same, but a new tab moves to that index. Events are fired for all of * these cases. * * @see #addChangeListener * @see EventListenerList */ protected void fireStateChanged() { /* --- Begin code to deal with visibility --- */ /* This code deals with changing the visibility of components to * hide and show the contents for the selected tab. It duplicates * logic already present in BasicTabbedPaneUI, logic that is * processed during the layout pass. This code exists to allow * developers to do things that are quite difficult to accomplish * with the previous model of waiting for the layout pass to process * visibility changes; such as requesting focus on the new visible * component. * * For the average code, using the typical JTabbedPane methods, * all visibility changes will now be processed here. However, * the code in BasicTabbedPaneUI still exists, for the purposes * of backward compatibility. Therefore, when making changes to * this code, ensure that the BasicTabbedPaneUI code is kept in * synch. */ int selIndex = getSelectedIndex(); /* if the selection is now nothing */ if (selIndex < 0) { /* if there was a previous visible component */ if (visComp != null && visComp.isVisible()) { /* make it invisible */ visComp.setVisible(false); } /* now there's no visible component */ visComp = null; /* else - the selection is now something */ } else { /* Fetch the component for the new selection */ Component newComp = getComponentAt(selIndex); /* if the new component is non-null and different */ if (newComp != null && newComp != visComp) { boolean shouldChangeFocus = false; /* Note: the following (clearing of the old visible component) * is inside this if-statement for good reason: Tabbed pane * should continue to show the previously visible component * if there is no component for the chosen tab. */ /* if there was a previous visible component */ if (visComp != null) { shouldChangeFocus = (SwingUtilities.findFocusOwner(visComp) != null); /* if it's still visible */ if (visComp.isVisible()) { /* make it invisible */ visComp.setVisible(false); } } if (!newComp.isVisible()) { newComp.setVisible(true); } if (shouldChangeFocus) { SwingUtilities2.tabbedPaneChangeFocusTo(newComp); } visComp = newComp; } /* else - the visible component shouldn't changed */ } /* --- End code to deal with visibility --- */ // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==ChangeListener.class) { // Lazily create the event: if (changeEvent == null) changeEvent = new ChangeEvent(this); ((ChangeListener)listeners[i+1]).stateChanged(changeEvent); } } } /** * Returns the model associated with this tabbedpane. * * @see #setModel */ public SingleSelectionModel getModel() { return model; } /** * Sets the model to be used with this tabbedpane. * * @param model the model to be used * @see #getModel * @beaninfo * bound: true * description: The tabbedpane's SingleSelectionModel. */ public void setModel(SingleSelectionModel model) { SingleSelectionModel oldModel = getModel(); if (oldModel != null) { oldModel.removeChangeListener(changeListener); changeListener = null; } this.model = model; if (model != null) { changeListener = createChangeListener(); model.addChangeListener(changeListener); } firePropertyChange("model", oldModel, model); repaint(); } /** * Returns the placement of the tabs for this tabbedpane. * @see #setTabPlacement */ public int getTabPlacement() { return tabPlacement; } /** * Sets the tab placement for this tabbedpane. * Possible values are:<ul> * <li><code>JTabbedPane.TOP</code> * <li><code>JTabbedPane.BOTTOM</code> * <li><code>JTabbedPane.LEFT</code> * <li><code>JTabbedPane.RIGHT</code> * </ul> * The default value, if not set, is <code>SwingConstants.TOP</code>. * * @param tabPlacement the placement for the tabs relative to the content * @exception IllegalArgumentException if tab placement value isn't one * of the above valid values * * @beaninfo * preferred: true * bound: true * attribute: visualUpdate true * enum: TOP JTabbedPane.TOP * LEFT JTabbedPane.LEFT * BOTTOM JTabbedPane.BOTTOM * RIGHT JTabbedPane.RIGHT * description: The tabbedpane's tab placement. * */ public void setTabPlacement(int tabPlacement) { if (tabPlacement != TOP && tabPlacement != LEFT && tabPlacement != BOTTOM && tabPlacement != RIGHT) { throw new IllegalArgumentException("illegal tab placement: must be TOP, BOTTOM, LEFT, or RIGHT"); } if (this.tabPlacement != tabPlacement) { int oldValue = this.tabPlacement; this.tabPlacement = tabPlacement; firePropertyChange("tabPlacement", oldValue, tabPlacement); revalidate();