Source for javax.swing.JTabbedPane

   1: /* JTabbedPane.java --
   2:    Copyright (C) 2002, 2004, 2005, 2006,  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.Locale;
  48: import java.util.Vector;
  49: 
  50: import javax.accessibility.Accessible;
  51: import javax.accessibility.AccessibleContext;
  52: import javax.accessibility.AccessibleRole;
  53: import javax.accessibility.AccessibleSelection;
  54: import javax.accessibility.AccessibleState;
  55: import javax.accessibility.AccessibleStateSet;
  56: import javax.swing.event.ChangeEvent;
  57: import javax.swing.event.ChangeListener;
  58: import javax.swing.plaf.TabbedPaneUI;
  59: import javax.swing.plaf.UIResource;
  60: 
  61: /**
  62:  * This is a container for components where only one component is displayed at
  63:  * a given time and the displayed component can be switched by clicking on
  64:  * tabs.
  65:  * 
  66:  * <p>
  67:  * Tabs can be oriented in several ways. They can be above, below, left and
  68:  * right of the component. Tabs can either wrap around (by creating multiple
  69:  * rows of tabs) or they can be scrolled (where only a subset of the  tabs
  70:  * can be seen at once). More tabs can be added by calling the
  71:  * add/addTab/insertTab methods.
  72:  * </p>
  73:  */
  74: public class JTabbedPane extends JComponent implements Serializable,
  75:                                                        Accessible,
  76:                                                        SwingConstants
  77: {
  78:   /**
  79:    * Accessibility support for <code>JTabbedPane</code>.
  80:    */
  81:   protected class AccessibleJTabbedPane extends JComponent.AccessibleJComponent
  82:     implements AccessibleSelection, ChangeListener
  83:   {
  84:     /**
  85:      * The serialization UID.
  86:      */
  87:     private static final long serialVersionUID = 7610530885966830483L;
  88: 
  89:     /**
  90:      * Creates a new AccessibleJTabbedPane object.
  91:      */
  92:     public AccessibleJTabbedPane()
  93:     {
  94:       super();
  95:     }
  96: 
  97:     /**
  98:      * Receives notification when the selection state of the
  99:      * <code>JTabbedPane</code> changes and fires appropriate property change
 100:      * events to interested listeners.
 101:      *
 102:      * @param e the change event describing the change
 103:      */
 104:     public void stateChanged(ChangeEvent e)
 105:     {
 106:       // I couldn't figure out what else should be done here.
 107:       Object source = e.getSource();
 108:       firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
 109:                          null, source);
 110:     }
 111: 
 112:     /**
 113:      * Returns the accessible role of the <code>JTabbedPane</code>, which is
 114:      * {@link AccessibleRole#PAGE_TAB_LIST}.
 115:      *
 116:      * @return the accessible role of the <code>JTabbedPane</code>
 117:      */
 118:     public AccessibleRole getAccessibleRole()
 119:     {
 120:       return AccessibleRole.PAGE_TAB_LIST;
 121:     }
 122: 
 123:     /**
 124:      * Returns the number of accessible child components of the
 125:      * <code>JTabbedPane</code>.
 126:      *
 127:      * @return the number of accessible child components of the
 128:      *         <code>JTabbedPane</code>
 129:      */
 130:     public int getAccessibleChildrenCount()
 131:     {
 132:       return getTabCount();
 133:     }
 134: 
 135:     /**
 136:      * Returns the accessible child component at the specified index.
 137:      *
 138:      * @param i the index of the child component to fetch
 139:      *
 140:      * @return the accessible child component at the specified index
 141:      */
 142:     public Accessible getAccessibleChild(int i)
 143:     {
 144:       // Testing shows that the reference implementation returns instances
 145:       // of page here.
 146:       Accessible child = null;
 147:       if (i >= 0 && i < tabs.size())
 148:         child = (Page) tabs.get(i);
 149:       return child;
 150:     }
 151: 
 152:     /**
 153:      * Returns the current selection state of the <code>JTabbedPane</code>
 154:      * as AccessibleSelection object.
 155:      *
 156:      * @return the current selection state of the <code>JTabbedPane</code>
 157:      */
 158:     public AccessibleSelection getAccessibleSelection()
 159:     {
 160:       return this;
 161:     }
 162: 
 163:     /**
 164:      * Returns the accessible child component at the specified coordinates.
 165:      * If there is no child component at this location, then return the
 166:      * currently selected tab.
 167:      *
 168:      * @param p the coordinates at which to look up the child component
 169:      *
 170:      * @return the accessible child component at the specified coordinates or
 171:      *         the currently selected tab if there is no child component at
 172:      *         this location
 173:      */
 174:     public Accessible getAccessibleAt(Point p)
 175:     {
 176:       int tabIndex = indexAtLocation(p.x, p.y);
 177:       if (tabIndex >= 0)
 178:         return getAccessibleChild(tabIndex);
 179:       else
 180:         return getAccessibleSelection(0);
 181:     }
 182: 
 183:     /**
 184:      * Returns the number of selected child components of the
 185:      * <code>JTabbedPane</code>. The reference implementation appears
 186:      * to return <code>1</code> always and we do the same. 
 187:      *
 188:      * @return <code>1</code>
 189:      */
 190:     public int getAccessibleSelectionCount()
 191:     {
 192:       return 1;
 193:     }
 194: 
 195:     /**
 196:      * Returns the selected tab, or <code>null</code> if there is no 
 197:      * selection.
 198:      *
 199:      * @param i  the selection index (ignored here).
 200:      *
 201:      * @return The selected tab, or <code>null</code>.
 202:      */
 203:     public Accessible getAccessibleSelection(int i)
 204:     {
 205:       Accessible result = null;
 206:       int selected = getSelectedIndex();
 207:       if (selected >= 0)
 208:         result = (Page) tabs.get(selected);
 209:       return result;
 210:     }
 211: 
 212:     /**
 213:      * Returns <code>true</code> if the specified child is selected,
 214:      * and <code>false</code> otherwise.
 215:      *
 216:      * @param i the child index.
 217:      *
 218:      * @return A boolean.
 219:      */
 220:     public boolean isAccessibleChildSelected(int i)
 221:     {
 222:       return i == getSelectedIndex();
 223:     }
 224: 
 225:     /**
 226:      * Selects the specified tab.
 227:      *
 228:      * @param i  the index of the item to select.
 229:      */
 230:     public void addAccessibleSelection(int i)
 231:     {
 232:       setSelectedIndex(i);
 233:     }
 234: 
 235:     /**
 236:      * Does nothing - it makes no sense to remove a selection for a
 237:      * tabbed pane, since one tab must always be selected.
 238:      *
 239:      * @param i  the item index.
 240:      * 
 241:      * @see #addAccessibleSelection(int)
 242:      */
 243:     public void removeAccessibleSelection(int i)
 244:     {
 245:       // do nothing
 246:     }
 247: 
 248:     /**
 249:      * Does nothing - it makes no sense to clear the selection for
 250:      * a tabbed pane, since one tab must always be selected.
 251:      * 
 252:      * @see #addAccessibleSelection(int)
 253:      */
 254:     public void clearAccessibleSelection()
 255:     {
 256:       // do nothing
 257:     }
 258: 
 259:     /**
 260:      * Does nothing - it makes no sense to select all for a tabbed
 261:      * pane, since only one tab can be selected at a time.
 262:      * 
 263:      * @see #addAccessibleSelection(int)
 264:      */
 265:     public void selectAllAccessibleSelection()
 266:     {
 267:       // do nothing
 268:     }
 269:   }
 270: 
 271:   /**
 272:    * A helper class that listens for changes to the model.
 273:    */
 274:   protected class ModelListener implements ChangeListener, Serializable
 275:   {
 276:     private static final long serialVersionUID = 497359819958114132L;
 277: 
 278:     /**
 279:      * Creates a new ModelListener object.
 280:      */
 281:     protected ModelListener()
 282:     {
 283:       // Nothing to do here.
 284:     }
 285: 
 286:     /**
 287:      * This method is called whenever the model  is changed.
 288:      *
 289:      * @param e The ChangeEvent that is passed from the model.
 290:      */
 291:     public void stateChanged(ChangeEvent e)
 292:     {
 293:       // Propagate to our listeners.
 294:       fireStateChanged();
 295:     }
 296:   }
 297: 
 298:   /**
 299:    * A private class that holds all the information  for each tab.
 300:    */
 301:   private class Page
 302:     extends AccessibleContext
 303:     implements Accessible
 304:   {
 305:     /** The tooltip string. */
 306:     private String tip;
 307: 
 308:     /** The component associated with the tab. */
 309:     private Component component;
 310: 
 311:     /** The active icon associated with the tab. */
 312:     private transient Icon icon;
 313: 
 314:     /** The disabled icon associated with the tab. */
 315:     private transient Icon disabledIcon;
 316: 
 317:     /** The tab's enabled status. */
 318:     private transient boolean enabled = true;
 319: 
 320:     /** The string painted on the tab. */
 321:     private transient String title;
 322: 
 323:     /** The background color of the tab. */
 324:     private transient Color bg;
 325: 
 326:     /** The foreground color of the tab. */
 327:     private transient Color fg;
 328: 
 329:     /** The mnemonic associated with the tab. */
 330:     private transient int mnemonicKey;
 331: 
 332:     /** The index of the underlined character in the string. */
 333:     private transient int underlinedChar = -1;
 334: 
 335:     /**
 336:      * Creates a new data storage for the tab.
 337:      *
 338:      * @param title The string displayed on the tab.
 339:      * @param icon The active icon displayed on the tab.
 340:      * @param component The component associated with the tab.
 341:      * @param tip The tooltip associated with the tab.
 342:      */
 343:     protected Page(String title, Icon icon, Component component, String tip)
 344:     {
 345:       this.title = title;
 346:       this.icon = icon;
 347:       this.component = component;
 348:       this.tip = tip;
 349:     }
 350: 
 351:     /**
 352:      * This method returns the component associated with the tab.
 353:      *
 354:      * @return The component associated with the tab.
 355:      */
 356:     public Component getComponent()
 357:     {
 358:       return component;
 359:     }
 360: 
 361:     /**
 362:      * This method sets the component associated with the tab.
 363:      *
 364:      * @param c The component associated with the tab.
 365:      */
 366:     public void setComponent(Component c)
 367:     {
 368:       int i = indexOfComponent(component);
 369:       insertTab(title, icon, c, tip, i);
 370:       component = c;
 371:       removeTabAt(i);
 372:     }
 373: 
 374:     /**
 375:      * This method returns the tooltip string.
 376:      *
 377:      * @return The tooltip string.
 378:      */
 379:     public String getTip()
 380:     {
 381:       return tip;
 382:     }
 383: 
 384:     /**
 385:      * This method sets the tooltip string.
 386:      *
 387:      * @param tip The tooltip string.
 388:      */
 389:     public void setTip(String tip)
 390:     {
 391:       this.tip = tip;
 392:     }
 393: 
 394:     /**
 395:      * This method returns the background color.
 396:      *
 397:      * @return The background color.
 398:      */
 399:     public Color getBackground()
 400:     {
 401:       Color background;
 402:       if (bg == null)
 403:         background = JTabbedPane.this.getBackground();
 404:       else
 405:         background = bg;
 406:       return background;
 407:     }
 408: 
 409:     /**
 410:      * This method sets the background color.
 411:      *
 412:      * @param background The background color.
 413:      */
 414:     public void setBackground(Color background)
 415:     {
 416:       bg = background;
 417:     }
 418: 
 419:     /**
 420:      * This method returns the foreground color.
 421:      *
 422:      * @return The foreground color.
 423:      */
 424:     public Color getForeground()
 425:     {
 426:       Color foreground;
 427:       if (fg == null)
 428:         foreground = JTabbedPane.this.getForeground();
 429:       else
 430:         foreground = fg;
 431:       return foreground;
 432:     }
 433: 
 434:     /**
 435:      * This method sets the foreground color.
 436:      *
 437:      * @param foreground The foreground color.
 438:      */
 439:     public void setForeground(Color foreground)
 440:     {
 441:       fg = foreground;
 442:     }
 443: 
 444:     /**
 445:      * This method returns the title associated with the tab.
 446:      *
 447:      * @return The title of the tab.
 448:      */
 449:     public String getTitle()
 450:     {
 451:       return title;
 452:     }
 453: 
 454:     private static final long serialVersionUID = 1614381073220130939L;
 455: 
 456:     /**
 457:      * This method sets the title of the tab.
 458:      *
 459:      * @param text The title of the tab.
 460:      */
 461:     public void setTitle(String text)
 462:     {
 463:       title = text;
 464:       if (title != null && title.length() <= underlinedChar)
 465:     setDisplayedMnemonicIndex(title.length() - 1);
 466:     }
 467: 
 468:     /**
 469:      * This method returns the active icon.
 470:      *
 471:      * @return The active icon.
 472:      */
 473:     public Icon getIcon()
 474:     {
 475:       return icon;
 476:     }
 477: 
 478:     /**
 479:      * This method sets the active icon.
 480:      *
 481:      * @param icon The active icon.
 482:      */
 483:     public void setIcon(Icon icon)
 484:     {
 485:       this.icon = icon;
 486:     }
 487: 
 488:     /**
 489:      * This method returns the disabled icon.
 490:      *
 491:      * @return The disabled icon.
 492:      */
 493:     public Icon getDisabledIcon()
 494:     {
 495:       if (disabledIcon == null && icon instanceof ImageIcon)
 496:     setDisabledIcon(icon);
 497:       return disabledIcon;
 498:     }
 499: 
 500:     /**
 501:      * This method sets the disabled icon.
 502:      *
 503:      * @param disabledIcon The disabled icon.
 504:      */
 505:     public void setDisabledIcon(Icon disabledIcon)
 506:     {
 507:       this.disabledIcon = disabledIcon;
 508:     }
 509: 
 510:     /**
 511:      * This method returns whether the tab is enabled.
 512:      *
 513:      * @return Whether the tab is enabled.
 514:      */
 515:     public boolean isEnabled()
 516:     {
 517:       return enabled;
 518:     }
 519: 
 520:     /**
 521:      * This method sets whether the tab is enabled.
 522:      *
 523:      * @param enabled Whether this tab is enabled.
 524:      */
 525:     public void setEnabled(boolean enabled)
 526:     {
 527:       this.enabled = enabled;
 528:     }
 529: 
 530:     /**
 531:      * This method returns the mnemonic.
 532:      *
 533:      * @return The mnemonic.
 534:      */
 535:     public int getMnemonic()
 536:     {
 537:       return mnemonicKey;
 538:     }
 539: 
 540:     /**
 541:      * This method sets the mnemonic. If the title is set, it will update the
 542:      * mnemonicIndex.
 543:      *
 544:      * @param key The mnemonic.
 545:      */
 546:     public void setMnemonic(int key)
 547:     {
 548:       setMnemonic((char) key);
 549:     }
 550: 
 551:     /**
 552:      * This method sets the mnemonic. If the title is set, it will update the
 553:      * mnemonicIndex.
 554:      *
 555:      * @param aChar The mnemonic.
 556:      */
 557:     public void setMnemonic(char aChar)
 558:     {
 559:       mnemonicKey = aChar;
 560:       if (title != null)
 561:     setDisplayedMnemonicIndex(title.indexOf(mnemonicKey));
 562:     }
 563: 
 564:     /**
 565:      * This method returns the mnemonicIndex.
 566:      *
 567:      * @return The mnemonicIndex.
 568:      */
 569:     public int getDisplayedMnemonicIndex()
 570:     {
 571:       return underlinedChar;
 572:     }
 573: 
 574:     /**
 575:      * This method sets the mnemonicIndex.
 576:      *
 577:      * @param index The mnemonicIndex.
 578:      *
 579:      * @throws IllegalArgumentException If index less than -1 || index greater
 580:      *         or equal to title.length.
 581:      */
 582:     public void setDisplayedMnemonicIndex(int index)
 583:       throws IllegalArgumentException
 584:     {
 585:       if (index < -1 || title != null && index >= title.length())
 586:     throw new IllegalArgumentException();
 587: 
 588:       if (title == null || mnemonicKey == 0 || (index > -1 && title.charAt(index) != mnemonicKey))
 589:     index = -1;
 590: 
 591:       underlinedChar = index;
 592:     }
 593: 
 594:     /**
 595:      * Returns the accessible context, which is this object itself.
 596:      *
 597:      * @return the accessible context, which is this object itself
 598:      */
 599:     public AccessibleContext getAccessibleContext()
 600:     {
 601:       return this;
 602:     }
 603: 
 604:     /**
 605:      * Returns the accessible name for this tab.
 606:      * 
 607:      * @return The accessible name.
 608:      */
 609:     public String getAccessibleName()
 610:     {
 611:       if (accessibleName != null)
 612:         return accessibleName;
 613:       else
 614:         return title;
 615:     }
 616:     
 617:     /**
 618:      * Returns the accessible role of this tab, which is always
 619:      * {@link AccessibleRole#PAGE_TAB}.
 620:      *
 621:      * @return the accessible role of this tab
 622:      */
 623:     public AccessibleRole getAccessibleRole()
 624:     {
 625:       return AccessibleRole.PAGE_TAB;
 626:     }
 627: 
 628:     /**
 629:      * Returns the accessible state set of this object.
 630:      *
 631:      * @return the accessible state set of this object
 632:      */
 633:     public AccessibleStateSet getAccessibleStateSet()
 634:     {
 635:       AccessibleContext parentCtx = JTabbedPane.this.getAccessibleContext(); 
 636:       AccessibleStateSet state = parentCtx.getAccessibleStateSet();
 637:       state.add(AccessibleState.SELECTABLE);
 638:       if (component == getSelectedComponent())
 639:         state.add(AccessibleState.SELECTED);
 640:       return state;
 641:     }
 642: 
 643:     /**
 644:      * Returns the index of this tab inside its parent.
 645:      *
 646:      * @return the index of this tab inside its parent
 647:      */
 648:     public int getAccessibleIndexInParent()
 649:     {
 650:       // TODO: Not sure if the title is unambiguous, but I can't figure
 651:       // another way of doing this.
 652:       return indexOfTab(title);
 653:     }
 654: 
 655:     /**
 656:      * Returns the number of accessible children, which is always one (the
 657:      * component of this tab).
 658:      *
 659:      * @return the number of accessible children
 660:      */
 661:     public int getAccessibleChildrenCount()
 662:     {
 663:       return 1;
 664:     }
 665: 
 666:     /**
 667:      * Returns the accessible child of this tab, which is the component
 668:      * displayed by the tab.
 669:      *
 670:      * @return the accessible child of this tab
 671:      */
 672:     public Accessible getAccessibleChild(int i)
 673:     {
 674:       // A quick test shows that this method always returns the component
 675:       // displayed by the tab, regardless of the index.
 676:       return (Accessible) component;
 677:     }
 678: 
 679:     /**
 680:      * Returns the locale of this accessible object.
 681:      *
 682:      * @return the locale of this accessible object
 683:      */
 684:     public Locale getLocale()
 685:     {
 686:       // TODO: Is this ok?
 687:       return Locale.getDefault();
 688:     }
 689:   }
 690: 
 691:   private static final long serialVersionUID = 1614381073220130939L;
 692: 
 693:   /** The changeEvent used to fire changes to listeners. */
 694:   protected ChangeEvent changeEvent;
 695: 
 696:   /** The listener that listens to the model. */
 697:   protected ChangeListener changeListener;
 698: 
 699:   /** The model that describes this JTabbedPane. */
 700:   protected SingleSelectionModel model;
 701: 
 702:   /** Indicates that the TabbedPane is in scrolling mode. */
 703:   public static final int SCROLL_TAB_LAYOUT = 1;
 704: 
 705:   /** Indicates that the TabbedPane is in wrap mode. */
 706:   public static final int WRAP_TAB_LAYOUT = 0;
 707: 
 708:   /** The current tabPlacement of the TabbedPane. */
 709:   protected int tabPlacement = SwingConstants.TOP;
 710: 
 711:   /** The current tabLayoutPolicy of the TabbedPane. */
 712:   private transient int layoutPolicy;
 713: 
 714:   /** The list of tabs associated with the TabbedPane. */
 715:   transient Vector tabs = new Vector();
 716: 
 717:   /**
 718:    * Creates a new JTabbedPane object with tabs on top and using wrap tab
 719:    * layout.
 720:    */
 721:   public JTabbedPane()
 722:   {
 723:     this(SwingConstants.TOP, WRAP_TAB_LAYOUT);
 724:   }
 725: 
 726:   /**
 727:    * Creates a new JTabbedPane object using wrap tab layout  and the given
 728:    * <code>tabPlacement</code>, where <code>tabPlacement</code> can be one
 729:    * of the following values: {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} or
 730:    * {@link #RIGHT}.
 731:    *
 732:    * @param tabPlacement where the tabs will be placed
 733:    */
 734:   public JTabbedPane(int tabPlacement)
 735:   {
 736:     this(tabPlacement, WRAP_TAB_LAYOUT);
 737:   }
 738: 
 739:   /**
 740:    * Creates a new JTabbedPane object with the given <code>tabPlacement</code>
 741:    * and <code>tabLayoutPolicy</code>. The <code>tabPlacement</code> can be one
 742:    * of the following values: {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} or
 743:    * {@link #RIGHT}. The <code>tabLayoutPolicy</code> can be either
 744:    * {@link #SCROLL_TAB_LAYOUT} or {@link #WRAP_TAB_LAYOUT}.
 745:    *
 746:    * @param tabPlacement where the tabs will be placed
 747:    * @param tabLayoutPolicy the way tabs will be placed
 748:    *
 749:    * @throws IllegalArgumentException If tabLayoutPolicy or tabPlacement are
 750:    *         not valid.
 751:    */
 752:   public JTabbedPane(int tabPlacement, int tabLayoutPolicy)
 753:   {
 754:     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
 755:         && tabPlacement != LEFT)
 756:       throw new IllegalArgumentException("tabPlacement is not valid.");
 757:     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
 758:         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
 759:       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
 760:     this.tabPlacement = tabPlacement;
 761:     layoutPolicy = tabLayoutPolicy;
 762:     
 763:     setModel(new DefaultSingleSelectionModel());
 764: 
 765:     updateUI();
 766:   }
 767: 
 768:   /**
 769:    * This method returns the UI used to display the JTabbedPane.
 770:    *
 771:    * @return The UI used to display the JTabbedPane.
 772:    */
 773:   public TabbedPaneUI getUI()
 774:   {
 775:     return (TabbedPaneUI) ui;
 776:   }
 777: 
 778:   /**
 779:    * This method sets the UI used to display the JTabbedPane.
 780:    *
 781:    * @param ui The UI used to display the JTabbedPane.
 782:    */
 783:   public void setUI(TabbedPaneUI ui)
 784:   {
 785:     super.setUI(ui);
 786:   }
 787: 
 788:   /**
 789:    * This method restores the UI to the defaults given by the UIManager.
 790:    */
 791:   public void updateUI()
 792:   {
 793:     setUI((TabbedPaneUI) UIManager.getUI(this));
 794:   }
 795: 
 796:   /**
 797:    * This method returns a string identifier that  is used to determine which
 798:    * UI will be used with  the JTabbedPane.
 799:    *
 800:    * @return A string identifier for the UI.
 801:    */
 802:   public String getUIClassID()
 803:   {
 804:     return "TabbedPaneUI";
 805:   }
 806: 
 807:   /**
 808:    * This method creates a ChangeListener that is used to  listen to the model
 809:    * for events.
 810:    *
 811:    * @return A ChangeListener to listen to the model.
 812:    */
 813:   protected ChangeListener createChangeListener()
 814:   {
 815:     return new ModelListener();
 816:   }
 817: 
 818:   /**
 819:    * This method adds a ChangeListener to the JTabbedPane.
 820:    *
 821:    * @param l The ChangeListener to add.
 822:    */
 823:   public void addChangeListener(ChangeListener l)
 824:   {
 825:     listenerList.add(ChangeListener.class, l);
 826:   }
 827: 
 828:   /**
 829:    * This method removes a ChangeListener to the JTabbedPane.
 830:    *
 831:    * @param l The ChangeListener to remove.
 832:    */
 833:   public void removeChangeListener(ChangeListener l)
 834:   {
 835:     listenerList.remove(ChangeListener.class, l);
 836:   }
 837: 
 838:   /**
 839:    * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners.
 840:    */
 841:   protected void fireStateChanged()
 842:   {
 843:     Object[] changeListeners = listenerList.getListenerList();
 844:     if (changeEvent == null)
 845:       changeEvent = new ChangeEvent(this);
 846:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 847:       {
 848:     if (changeListeners[i] == ChangeListener.class)
 849:       ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 850:       }
 851:   }
 852: 
 853:   /**
 854:    * This method returns all ChangeListeners registered with the JTabbedPane.
 855:    *
 856:    * @return The ChangeListeners registered with the JTabbedPane.
 857:    */
 858:   public ChangeListener[] getChangeListeners()
 859:   {
 860:     return (ChangeListener[]) super.getListeners(ChangeListener.class);
 861:   }
 862: 
 863:   /**
 864:    * This method returns the model used with the JTabbedPane.
 865:    *
 866:    * @return The JTabbedPane's model.
 867:    */
 868:   public SingleSelectionModel getModel()
 869:   {
 870:     return model;
 871:   }
 872: 
 873:   /**
 874:    * This method changes the model property of the JTabbedPane.
 875:    *
 876:    * @param m The new model to use with the JTabbedPane.
 877:    */
 878:   public void setModel(SingleSelectionModel m)
 879:   {
 880:     if (m != model)
 881:       {
 882:     SingleSelectionModel oldModel = this.model;
 883:         if (oldModel != null && changeListener != null)
 884:           oldModel.removeChangeListener(changeListener);
 885: 
 886:     model = m;
 887: 
 888:         if (model != null)
 889:           {
 890:             if (changeListener == null)
 891:               changeListener = createChangeListener();
 892:             model.addChangeListener(changeListener);
 893:           }
 894:     firePropertyChange("model", oldModel, this.model);
 895:       }
 896:   }
 897: 
 898:   /**
 899:    * This method returns the tabPlacement.
 900:    *
 901:    * @return The tabPlacement used with the JTabbedPane.
 902:    */
 903:   public int getTabPlacement()
 904:   {
 905:     return tabPlacement;
 906:   }
 907: 
 908:   /**
 909:    * This method changes the tabPlacement property of the JTabbedPane.
 910:    *
 911:    * @param tabPlacement The tabPlacement to use.
 912:    *
 913:    * @throws IllegalArgumentException If tabPlacement is not one of TOP,
 914:    *         BOTTOM, LEFT, or RIGHT.
 915:    */
 916:   public void setTabPlacement(int tabPlacement)
 917:   {
 918:     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
 919:         && tabPlacement != LEFT)
 920:       throw new IllegalArgumentException("tabPlacement is not valid.");
 921:     if (tabPlacement != this.tabPlacement)
 922:       {
 923:     int oldPlacement = this.tabPlacement;
 924:     this.tabPlacement = tabPlacement;
 925:     firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement);
 926:       }
 927:   }
 928: 
 929:   /**
 930:    * This method returns the tabLayoutPolicy.
 931:    *
 932:    * @return The tabLayoutPolicy.
 933:    */
 934:   public int getTabLayoutPolicy()
 935:   {
 936:     return layoutPolicy;
 937:   }
 938: 
 939:   /**
 940:    * This method changes the tabLayoutPolicy property of the JTabbedPane.
 941:    *
 942:    * @param tabLayoutPolicy The tabLayoutPolicy to use.
 943:    *
 944:    * @throws IllegalArgumentException If tabLayoutPolicy is not one of
 945:    *         SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT.
 946:    */
 947:   public void setTabLayoutPolicy(int tabLayoutPolicy)
 948:   {
 949:     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
 950:         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
 951:       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
 952:     if (tabLayoutPolicy != layoutPolicy)
 953:       {
 954:     int oldPolicy = layoutPolicy;
 955:     layoutPolicy = tabLayoutPolicy;
 956:     firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy);
 957:       }
 958:   }
 959: 
 960:   /**
 961:    * This method returns the index of the tab that is currently selected.
 962:    *
 963:    * @return The index of the selected tab.
 964:    */
 965:   public int getSelectedIndex()
 966:   {
 967:     return model.getSelectedIndex();
 968:   }
 969: 
 970:   /**
 971:    * This method checks the index.
 972:    *
 973:    * @param index The index to check.
 974:    * @param start DOCUMENT ME!
 975:    * @param end DOCUMENT ME!
 976:    *
 977:    * @throws IndexOutOfBoundsException DOCUMENT ME!
 978:    */
 979:   private void checkIndex(int index, int start, int end)
 980:   {
 981:     if (index < start || index >= end)
 982:       throw new IndexOutOfBoundsException("Index < " + start + " || Index >= "
 983:                                           + end);
 984:   }
 985: 
 986:   /**
 987:    * This method sets the selected index. This method will hide the old
 988:    * component and show the new component.
 989:    *
 990:    * @param index The index to set it at.
 991:    */
 992:   public void setSelectedIndex(int index)
 993:   {
 994:     checkIndex(index, -1, tabs.size());
 995:     if (index != getSelectedIndex())
 996:       {
 997:         // Hiding and showing the involved components
 998:         // is done by the JTabbedPane's UI.
 999:     model.setSelectedIndex(index);
1000:       }
1001:   }
1002: 
1003:   /**
1004:    * This method returns the component at the selected index.
1005:    *
1006:    * @return The component at the selected index.
1007:    */
1008:   public Component getSelectedComponent()
1009:   {
1010:     int selectedIndex = getSelectedIndex();
1011:     Component selected = null;
1012:     if (selectedIndex >= 0)
1013:       selected = getComponentAt(selectedIndex);
1014:     return selected;
1015:   }
1016: 
1017:   /**
1018:    * This method sets the component at the selected index.
1019:    *
1020:    * @param c The component associated with the selected index.
1021:    */
1022:   public void setSelectedComponent(Component c)
1023:   {
1024:     if (c.getParent() == this)
1025:       setSelectedIndex(indexOfComponent(c));
1026:     else
1027:       setComponentAt(getSelectedIndex(), c);
1028:   }
1029: 
1030:   /**
1031:    * This method inserts tabs into JTabbedPane. This includes adding the
1032:    * component to the JTabbedPane and hiding it.
1033:    *
1034:    * @param title the title of the tab; may be <code>null</code>
1035:    * @param icon the tab's icon; may be <code>null</code>
1036:    * @param component the component associated with the tab
1037:    * @param tip the tooltip for the tab
1038:    * @param index the index to insert the tab at
1039:    */
1040:   public void insertTab(String title, Icon icon, Component component,
1041:                         String tip, int index)
1042:   {
1043:     if (title == null)
1044:       title = "";
1045:     Page p = new Page(title, icon, component, tip);
1046:     tabs.insertElementAt(p, index);
1047: 
1048:     // Hide the component so we don't see it. Do it before we parent it
1049:     // so we don't trigger a repaint.
1050:     if (component != null)
1051:       {
1052:     component.hide();
1053:     super.add(component);
1054:       }
1055: 
1056:     if (getSelectedIndex() == -1)
1057:       {
1058:         setSelectedIndex(0);
1059:         fireStateChanged();
1060:       }
1061: 
1062:     revalidate();
1063:     repaint();
1064:   }
1065: 
1066:   /**
1067:    * This method adds a tab to the JTabbedPane.
1068:    *
1069:    * @param title the title of the tab; may be <code>null</code>
1070:    * @param icon the icon for the tab; may be <code>null</code>
1071:    * @param component the associated component
1072:    * @param tip the associated tooltip
1073:    */
1074:   public void addTab(String title, Icon icon, Component component, String tip)
1075:   {
1076:     insertTab(title, icon, component, tip, tabs.size());
1077:   }
1078: 
1079:   /**
1080:    * This method adds a tab to the JTabbedPane.
1081:    *
1082:    * @param title the title of the tab; may be <code>null</code>
1083:    * @param icon the icon for the tab; may be <code>null</code>
1084:    * @param component the associated component
1085:    */
1086:   public void addTab(String title, Icon icon, Component component)
1087:   {
1088:     insertTab(title, icon, component, null, tabs.size());
1089:   }
1090: 
1091:   /**
1092:    * This method adds a tab to the JTabbedPane.
1093:    *
1094:    * @param title the title of the tab; may be <code>null</code>
1095:    * @param component the associated component
1096:    */
1097:   public void addTab(String title, Component component)
1098:   {
1099:     insertTab(title, null, component, null, tabs.size());
1100:   }
1101: 
1102:   /**
1103:    * This method adds a tab to the JTabbedPane. The title of the tab is the
1104:    * Component's name. If the Component is an instance of UIResource, it
1105:    * doesn't add the tab and instead add the component directly to the
1106:    * JTabbedPane.
1107:    *
1108:    * @param component The associated component.
1109:    *
1110:    * @return The Component that was added.
1111:    */
1112:   public Component add(Component component)
1113:   {
1114:     if (component instanceof UIResource)
1115:       super.add(component);
1116:     else
1117:       insertTab(component.getName(), null, component, null, tabs.size());
1118:     
1119:     return component;
1120:   }
1121: 
1122:   /**
1123:    * This method adds a tab to the JTabbedPane. If the Component is an
1124:    * instance of UIResource, it doesn't add the tab and instead add the
1125:    * component directly to the JTabbedPane.
1126:    *
1127:    * @param title the title of the tab; may be <code>null</code>
1128:    * @param component the associated component
1129:    *
1130:    * @return The Component that was added.
1131:    */
1132:   public Component add(String title, Component component)
1133:   {
1134:     if (component instanceof UIResource)
1135:       super.add(component);
1136:     else
1137:       insertTab(title, null, component, null, tabs.size());
1138:     return component;
1139:   }
1140: 
1141:   /**
1142:    * This method adds a tab to the JTabbedPane. If the Component is an
1143:    * instance of UIResource, it doesn't add the tab and instead add the
1144:    * component directly to the JTabbedPane.
1145:    *
1146:    * @param component The associated component.
1147:    * @param index The index to insert the tab at.
1148:    *
1149:    * @return The Component that was added.
1150:    */
1151:   public Component add(Component component, int index)
1152:   {
1153:     if (component instanceof UIResource)
1154:       super.add(component);
1155:     else
1156:       insertTab(component.getName(), null, component, null, index);
1157:     return component;
1158:   }
1159: 
1160:   /**
1161:    * This method adds a tab to the JTabbedPane. If the Component is an
1162:    * instance of UIResource, it doesn't add the tab and instead add the
1163:    * component directly to the JTabbedPane. If the constraints object is an
1164:    * icon, it will be used as the tab's icon. If the constraints object is a
1165:    * string, we will use it as the title.
1166:    *
1167:    * @param component The associated component.
1168:    * @param constraints The constraints object.
1169:    */
1170:   public void add(Component component, Object constraints)
1171:   {
1172:     add(component, constraints, tabs.size());
1173:   }
1174: 
1175:   /**
1176:    * This method adds a tab to the JTabbedPane. If the Component is an
1177:    * instance of UIResource, it doesn't add the tab and instead add the
1178:    * component directly to the JTabbedPane. If the constraints object is an
1179:    * icon, it will be used as the tab's icon. If the constraints object is a
1180:    * string, we will use it as the title.
1181:    *
1182:    * @param component The associated component.
1183:    * @param constraints The constraints object.
1184:    * @param index The index to insert the tab at.
1185:    */
1186:   public void add(Component component, Object constraints, int index)
1187:   {
1188:     if (component instanceof UIResource)
1189:       super.add(component);
1190:     else
1191:       {
1192:     if (constraints instanceof String)
1193:       insertTab((String) constraints, null, component, null, index);
1194:     else
1195:       insertTab(component.getName(),
1196:                 (constraints instanceof Icon) ? (Icon) constraints : null,
1197:                 component, null, index);
1198:       }
1199:   }
1200: 
1201:   /**
1202:    * Removes the tab at index. After the component associated with 
1203:    * index is removed, its visibility is reset to true to ensure it 
1204:    * will be visible if added to other containers.
1205:    *
1206:    * @param index The index of the tab to remove.
1207:    */
1208:   public void removeTabAt(int index)
1209:   {
1210:     checkIndex(index, 0, tabs.size());
1211: 
1212:     // We need to adjust the selection if we remove a tab that comes
1213:     // before the selected tab or if the selected tab is removed.
1214:     // This decrements the selected index by 1 if any of this is the case.
1215:     // Note that this covers all cases:
1216:     // - When the selected tab comes after the removed tab, this simply
1217:     //   adjusts the selection so that after the removal the selected tab
1218:     //   is still the same.
1219:     // - When we remove the currently selected tab, then the tab before the
1220:     //   selected tab gets selected.
1221:     // - When the last tab is removed, then we have an index==0, which gets
1222:     //   decremented to -1, which means no selection, which is 100% perfect.
1223:     int selectedIndex = getSelectedIndex();
1224:     if (selectedIndex >= index)
1225:       setSelectedIndex(selectedIndex - 1);
1226: 
1227:     Component comp = getComponentAt(index);
1228: 
1229:     // Remove the tab object.
1230:     tabs.remove(index);
1231: 
1232:     // Remove the component. I think we cannot assume that the tab order
1233:     // is equal to the component order, so we iterate over the children
1234:     // here to find the and remove the correct component.
1235:     if (comp != null)
1236:       {
1237:         Component[] children = getComponents();
1238:         for (int i = children.length - 1; i >= 0; --i)
1239:           {
1240:             if (children[i] == comp)
1241:               {
1242:                 super.remove(i);
1243:                 comp.setVisible(true);
1244:                 break;
1245:               }
1246:           }
1247:       }
1248:     revalidate();
1249:     repaint();
1250:   }
1251: 
1252:   /**
1253:    * Removes the specified Component from the JTabbedPane.
1254:    *
1255:    * @param component The Component to remove.
1256:    */
1257:   public void remove(Component component)
1258:   {
1259:     // Since components implementing UIResource
1260:     // are not added as regular tabs by the add()
1261:     // methods we have to take special care when
1262:     // removing these object. Especially 
1263:     // Container.remove(Component) cannot be used
1264:     // because it will call JTabbedPane.remove(int)
1265:     // later which is overridden and can only
1266:     // handle tab components.
1267:     // This implementation can even cope with a
1268:     // situation that someone called insertTab()
1269:     // with a component that implements UIResource.
1270:     int index = indexOfComponent(component);
1271:     
1272:     // If the component is not a tab component
1273:     // find out its Container-given index
1274:     // and call that class' implementation
1275:     // directly.
1276:     if (index == -1)
1277:       {
1278:         Component[] cs = getComponents();
1279:         for (int i = 0; i< cs.length; i++)
1280:           if (cs[i] == component)
1281:             super.remove(i);
1282:       }
1283:     else
1284:       removeTabAt(index);
1285:   }
1286: 
1287:   /**
1288:    * Removes the tab and component which corresponds to the specified index.
1289:    *
1290:    * @param index The index of the tab to remove.
1291:    */
1292:   public void remove(int index)
1293:   {
1294:     removeTabAt(index);
1295:   }
1296: 
1297:   /**
1298:    * This method removes all tabs and associated components from the
1299:    * JTabbedPane.
1300:    */
1301:   public void removeAll()
1302:   {
1303:     setSelectedIndex(-1);
1304:     for (int i = getTabCount() - 1; i >= 0; i--)
1305:       removeTabAt(i);
1306:   }
1307: 
1308:   /**
1309:    * This method returns how many tabs are in the JTabbedPane.
1310:    *
1311:    * @return The number of tabs in the JTabbedPane.
1312:    */
1313:   public int getTabCount()
1314:   {
1315:     return tabs.size();
1316:   }
1317: 
1318:   /**
1319:    * This method returns the number of runs used  to paint the JTabbedPane.
1320:    *
1321:    * @return The number of runs.
1322:    */
1323:   public int getTabRunCount()
1324:   {
1325:     return ((TabbedPaneUI) ui).getTabRunCount(this);
1326:   }
1327: 
1328:   /**
1329:    * This method returns the tab title given the index.
1330:    *
1331:    * @param index The index of the tab.
1332:    *
1333:    * @return The title for the tab.
1334:    */
1335:   public String getTitleAt(int index)
1336:   {
1337:     checkIndex(index, 0, tabs.size());
1338:     return ((Page) tabs.elementAt(index)).getTitle();
1339:   }
1340: 
1341:   /**
1342:    * This method returns the active icon given the index.
1343:    *
1344:    * @param index The index of the tab.
1345:    *
1346:    * @return The active icon for the tab.
1347:    */
1348:   public Icon getIconAt(int index)
1349:   {
1350:     checkIndex(index, 0, tabs.size());
1351:     return ((Page) tabs.elementAt(index)).getIcon();
1352:   }
1353: 
1354:   /**
1355:    * This method returns the disabled icon given the index.
1356:    *
1357:    * @param index The index of the tab.
1358:    *
1359:    * @return The disabled icon for the tab.
1360:    */
1361:   public Icon getDisabledIconAt(int index)
1362:   {
1363:     checkIndex(index, 0, tabs.size());
1364:     return ((Page) tabs.elementAt(index)).getDisabledIcon();
1365:   }
1366: 
1367:   /**
1368:    * This method returns the tooltip string for the tab.
1369:    *
1370:    * @param index The index of the tab.
1371:    *
1372:    * @return The tooltip string for the tab.
1373:    */
1374:   public String getToolTipTextAt(int index)
1375:   {
1376:     checkIndex(index, 0, tabs.size());
1377:     return ((Page) tabs.elementAt(index)).getTip();
1378:   }
1379: 
1380:   /**
1381:    * This method returns the foreground color for the tab.
1382:    *
1383:    * @param index The index of the tab.
1384:    *
1385:    * @return The foreground color for the tab.
1386:    */
1387:   public Color getForegroundAt(int index)
1388:   {
1389:     checkIndex(index, 0, tabs.size());
1390:     return ((Page) tabs.elementAt(index)).getForeground();
1391:   }
1392: 
1393:   /**
1394:    * This method returns the background color for the tab.
1395:    *
1396:    * @param index The index of the tab.
1397:    *
1398:    * @return The background color for the tab.
1399:    */
1400:   public Color getBackgroundAt(int index)
1401:   {
1402:     checkIndex(index, 0, tabs.size());
1403:     return ((Page) tabs.elementAt(index)).getBackground();
1404:   }
1405: 
1406:   /**
1407:    * This method returns the component associated with the tab.
1408:    *
1409:    * @param index The index of the tab.
1410:    *
1411:    * @return The component associated with the tab.
1412:    */
1413:   public Component getComponentAt(int index)
1414:   {
1415:     checkIndex(index, 0, tabs.size());
1416:     return ((Page) tabs.elementAt(index)).getComponent();
1417:   }
1418: 
1419:   /**
1420:    * This method returns whether this tab is enabled. Disabled tabs cannot be
1421:    * selected.
1422:    *
1423:    * @param index The index of the tab.
1424:    *
1425:    * @return Whether the tab is enabled.
1426:    */
1427:   public boolean isEnabledAt(int index)
1428:   {
1429:     checkIndex(index, 0, tabs.size());
1430:     return ((Page) tabs.elementAt(index)).isEnabled();
1431:   }
1432: 
1433:   /**
1434:    * This method returns the mnemonic for the tab.
1435:    *
1436:    * @param tabIndex The index of the tab.
1437:    *
1438:    * @return The mnemonic for the tab.
1439:    */
1440:   public int getMnemonicAt(int tabIndex)
1441:   {
1442:     checkIndex(tabIndex, 0, tabs.size());
1443:     return ((Page) tabs.elementAt(tabIndex)).getMnemonic();
1444:   }
1445: 
1446:   /**
1447:    * This method returns the mnemonic index for the tab.
1448:    *
1449:    * @param tabIndex The index of the tab.
1450:    *
1451:    * @return The mnemonic index for the tab.
1452:    */
1453:   public int getDisplayedMnemonicIndexAt(int tabIndex)
1454:   {
1455:     checkIndex(tabIndex, 0, tabs.size());
1456:     return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex();
1457:   }
1458: 
1459:   /**
1460:    * This method returns the bounds of the tab given the index.
1461:    *
1462:    * @param index The index of the tab.
1463:    *
1464:    * @return A rectangle describing the bounds of the tab.
1465:    */
1466:   public Rectangle getBoundsAt(int index)
1467:   {
1468:     checkIndex(index, 0, tabs.size());
1469:     return ((TabbedPaneUI) ui).getTabBounds(this, index);
1470:   }
1471: 
1472:   /**
1473:    * This method sets the title of the tab.
1474:    *
1475:    * @param index The index of the tab.
1476:    * @param title The new title.
1477:    */
1478:   public void setTitleAt(int index, String title)
1479:   {
1480:     checkIndex(index, 0, tabs.size());
1481:     ((Page) tabs.elementAt(index)).setTitle(title);
1482:   }
1483: 
1484:   /**
1485:    * This method sets the icon of the tab.
1486:    *
1487:    * @param index The index of the tab.
1488:    * @param icon The new icon.
1489:    */
1490:   public void setIconAt(int index, Icon icon)
1491:   {
1492:     checkIndex(index, 0, tabs.size());
1493:     ((Page) tabs.elementAt(index)).setIcon(icon);
1494:   }
1495: 
1496:   /**
1497:    * This method sets the disabled icon of the tab.
1498:    *
1499:    * @param index The index of the tab.
1500:    * @param disabledIcon The new disabled icon.
1501:    */
1502:   public void setDisabledIconAt(int index, Icon disabledIcon)
1503:   {
1504:     checkIndex(index, 0, tabs.size());
1505:     ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon);
1506:   }
1507: 
1508:   /**
1509:    * This method sets the tooltip text of the tab.
1510:    *
1511:    * @param index The index of the tab.
1512:    * @param toolTipText The tooltip text.
1513:    */
1514:   public void setToolTipTextAt(int index, String toolTipText)
1515:   {
1516:     checkIndex(index, 0, tabs.size());
1517:     ((Page) tabs.elementAt(index)).setTip(toolTipText);
1518:   }
1519: 
1520:   /**
1521:    * This method sets the background color of the tab.
1522:    *
1523:    * @param index The index of the tab.
1524:    * @param background The background color of the tab.
1525:    */
1526:   public void setBackgroundAt(int index, Color background)
1527:   {
1528:     checkIndex(index, 0, tabs.size());
1529:     ((Page) tabs.elementAt(index)).setBackground(background);
1530:   }
1531: 
1532:   /**
1533:    * This method sets the foreground color of the tab.
1534:    *
1535:    * @param index The index of the tab.
1536:    * @param foreground The foreground color of the tab.
1537:    */
1538:   public void setForegroundAt(int index, Color foreground)
1539:   {
1540:     checkIndex(index, 0, tabs.size());
1541:     ((Page) tabs.elementAt(index)).setForeground(foreground);
1542:   }
1543: 
1544:   /**
1545:    * This method sets whether the tab is enabled.
1546:    *
1547:    * @param index The index of the tab.
1548:    * @param enabled Whether the tab is enabled.
1549:    */
1550:   public void setEnabledAt(int index, boolean enabled)
1551:   {
1552:     checkIndex(index, 0, tabs.size());
1553:     ((Page) tabs.elementAt(index)).setEnabled(enabled);
1554:   }
1555: 
1556:   /**
1557:    * This method sets the component associated with the tab.
1558:    *
1559:    * @param index The index of the tab.
1560:    * @param component The component associated with the tab.
1561:    */
1562:   public void setComponentAt(int index, Component component)
1563:   {
1564:     checkIndex(index, 0, tabs.size());
1565:     ((Page) tabs.elementAt(index)).setComponent(component);
1566:   }
1567: 
1568:   /**
1569:    * This method sets the displayed mnemonic index of the tab.
1570:    *
1571:    * @param tabIndex The index of the tab.
1572:    * @param mnemonicIndex The mnemonic index.
1573:    */
1574:   public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex)
1575:   {
1576:     checkIndex(tabIndex, 0, tabs.size());
1577:     ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex);
1578:   }
1579: 
1580:   /**
1581:    * This method sets the mnemonic for the tab.
1582:    *
1583:    * @param tabIndex The index of the tab.
1584:    * @param mnemonic The mnemonic.
1585:    */
1586:   public void setMnemonicAt(int tabIndex, int mnemonic)
1587:   {
1588:     checkIndex(tabIndex, 0, tabs.size());
1589:     ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic);
1590:   }
1591: 
1592:   /**
1593:    * This method finds the index of a tab given the title.
1594:    *
1595:    * @param title The title that belongs to a tab.
1596:    *
1597:    * @return The index of the tab that has the title or -1 if not found.
1598:    */
1599:   public int indexOfTab(String title)
1600:   {
1601:     int index = -1;
1602:     for (int i = 0; i < tabs.size(); i++)
1603:       {
1604:     if (((Page) tabs.elementAt(i)).getTitle().equals(title))
1605:       {
1606:         index = i;
1607:         break;
1608:       }
1609:       }
1610:     return index;
1611:   }
1612: 
1613:   /**
1614:    * This method finds the index of a tab given the icon.
1615:    *
1616:    * @param icon The icon that belongs to a tab.
1617:    *
1618:    * @return The index of the tab that has the icon or -1 if not found.
1619:    */
1620:   public int indexOfTab(Icon icon)
1621:   {
1622:     int index = -1;
1623:     for (int i = 0; i < tabs.size(); i++)
1624:       {
1625:     if (((Page) tabs.elementAt(i)).getIcon() == icon)
1626:       {
1627:         index = i;
1628:         break;
1629:       }
1630:       }
1631:     return index;
1632:   }
1633: 
1634:   /**
1635:    * This method finds the index of a tab given the component.
1636:    *
1637:    * @param component A component associated with a tab.
1638:    *
1639:    * @return The index of the tab that has this component or -1 if not found.
1640:    */
1641:   public int indexOfComponent(Component component)
1642:   {
1643:     int index = -1;
1644:     for (int i = 0; i < tabs.size(); i++)
1645:       {
1646:     if (((Page) tabs.elementAt(i)).getComponent() == component)
1647:       {
1648:         index = i;
1649:         break;
1650:       }
1651:       }
1652:     return index;
1653:   }
1654: 
1655:   /**
1656:    * This method returns a tab index given an (x,y) location. The origin of
1657:    * the (x,y) pair will be the JTabbedPane's top left position. The  tab
1658:    * returned will be the one that contains the point. This method is
1659:    * delegated to the UI.
1660:    *
1661:    * @param x The x coordinate of the point.
1662:    * @param y The y coordinate of the point.
1663:    *
1664:    * @return The index of the tab that contains the point.
1665:    */
1666:   public int indexAtLocation(int x, int y)
1667:   {
1668:     return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y);
1669:   }
1670: 
1671:   /**
1672:    * This method returns the tooltip text given a mouse event.
1673:    *
1674:    * @param event The mouse event.
1675:    *
1676:    * @return The tool tip text that is associated with this mouse event.
1677:    */
1678:   public String getToolTipText(MouseEvent event)
1679:   {
1680:     int index = indexAtLocation(event.getX(), event.getY());
1681:     return ((Page) tabs.elementAt(index)).getTip();
1682:   }
1683: 
1684:   /**
1685:    * Returns a string describing the attributes for the 
1686:    * <code>JTabbedPane</code> component, for use in debugging.  The return 
1687:    * value is guaranteed to be non-<code>null</code>, but the format of the 
1688:    * string may vary between implementations.
1689:    *
1690:    * @return A string describing the attributes of the 
1691:    *     <code>JTabbedPane</code>.
1692:    */
1693:   protected String paramString()
1694:   {
1695:     StringBuffer sb = new StringBuffer(super.paramString());
1696:     sb.append(",tabPlacement=");
1697:     if (tabPlacement == TOP)
1698:       sb.append("TOP");
1699:     if (tabPlacement == BOTTOM)
1700:       sb.append("BOTTOM");
1701:     if (tabPlacement == LEFT)
1702:       sb.append("LEFT");
1703:     if (tabPlacement == RIGHT)
1704:       sb.append("RIGHT");
1705:     return sb.toString();
1706:   }
1707: 
1708:   /**
1709:    * Returns the object that provides accessibility features for this
1710:    * <code>JTabbedPane</code> component.
1711:    *
1712:    * @return The accessible context (an instance of 
1713:    *         {@link AccessibleJTabbedPane}).
1714:    */
1715:   public AccessibleContext getAccessibleContext()
1716:   {
1717:     if (accessibleContext == null)
1718:       {
1719:         AccessibleJTabbedPane ctx = new AccessibleJTabbedPane();
1720:         addChangeListener(ctx);
1721:         accessibleContext = ctx;
1722:       }
1723: 
1724:     return accessibleContext;
1725:   }
1726: }