1 /* JTabbedPane.java --
2    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package javax.swing;
40 
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Point;
44 import java.awt.Rectangle;
45 import java.awt.event.MouseEvent;
46 import java.io.Serializable;
47 import java.util.Vector;
48 
49 import javax.accessibility.Accessible;
50 import javax.accessibility.AccessibleContext;
51 import javax.accessibility.AccessibleRole;
52 import javax.accessibility.AccessibleSelection;
53 import javax.swing.event.ChangeEvent;
54 import javax.swing.event.ChangeListener;
55 import javax.swing.plaf.TabbedPaneUI;
56 import javax.swing.plaf.UIResource;
57 
58 /**
59  * This is a container for components where only one component is displayed at
60  * a given time and the displayed component can be switched by clicking on
61  * tabs.
62  *
63  * <p>
64  * Tabs can be oriented in several ways. They can be above, below, left and
65  * right of the component. Tabs can either wrap around (by creating multiple
66  * rows of tabs) or they can be scrolled (where only a subset of the  tabs
67  * can be seen at once). More tabs can be added by calling the
68  * add/addTab/insertTab methods.
69  * </p>
70  */
71 public class JTabbedPane extends JComponent implements Serializable,
72                                                        Accessible,
73                                                        SwingConstants
74 {
75   /**
76    * Accessibility support for <code>JTabbedPane</code>.
77    */
78   // FIXME: This inner class is a complete stub and must be implemented
79   // properly.
80   protected class AccessibleJTabbedPane extends JComponent.AccessibleJComponent
81     implements AccessibleSelection, ChangeListener
82   {
83     /**
84      * The serialization UID.
85      */
86     private static final long serialVersionUID = 7610530885966830483L;
87 
88     /**
89      * Creates a new AccessibleJTabbedPane object.
90      */
AccessibleJTabbedPane()91     public AccessibleJTabbedPane()
92     {
93       super();
94     }
95 
96     /**
97      * Receives notification when the selection state of the
98      * <code>JTabbedPane</code> changes.
99      *
100      * @param e the change event describing the change
101      */
stateChanged(ChangeEvent e)102     public void stateChanged(ChangeEvent e)
103     {
104       // Implement this properly.
105     }
106 
107     /**
108      * Returns the accessible role of the <code>JTabbedPane</code>, which is
109      * {@link AccessibleRole#PAGE_TAB_LIST}.
110      *
111      * @return the accessible role of the <code>JTabbedPane</code>
112      */
getAccessibleRole()113     public AccessibleRole getAccessibleRole()
114     {
115       return null;
116     }
117 
118     /**
119      * Returns the number of accessible child components of the
120      * <code>JTabbedPane</code>.
121      *
122      * @return the number of accessible child components of the
123      *         <code>JTabbedPane</code>
124      */
getAccessibleChildrenCount()125     public int getAccessibleChildrenCount()
126     {
127       return 0;
128     }
129 
130     /**
131      * Returns the accessible child component at the specified index.
132      *
133      * @param i the index of the child component to fetch
134      *
135      * @return the accessible child component at the specified index
136      */
getAccessibleChild(int i)137     public Accessible getAccessibleChild(int i)
138     {
139       return null;
140     }
141 
142     /**
143      * Returns the current selection state of the <code>JTabbedPane</code>
144      * as AccessibleSelection object.
145      *
146      * @return the current selection state of the <code>JTabbedPane</code>
147      */
getAccessibleSelection()148     public AccessibleSelection getAccessibleSelection()
149     {
150       return null;
151     }
152 
153     /**
154      * Returns the accessible child component at the specified coordinates.
155      * If there is no child component at this location, then return the
156      * currently selected tab.
157      *
158      * @param p the coordinates at which to look up the child component
159      *
160      * @return the accessible child component at the specified coordinates or
161      *         the currently selected tab if there is no child component at
162      *         this location
163      */
getAccessibleAt(Point p)164     public Accessible getAccessibleAt(Point p)
165     {
166       return null;
167     }
168 
169     /**
170      * The number of selected child components of the
171      * <code>JTabbedPane</code>. This will be <code>0</code> if the
172      * <code>JTabbedPane</code> has no children, or <code>1</code> otherwise,
173      * since there is always exactly one tab selected.
174      *
175      * @return number of selected child components of the
176      *         <code>JTabbedPane</code>
177      */
getAccessibleSelectionCount()178     public int getAccessibleSelectionCount()
179     {
180       return 0;
181     }
182 
183     /**
184      * DOCUMENT ME!
185      *
186      * @param i DOCUMENT ME!
187      *
188      * @return DOCUMENT ME!
189      */
getAccessibleSelection(int i)190     public Accessible getAccessibleSelection(int i)
191     {
192       return null;
193     }
194 
195     /**
196      * DOCUMENT ME!
197      *
198      * @param i DOCUMENT ME!
199      *
200      * @return DOCUMENT ME!
201      */
isAccessibleChildSelected(int i)202     public boolean isAccessibleChildSelected(int i)
203     {
204       return false;
205     }
206 
207     /**
208      * DOCUMENT ME!
209      *
210      * @param i DOCUMENT ME!
211      */
addAccessibleSelection(int i)212     public void addAccessibleSelection(int i)
213     {
214       // TODO: Implement this properly.
215     }
216 
217     /**
218      * DOCUMENT ME!
219      *
220      * @param i DOCUMENT ME!
221      */
removeAccessibleSelection(int i)222     public void removeAccessibleSelection(int i)
223     {
224       // TODO: Implement this properly.
225     }
226 
227     /**
228      * DOCUMENT ME!
229      */
clearAccessibleSelection()230     public void clearAccessibleSelection()
231     {
232       // TODO: Implement this properly.
233     }
234 
235     /**
236      * DOCUMENT ME!
237      */
selectAllAccessibleSelection()238     public void selectAllAccessibleSelection()
239     {
240       // TODO: Implement this properly.
241     }
242   }
243 
244   /**
245    * A helper class that listens for changes to the model.
246    */
247   protected class ModelListener implements ChangeListener, Serializable
248   {
249     /** DOCUMENT ME! */
250     private static final long serialVersionUID = 497359819958114132L;
251 
252     /**
253      * Creates a new ModelListener object.
254      */
ModelListener()255     protected ModelListener()
256     {
257       // Nothing to do here.
258     }
259 
260     /**
261      * This method is called whenever the model  is changed.
262      *
263      * @param e The ChangeEvent that is passed from the model.
264      */
stateChanged(ChangeEvent e)265     public void stateChanged(ChangeEvent e)
266     {
267       // Propagate to our listeners.
268       fireStateChanged();
269     }
270   }
271 
272   /**
273    * A private class that holds all the information  for each tab.
274    */
275   private class Page
276   {
277     /** The tooltip string. */
278     private String tip;
279 
280     /** The component associated with the tab. */
281     private Component component;
282 
283     /** The active icon associated with the tab. */
284     private transient Icon icon;
285 
286     /** The disabled icon associated with the tab. */
287     private transient Icon disabledIcon;
288 
289     /** The tab's enabled status. */
290     private transient boolean enabled = true;
291 
292     /** The string painted on the tab. */
293     private transient String title;
294 
295     /** The background color of the tab. */
296     private transient Color bg;
297 
298     /** The foreground color of the tab. */
299     private transient Color fg;
300 
301     /** The mnemonic associated with the tab. */
302     private transient int mnemonicKey;
303 
304     /** The index of the underlined character in the string. */
305     private transient int underlinedChar = -1;
306 
307     /**
308      * Creates a new data storage for the tab.
309      *
310      * @param title The string displayed on the tab.
311      * @param icon The active icon displayed on the tab.
312      * @param component The component associated with the tab.
313      * @param tip The tooltip associated with the tab.
314      */
Page(String title, Icon icon, Component component, String tip)315     protected Page(String title, Icon icon, Component component, String tip)
316     {
317       this.title = title;
318       this.icon = icon;
319       this.component = component;
320       this.tip = tip;
321     }
322 
323     /**
324      * This method returns the component associated with the tab.
325      *
326      * @return The component associated with the tab.
327      */
getComponent()328     public Component getComponent()
329     {
330       return component;
331     }
332 
333     /**
334      * This method sets the component associated with the tab.
335      *
336      * @param c The component associated with the tab.
337      */
setComponent(Component c)338     public void setComponent(Component c)
339     {
340       remove(component);
341       this.component = c;
342       add(c);
343     }
344 
345     /**
346      * This method returns the tooltip string.
347      *
348      * @return The tooltip string.
349      */
getTip()350     public String getTip()
351     {
352       return tip;
353     }
354 
355     /**
356      * This method sets the tooltip string.
357      *
358      * @param tip The tooltip string.
359      */
setTip(String tip)360     public void setTip(String tip)
361     {
362       this.tip = tip;
363     }
364 
365     /**
366      * This method returns the background color.
367      *
368      * @return The background color.
369      */
getBackground()370     public Color getBackground()
371     {
372       return bg;
373     }
374 
375     /**
376      * This method sets the background color.
377      *
378      * @param background The background color.
379      */
setBackground(Color background)380     public void setBackground(Color background)
381     {
382       bg = background;
383     }
384 
385     /**
386      * This method returns the foreground color.
387      *
388      * @return The foreground color.
389      */
getForeground()390     public Color getForeground()
391     {
392       return fg;
393     }
394 
395     /**
396      * This method sets the foreground color.
397      *
398      * @param foreground The foreground color.
399      */
setForeground(Color foreground)400     public void setForeground(Color foreground)
401     {
402       fg = foreground;
403     }
404 
405     /**
406      * This method returns the title associated with the tab.
407      *
408      * @return The title of the tab.
409      */
getTitle()410     public String getTitle()
411     {
412       return title;
413     }
414 
415     /** DOCUMENT ME! */
416     private static final long serialVersionUID = 1614381073220130939L;
417 
418     /**
419      * This method sets the title of the tab.
420      *
421      * @param text The title of the tab.
422      */
setTitle(String text)423     public void setTitle(String text)
424     {
425       title = text;
426       if (title != null && title.length() <= underlinedChar)
427 	setDisplayedMnemonicIndex(title.length() - 1);
428     }
429 
430     /**
431      * This method returns the active icon.
432      *
433      * @return The active icon.
434      */
getIcon()435     public Icon getIcon()
436     {
437       return icon;
438     }
439 
440     /**
441      * This method sets the active icon.
442      *
443      * @param icon The active icon.
444      */
setIcon(Icon icon)445     public void setIcon(Icon icon)
446     {
447       this.icon = icon;
448     }
449 
450     /**
451      * This method returns the disabled icon.
452      *
453      * @return The disabled icon.
454      */
getDisabledIcon()455     public Icon getDisabledIcon()
456     {
457       if (disabledIcon == null && icon instanceof ImageIcon)
458 	setDisabledIcon(icon);
459       return disabledIcon;
460     }
461 
462     /**
463      * This method sets the disabled icon.
464      *
465      * @param disabledIcon The disabled icon.
466      */
setDisabledIcon(Icon disabledIcon)467     public void setDisabledIcon(Icon disabledIcon)
468     {
469       this.disabledIcon = disabledIcon;
470     }
471 
472     /**
473      * This method returns whether the tab is enabled.
474      *
475      * @return Whether the tab is enabled.
476      */
isEnabled()477     public boolean isEnabled()
478     {
479       return enabled;
480     }
481 
482     /**
483      * This method sets whether the tab is enabled.
484      *
485      * @param enabled Whether this tab is enabled.
486      */
setEnabled(boolean enabled)487     public void setEnabled(boolean enabled)
488     {
489       this.enabled = enabled;
490     }
491 
492     /**
493      * This method returns the mnemonic.
494      *
495      * @return The mnemonic.
496      */
getMnemonic()497     public int getMnemonic()
498     {
499       return (int) mnemonicKey;
500     }
501 
502     /**
503      * This method sets the mnemonic. If the title is set, it will update the
504      * mnemonicIndex.
505      *
506      * @param key The mnemonic.
507      */
setMnemonic(int key)508     public void setMnemonic(int key)
509     {
510       setMnemonic((char) key);
511     }
512 
513     /**
514      * This method sets the mnemonic. If the title is set, it will update the
515      * mnemonicIndex.
516      *
517      * @param aChar The mnemonic.
518      */
setMnemonic(char aChar)519     public void setMnemonic(char aChar)
520     {
521       mnemonicKey = aChar;
522       if (title != null)
523 	setDisplayedMnemonicIndex(title.indexOf(mnemonicKey));
524     }
525 
526     /**
527      * This method returns the mnemonicIndex.
528      *
529      * @return The mnemonicIndex.
530      */
getDisplayedMnemonicIndex()531     public int getDisplayedMnemonicIndex()
532     {
533       return underlinedChar;
534     }
535 
536     /**
537      * This method sets the mnemonicIndex.
538      *
539      * @param index The mnemonicIndex.
540      *
541      * @throws IllegalArgumentException If index less than -1 || index greater
542      *         or equal to title.length.
543      */
setDisplayedMnemonicIndex(int index)544     public void setDisplayedMnemonicIndex(int index)
545       throws IllegalArgumentException
546     {
547       if (index < -1 || title != null && index >= title.length())
548 	throw new IllegalArgumentException();
549 
550       if (title == null || mnemonicKey == 0 || (index > -1 && title.charAt(index) != mnemonicKey))
551 	index = -1;
552 
553       underlinedChar = index;
554     }
555   }
556 
557   private static final long serialVersionUID = 1614381073220130939L;
558 
559   /** The changeEvent used to fire changes to listeners. */
560   protected ChangeEvent changeEvent;
561 
562   /** The listener that listens to the model. */
563   protected ChangeListener changeListener;
564 
565   /** The model that describes this JTabbedPane. */
566   protected SingleSelectionModel model;
567 
568   /** Indicates that the TabbedPane is in scrolling mode. */
569   public static final int SCROLL_TAB_LAYOUT = 1;
570 
571   /** Indicates that the TabbedPane is in wrap mode. */
572   public static final int WRAP_TAB_LAYOUT = 0;
573 
574   /** The current tabPlacement of the TabbedPane. */
575   protected int tabPlacement = SwingConstants.TOP;
576 
577   /** The current tabLayoutPolicy of the TabbedPane. */
578   private transient int layoutPolicy;
579 
580   /** The list of tabs associated with the TabbedPane. */
581   transient Vector tabs = new Vector();
582 
583   /**
584    * Creates a new JTabbedPane object with tabs on top and using wrap tab
585    * layout.
586    */
JTabbedPane()587   public JTabbedPane()
588   {
589     this(SwingConstants.TOP, WRAP_TAB_LAYOUT);
590   }
591 
592   /**
593    * Creates a new JTabbedPane object using wrap tab layout  and the given
594    * tabPlacement.
595    *
596    * @param tabPlacement Where the tabs will be placed.
597    */
JTabbedPane(int tabPlacement)598   public JTabbedPane(int tabPlacement)
599   {
600     this(tabPlacement, WRAP_TAB_LAYOUT);
601   }
602 
603   /**
604    * Creates a new JTabbedPane object with the given tabPlacement and
605    * tabLayoutPolicy.
606    *
607    * @param tabPlacement Where the tabs will be placed.
608    * @param tabLayoutPolicy The way tabs will be placed.
609    *
610    * @throws IllegalArgumentException If tabLayoutPolicy or tabPlacement are
611    *         not valid.
612    */
JTabbedPane(int tabPlacement, int tabLayoutPolicy)613   public JTabbedPane(int tabPlacement, int tabLayoutPolicy)
614   {
615     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
616         && tabPlacement != LEFT)
617       throw new IllegalArgumentException("tabPlacement is not valid.");
618     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
619         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
620       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
621     this.tabPlacement = tabPlacement;
622     layoutPolicy = tabLayoutPolicy;
623 
624     changeEvent = new ChangeEvent(this);
625     changeListener = createChangeListener();
626 
627     model = new DefaultSingleSelectionModel();
628     model.addChangeListener(changeListener);
629 
630     updateUI();
631   }
632 
633   /**
634    * This method returns the UI used to display the JTabbedPane.
635    *
636    * @return The UI used to display the JTabbedPane.
637    */
getUI()638   public TabbedPaneUI getUI()
639   {
640     return (TabbedPaneUI) ui;
641   }
642 
643   /**
644    * This method sets the UI used to display the JTabbedPane.
645    *
646    * @param ui The UI used to display the JTabbedPane.
647    */
setUI(TabbedPaneUI ui)648   public void setUI(TabbedPaneUI ui)
649   {
650     super.setUI(ui);
651   }
652 
653   /**
654    * This method restores the UI to the defaults given by the UIManager.
655    */
updateUI()656   public void updateUI()
657   {
658     setUI((TabbedPaneUI) UIManager.getUI(this));
659     invalidate();
660   }
661 
662   /**
663    * This method returns a string identifier that  is used to determine which
664    * UI will be used with  the JTabbedPane.
665    *
666    * @return A string identifier for the UI.
667    */
getUIClassID()668   public String getUIClassID()
669   {
670     return "TabbedPaneUI";
671   }
672 
673   /**
674    * This method creates a ChangeListener that is used to  listen to the model
675    * for events.
676    *
677    * @return A ChangeListener to listen to the model.
678    */
createChangeListener()679   protected ChangeListener createChangeListener()
680   {
681     return new ModelListener();
682   }
683 
684   /**
685    * This method adds a ChangeListener to the JTabbedPane.
686    *
687    * @param l The ChangeListener to add.
688    */
addChangeListener(ChangeListener l)689   public void addChangeListener(ChangeListener l)
690   {
691     listenerList.add(ChangeListener.class, l);
692   }
693 
694   /**
695    * This method removes a ChangeListener to the JTabbedPane.
696    *
697    * @param l The ChangeListener to remove.
698    */
removeChangeListener(ChangeListener l)699   public void removeChangeListener(ChangeListener l)
700   {
701     listenerList.remove(ChangeListener.class, l);
702   }
703 
704   /**
705    * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners.
706    */
fireStateChanged()707   protected void fireStateChanged()
708   {
709     Object[] changeListeners = listenerList.getListenerList();
710     if (changeEvent == null)
711       changeEvent = new ChangeEvent(this);
712     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
713       {
714 	if (changeListeners[i] == ChangeListener.class)
715 	  ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
716       }
717   }
718 
719   /**
720    * This method returns all ChangeListeners registered with the JTabbedPane.
721    *
722    * @return The ChangeListeners registered with the JTabbedPane.
723    */
getChangeListeners()724   public ChangeListener[] getChangeListeners()
725   {
726     return (ChangeListener[]) super.getListeners(ChangeListener.class);
727   }
728 
729   /**
730    * This method returns the model used with the JTabbedPane.
731    *
732    * @return The JTabbedPane's model.
733    */
getModel()734   public SingleSelectionModel getModel()
735   {
736     return model;
737   }
738 
739   /**
740    * This method changes the model property of the JTabbedPane.
741    *
742    * @param model The new model to use with the JTabbedPane.
743    */
setModel(SingleSelectionModel model)744   public void setModel(SingleSelectionModel model)
745   {
746     if (model != this.model)
747       {
748 	SingleSelectionModel oldModel = this.model;
749 	this.model.removeChangeListener(changeListener);
750 	this.model = model;
751 	this.model.addChangeListener(changeListener);
752 	firePropertyChange("model", oldModel, this.model);
753       }
754   }
755 
756   /**
757    * This method returns the tabPlacement.
758    *
759    * @return The tabPlacement used with the JTabbedPane.
760    */
getTabPlacement()761   public int getTabPlacement()
762   {
763     return tabPlacement;
764   }
765 
766   /**
767    * This method changes the tabPlacement property of the JTabbedPane.
768    *
769    * @param tabPlacement The tabPlacement to use.
770    *
771    * @throws IllegalArgumentException If tabPlacement is not one of TOP,
772    *         BOTTOM, LEFT, or RIGHT.
773    */
setTabPlacement(int tabPlacement)774   public void setTabPlacement(int tabPlacement)
775   {
776     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
777         && tabPlacement != LEFT)
778       throw new IllegalArgumentException("tabPlacement is not valid.");
779     if (tabPlacement != this.tabPlacement)
780       {
781 	int oldPlacement = this.tabPlacement;
782 	this.tabPlacement = tabPlacement;
783 	firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement);
784       }
785   }
786 
787   /**
788    * This method returns the tabLayoutPolicy.
789    *
790    * @return The tabLayoutPolicy.
791    */
getTabLayoutPolicy()792   public int getTabLayoutPolicy()
793   {
794     return layoutPolicy;
795   }
796 
797   /**
798    * This method changes the tabLayoutPolicy property of the JTabbedPane.
799    *
800    * @param tabLayoutPolicy The tabLayoutPolicy to use.
801    *
802    * @throws IllegalArgumentException If tabLayoutPolicy is not one of
803    *         SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT.
804    */
setTabLayoutPolicy(int tabLayoutPolicy)805   public void setTabLayoutPolicy(int tabLayoutPolicy)
806   {
807     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
808         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
809       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
810     if (tabLayoutPolicy != layoutPolicy)
811       {
812 	int oldPolicy = layoutPolicy;
813 	layoutPolicy = tabLayoutPolicy;
814 	firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy);
815       }
816   }
817 
818   /**
819    * This method returns the index of the tab that is currently selected.
820    *
821    * @return The index of the selected tab.
822    */
getSelectedIndex()823   public int getSelectedIndex()
824   {
825     return model.getSelectedIndex();
826   }
827 
828   /**
829    * This method checks the index.
830    *
831    * @param index The index to check.
832    * @param start DOCUMENT ME!
833    * @param end DOCUMENT ME!
834    *
835    * @throws IndexOutOfBoundsException DOCUMENT ME!
836    */
checkIndex(int index, int start, int end)837   private void checkIndex(int index, int start, int end)
838   {
839     if (index < start || index >= end)
840       throw new IndexOutOfBoundsException("Index < " + start + " || Index >= "
841                                           + end);
842   }
843 
844   /**
845    * This method sets the selected index. This method will hide the old
846    * component and show the new component.
847    *
848    * @param index The index to set it at.
849    */
setSelectedIndex(int index)850   public void setSelectedIndex(int index)
851   {
852     checkIndex(index, -1, tabs.size());
853     if (index != getSelectedIndex())
854       {
855 	if (getSelectedIndex() != -1 && getSelectedComponent() != null)
856 	  getSelectedComponent().hide();
857 	if (index != -1 && getComponentAt(index) != null)
858 	  getComponentAt(index).show();
859 	model.setSelectedIndex(index);
860       }
861   }
862 
863   /**
864    * This method returns the component at the selected index.
865    *
866    * @return The component at the selected index.
867    */
getSelectedComponent()868   public Component getSelectedComponent()
869   {
870     return getComponentAt(getSelectedIndex());
871   }
872 
873   /**
874    * This method sets the component at the selected index.
875    *
876    * @param c The component associated with the selected index.
877    */
setSelectedComponent(Component c)878   public void setSelectedComponent(Component c)
879   {
880     if (c.getParent() == this)
881       setSelectedIndex(indexOfComponent(c));
882     else
883       setComponentAt(getSelectedIndex(), c);
884   }
885 
886   /**
887    * This method inserts tabs into JTabbedPane. This includes adding the
888    * component to the JTabbedPane and hiding it.
889    *
890    * @param title the title of the tab; may be <code>null</code>
891    * @param icon the tab's icon; may be <code>null</code>
892    * @param component the component associated with the tab
893    * @param tip the tooltip for the tab
894    * @param index the index to insert the tab at
895    */
insertTab(String title, Icon icon, Component component, String tip, int index)896   public void insertTab(String title, Icon icon, Component component,
897                         String tip, int index)
898   {
899     if (title == null)
900       title = "";
901     Page p = new Page(title, icon, component, tip);
902     tabs.insertElementAt(p, index);
903 
904     // Hide the component so we don't see it. Do it before we parent it
905     // so we don't trigger a repaint.
906     if (component != null)
907       {
908 	component.hide();
909 	super.add(component);
910       }
911 
912     if (getSelectedIndex() == -1)
913       setSelectedIndex(0);
914 
915     layout();
916     repaint();
917   }
918 
919   /**
920    * This method adds a tab to the JTabbedPane.
921    *
922    * @param title the title of the tab; may be <code>null</code>
923    * @param icon the icon for the tab; may be <code>null</code>
924    * @param component the associated component
925    * @param tip the associated tooltip
926    */
addTab(String title, Icon icon, Component component, String tip)927   public void addTab(String title, Icon icon, Component component, String tip)
928   {
929     insertTab(title, icon, component, tip, tabs.size());
930   }
931 
932   /**
933    * This method adds a tab to the JTabbedPane.
934    *
935    * @param title the title of the tab; may be <code>null</code>
936    * @param icon the icon for the tab; may be <code>null</code>
937    * @param component the associated component
938    */
addTab(String title, Icon icon, Component component)939   public void addTab(String title, Icon icon, Component component)
940   {
941     insertTab(title, icon, component, null, tabs.size());
942   }
943 
944   /**
945    * This method adds a tab to the JTabbedPane.
946    *
947    * @param title the title of the tab; may be <code>null</code>
948    * @param component the associated component
949    */
addTab(String title, Component component)950   public void addTab(String title, Component component)
951   {
952     insertTab(title, null, component, null, tabs.size());
953   }
954 
955   /**
956    * This method adds a tab to the JTabbedPane. The title of the tab is the
957    * Component's name. If the Component is an instance of UIResource, it
958    * doesn't add the tab and instead add the component directly to the
959    * JTabbedPane.
960    *
961    * @param component The associated component.
962    *
963    * @return The Component that was added.
964    */
add(Component component)965   public Component add(Component component)
966   {
967     if (component instanceof UIResource)
968       super.add(component);
969     else
970       insertTab(component.getName(), null, component, null, tabs.size());
971     return component;
972   }
973 
974   /**
975    * This method adds a tab to the JTabbedPane. If the Component is an
976    * instance of UIResource, it doesn't add the tab and instead add the
977    * component directly to the JTabbedPane.
978    *
979    * @param title the title of the tab; may be <code>null</code>
980    * @param component the associated component
981    *
982    * @return The Component that was added.
983    */
add(String title, Component component)984   public Component add(String title, Component component)
985   {
986     if (component instanceof UIResource)
987       super.add(component);
988     else
989       insertTab(title, null, component, null, tabs.size());
990     return component;
991   }
992 
993   /**
994    * This method adds a tab to the JTabbedPane. If the Component is an
995    * instance of UIResource, it doesn't add the tab and instead add the
996    * component directly to the JTabbedPane.
997    *
998    * @param component The associated component.
999    * @param index The index to insert the tab at.
1000    *
1001    * @return The Component that was added.
1002    */
add(Component component, int index)1003   public Component add(Component component, int index)
1004   {
1005     if (component instanceof UIResource)
1006       super.add(component);
1007     else
1008       insertTab(component.getName(), null, component, null, index);
1009     return component;
1010   }
1011 
1012   /**
1013    * This method adds a tab to the JTabbedPane. If the Component is an
1014    * instance of UIResource, it doesn't add the tab and instead add the
1015    * component directly to the JTabbedPane. If the constraints object is an
1016    * icon, it will be used as the tab's icon. If the constraints object is a
1017    * string, we will use it as the title.
1018    *
1019    * @param component The associated component.
1020    * @param constraints The constraints object.
1021    */
add(Component component, Object constraints)1022   public void add(Component component, Object constraints)
1023   {
1024     add(component, constraints, tabs.size());
1025   }
1026 
1027   /**
1028    * This method adds a tab to the JTabbedPane. If the Component is an
1029    * instance of UIResource, it doesn't add the tab and instead add the
1030    * component directly to the JTabbedPane. If the constraints object is an
1031    * icon, it will be used as the tab's icon. If the constraints object is a
1032    * string, we will use it as the title.
1033    *
1034    * @param component The associated component.
1035    * @param constraints The constraints object.
1036    * @param index The index to insert the tab at.
1037    */
add(Component component, Object constraints, int index)1038   public void add(Component component, Object constraints, int index)
1039   {
1040     if (component instanceof UIResource)
1041       super.add(component);
1042     else
1043       {
1044 	if (constraints instanceof String)
1045 	  insertTab((String) constraints, null, component, null, index);
1046 	else
1047 	  insertTab(component.getName(),
1048 	            (constraints instanceof Icon) ? (Icon) constraints : null,
1049 	            component, null, index);
1050       }
1051   }
1052 
1053   /**
1054    * The tab and it's associated component are removed. After the component
1055    * has been removed from the JTabbedPane, it's set visible to ensure that
1056    * it can be seen.
1057    *
1058    * @param index The index of the tab to remove.
1059    */
removeTabAt(int index)1060   public void removeTabAt(int index)
1061   {
1062     checkIndex(index, 0, tabs.size());
1063     Component c = getComponentAt(index);
1064     super.remove(index);
1065     c.show();
1066     tabs.remove(index);
1067   }
1068 
1069   /**
1070    * This method removes the component from the JTabbedPane. After the
1071    * component has been removed from the JTabbedPane, it's  set visible to
1072    * ensure that it can be seen.
1073    *
1074    * @param component The Component to remove.
1075    */
remove(Component component)1076   public void remove(Component component)
1077   {
1078     // This simply removes the component.
1079     int index = indexOfComponent(component);
1080     super.remove(component);
1081     component.show();
1082     setComponentAt(index, null);
1083   }
1084 
1085   /**
1086    * This method removes the tab and component from the JTabbedPane. It simply
1087    * calls removeTabAt(int index).
1088    *
1089    * @param index The index of the tab to remove.
1090    */
remove(int index)1091   public void remove(int index)
1092   {
1093     removeTabAt(index);
1094   }
1095 
1096   /**
1097    * This method removes all tabs and associated components from the
1098    * JTabbedPane.
1099    */
removeAll()1100   public void removeAll()
1101   {
1102     for (int i = tabs.size() - 1; i >= 0; i--)
1103       removeTabAt(i);
1104   }
1105 
1106   /**
1107    * This method returns how many tabs are in the JTabbedPane.
1108    *
1109    * @return The number of tabs in the JTabbedPane.
1110    */
getTabCount()1111   public int getTabCount()
1112   {
1113     return tabs.size();
1114   }
1115 
1116   /**
1117    * This method returns the number of runs used  to paint the JTabbedPane.
1118    *
1119    * @return The number of runs.
1120    */
getTabRunCount()1121   public int getTabRunCount()
1122   {
1123     return ((TabbedPaneUI) ui).getTabRunCount(this);
1124   }
1125 
1126   /**
1127    * This method returns the tab title given the index.
1128    *
1129    * @param index The index of the tab.
1130    *
1131    * @return The title for the tab.
1132    */
getTitleAt(int index)1133   public String getTitleAt(int index)
1134   {
1135     checkIndex(index, 0, tabs.size());
1136     return ((Page) tabs.elementAt(index)).getTitle();
1137   }
1138 
1139   /**
1140    * This method returns the active icon given the index.
1141    *
1142    * @param index The index of the tab.
1143    *
1144    * @return The active icon for the tab.
1145    */
getIconAt(int index)1146   public Icon getIconAt(int index)
1147   {
1148     checkIndex(index, 0, tabs.size());
1149     return ((Page) tabs.elementAt(index)).getIcon();
1150   }
1151 
1152   /**
1153    * This method returns the disabled icon given the index.
1154    *
1155    * @param index The index of the tab.
1156    *
1157    * @return The disabled icon for the tab.
1158    */
getDisabledIconAt(int index)1159   public Icon getDisabledIconAt(int index)
1160   {
1161     checkIndex(index, 0, tabs.size());
1162     return ((Page) tabs.elementAt(index)).getDisabledIcon();
1163   }
1164 
1165   /**
1166    * This method returns the tooltip string for the tab.
1167    *
1168    * @param index The index of the tab.
1169    *
1170    * @return The tooltip string for the tab.
1171    */
getToolTipTextAt(int index)1172   public String getToolTipTextAt(int index)
1173   {
1174     checkIndex(index, 0, tabs.size());
1175     return ((Page) tabs.elementAt(index)).getTip();
1176   }
1177 
1178   /**
1179    * This method returns the foreground color for the tab.
1180    *
1181    * @param index The index of the tab.
1182    *
1183    * @return The foreground color for the tab.
1184    */
getForegroundAt(int index)1185   public Color getForegroundAt(int index)
1186   {
1187     checkIndex(index, 0, tabs.size());
1188     return ((Page) tabs.elementAt(index)).getForeground();
1189   }
1190 
1191   /**
1192    * This method returns the background color for the tab.
1193    *
1194    * @param index The index of the tab.
1195    *
1196    * @return The background color for the tab.
1197    */
getBackgroundAt(int index)1198   public Color getBackgroundAt(int index)
1199   {
1200     checkIndex(index, 0, tabs.size());
1201     return ((Page) tabs.elementAt(index)).getBackground();
1202   }
1203 
1204   /**
1205    * This method returns the component associated with the tab.
1206    *
1207    * @param index The index of the tab.
1208    *
1209    * @return The component associated with the tab.
1210    */
getComponentAt(int index)1211   public Component getComponentAt(int index)
1212   {
1213     checkIndex(index, 0, tabs.size());
1214     return ((Page) tabs.elementAt(index)).getComponent();
1215   }
1216 
1217   /**
1218    * This method returns whether this tab is enabled. Disabled tabs cannot be
1219    * selected.
1220    *
1221    * @param index The index of the tab.
1222    *
1223    * @return Whether the tab is enabled.
1224    */
isEnabledAt(int index)1225   public boolean isEnabledAt(int index)
1226   {
1227     checkIndex(index, 0, tabs.size());
1228     return ((Page) tabs.elementAt(index)).isEnabled();
1229   }
1230 
1231   /**
1232    * This method returns the mnemonic for the tab.
1233    *
1234    * @param tabIndex The index of the tab.
1235    *
1236    * @return The mnemonic for the tab.
1237    */
getMnemonicAt(int tabIndex)1238   public int getMnemonicAt(int tabIndex)
1239   {
1240     checkIndex(tabIndex, 0, tabs.size());
1241     return ((Page) tabs.elementAt(tabIndex)).getMnemonic();
1242   }
1243 
1244   /**
1245    * This method returns the mnemonic index for the tab.
1246    *
1247    * @param tabIndex The index of the tab.
1248    *
1249    * @return The mnemonic index for the tab.
1250    */
getDisplayedMnemonicIndexAt(int tabIndex)1251   public int getDisplayedMnemonicIndexAt(int tabIndex)
1252   {
1253     checkIndex(tabIndex, 0, tabs.size());
1254     return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex();
1255   }
1256 
1257   /**
1258    * This method returns the bounds of the tab given the index.
1259    *
1260    * @param index The index of the tab.
1261    *
1262    * @return A rectangle describing the bounds of the tab.
1263    */
getBoundsAt(int index)1264   public Rectangle getBoundsAt(int index)
1265   {
1266     checkIndex(index, 0, tabs.size());
1267     return ((TabbedPaneUI) ui).getTabBounds(this, index);
1268   }
1269 
1270   /**
1271    * This method sets the title of the tab.
1272    *
1273    * @param index The index of the tab.
1274    * @param title The new title.
1275    */
setTitleAt(int index, String title)1276   public void setTitleAt(int index, String title)
1277   {
1278     checkIndex(index, 0, tabs.size());
1279     ((Page) tabs.elementAt(index)).setTitle(title);
1280   }
1281 
1282   /**
1283    * This method sets the icon of the tab.
1284    *
1285    * @param index The index of the tab.
1286    * @param icon The new icon.
1287    */
setIconAt(int index, Icon icon)1288   public void setIconAt(int index, Icon icon)
1289   {
1290     checkIndex(index, 0, tabs.size());
1291     ((Page) tabs.elementAt(index)).setIcon(icon);
1292   }
1293 
1294   /**
1295    * This method sets the disabled icon of the tab.
1296    *
1297    * @param index The index of the tab.
1298    * @param disabledIcon The new disabled icon.
1299    */
setDisabledIconAt(int index, Icon disabledIcon)1300   public void setDisabledIconAt(int index, Icon disabledIcon)
1301   {
1302     checkIndex(index, 0, tabs.size());
1303     ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon);
1304   }
1305 
1306   /**
1307    * This method sets the tooltip text of the tab.
1308    *
1309    * @param index The index of the tab.
1310    * @param toolTipText The tooltip text.
1311    */
setToolTipTextAt(int index, String toolTipText)1312   public void setToolTipTextAt(int index, String toolTipText)
1313   {
1314     checkIndex(index, 0, tabs.size());
1315     ((Page) tabs.elementAt(index)).setTip(toolTipText);
1316   }
1317 
1318   /**
1319    * This method sets the background color of the tab.
1320    *
1321    * @param index The index of the tab.
1322    * @param background The background color of the tab.
1323    */
setBackgroundAt(int index, Color background)1324   public void setBackgroundAt(int index, Color background)
1325   {
1326     checkIndex(index, 0, tabs.size());
1327     ((Page) tabs.elementAt(index)).setBackground(background);
1328   }
1329 
1330   /**
1331    * This method sets the foreground color of the tab.
1332    *
1333    * @param index The index of the tab.
1334    * @param foreground The foreground color of the tab.
1335    */
setForegroundAt(int index, Color foreground)1336   public void setForegroundAt(int index, Color foreground)
1337   {
1338     checkIndex(index, 0, tabs.size());
1339     ((Page) tabs.elementAt(index)).setForeground(foreground);
1340   }
1341 
1342   /**
1343    * This method sets whether the tab is enabled.
1344    *
1345    * @param index The index of the tab.
1346    * @param enabled Whether the tab is enabled.
1347    */
setEnabledAt(int index, boolean enabled)1348   public void setEnabledAt(int index, boolean enabled)
1349   {
1350     checkIndex(index, 0, tabs.size());
1351     ((Page) tabs.elementAt(index)).setEnabled(enabled);
1352   }
1353 
1354   /**
1355    * This method sets the component associated with the tab.
1356    *
1357    * @param index The index of the tab.
1358    * @param component The component associated with the tab.
1359    */
setComponentAt(int index, Component component)1360   public void setComponentAt(int index, Component component)
1361   {
1362     checkIndex(index, 0, tabs.size());
1363     ((Page) tabs.elementAt(index)).setComponent(component);
1364   }
1365 
1366   /**
1367    * This method sets the displayed mnemonic index of the tab.
1368    *
1369    * @param tabIndex The index of the tab.
1370    * @param mnemonicIndex The mnemonic index.
1371    */
setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex)1372   public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex)
1373   {
1374     checkIndex(tabIndex, 0, tabs.size());
1375     ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex);
1376   }
1377 
1378   /**
1379    * This method sets the mnemonic for the tab.
1380    *
1381    * @param tabIndex The index of the tab.
1382    * @param mnemonic The mnemonic.
1383    */
setMnemonicAt(int tabIndex, int mnemonic)1384   public void setMnemonicAt(int tabIndex, int mnemonic)
1385   {
1386     checkIndex(tabIndex, 0, tabs.size());
1387     ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic);
1388   }
1389 
1390   /**
1391    * This method finds the index of a tab given the title.
1392    *
1393    * @param title The title that belongs to a tab.
1394    *
1395    * @return The index of the tab that has the title or -1 if not found.
1396    */
indexOfTab(String title)1397   public int indexOfTab(String title)
1398   {
1399     int index = -1;
1400     for (int i = 0; i < tabs.size(); i++)
1401       {
1402 	if (((Page) tabs.elementAt(i)).getTitle().equals(title))
1403 	  {
1404 	    index = i;
1405 	    break;
1406 	  }
1407       }
1408     return index;
1409   }
1410 
1411   /**
1412    * This method finds the index of a tab given the icon.
1413    *
1414    * @param icon The icon that belongs to a tab.
1415    *
1416    * @return The index of the tab that has the icon or -1 if not found.
1417    */
indexOfTab(Icon icon)1418   public int indexOfTab(Icon icon)
1419   {
1420     int index = -1;
1421     for (int i = 0; i < tabs.size(); i++)
1422       {
1423 	if (((Page) tabs.elementAt(i)).getIcon() == icon)
1424 	  {
1425 	    index = i;
1426 	    break;
1427 	  }
1428       }
1429     return index;
1430   }
1431 
1432   /**
1433    * This method finds the index of a tab given the component.
1434    *
1435    * @param component A component associated with a tab.
1436    *
1437    * @return The index of the tab that has this component or -1 if not found.
1438    */
indexOfComponent(Component component)1439   public int indexOfComponent(Component component)
1440   {
1441     int index = -1;
1442     for (int i = 0; i < tabs.size(); i++)
1443       {
1444 	if (((Page) tabs.elementAt(i)).getComponent() == component)
1445 	  {
1446 	    index = i;
1447 	    break;
1448 	  }
1449       }
1450     return index;
1451   }
1452 
1453   /**
1454    * This method returns a tab index given an (x,y) location. The origin of
1455    * the (x,y) pair will be the JTabbedPane's top left position. The  tab
1456    * returned will be the one that contains the point. This method is
1457    * delegated to the UI.
1458    *
1459    * @param x The x coordinate of the point.
1460    * @param y The y coordinate of the point.
1461    *
1462    * @return The index of the tab that contains the point.
1463    */
indexAtLocation(int x, int y)1464   public int indexAtLocation(int x, int y)
1465   {
1466     return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y);
1467   }
1468 
1469   /**
1470    * This method returns the tooltip text given a mouse event.
1471    *
1472    * @param event The mouse event.
1473    *
1474    * @return The tool tip text that is associated with this mouse event.
1475    */
getToolTipText(MouseEvent event)1476   public String getToolTipText(MouseEvent event)
1477   {
1478     int index = indexAtLocation(event.getX(), event.getY());
1479     return ((Page) tabs.elementAt(index)).getTip();
1480   }
1481 
1482   /**
1483    * This method returns a string representation of this JTabbedPane. It is
1484    * mainly used for debugging purposes.
1485    *
1486    * @return A string representation of this JTabbedPane.
1487    */
paramString()1488   protected String paramString()
1489   {
1490     return "JTabbedPane";
1491   }
1492 
1493   /**
1494    * DOCUMENT ME!
1495    *
1496    * @return DOCUMENT ME!
1497    */
getAccessibleContext()1498   public AccessibleContext getAccessibleContext()
1499   {
1500     if (accessibleContext == null)
1501       accessibleContext = new AccessibleJTabbedPane();
1502     return accessibleContext;
1503   }
1504 }
1505