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:     changeEvent = new ChangeEvent(this);
 764:     changeListener = createChangeListener();
 765: 
 766:     model = new DefaultSingleSelectionModel();
 767:     model.addChangeListener(changeListener);
 768: 
 769:     updateUI();
 770:   }
 771: 
 772:   /**
 773:    * This method returns the UI used to display the JTabbedPane.
 774:    *
 775:    * @return The UI used to display the JTabbedPane.
 776:    */
 777:   public TabbedPaneUI getUI()
 778:   {
 779:     return (TabbedPaneUI) ui;
 780:   }
 781: 
 782:   /**
 783:    * This method sets the UI used to display the JTabbedPane.
 784:    *
 785:    * @param ui The UI used to display the JTabbedPane.
 786:    */
 787:   public void setUI(TabbedPaneUI ui)
 788:   {
 789:     super.setUI(ui);
 790:   }
 791: 
 792:   /**
 793:    * This method restores the UI to the defaults given by the UIManager.
 794:    */
 795:   public void updateUI()
 796:   {
 797:     setUI((TabbedPaneUI) UIManager.getUI(this));
 798:   }
 799: 
 800:   /**
 801:    * This method returns a string identifier that  is used to determine which
 802:    * UI will be used with  the JTabbedPane.
 803:    *
 804:    * @return A string identifier for the UI.
 805:    */
 806:   public String getUIClassID()
 807:   {
 808:     return "TabbedPaneUI";
 809:   }
 810: 
 811:   /**
 812:    * This method creates a ChangeListener that is used to  listen to the model
 813:    * for events.
 814:    *
 815:    * @return A ChangeListener to listen to the model.
 816:    */
 817:   protected ChangeListener createChangeListener()
 818:   {
 819:     return new ModelListener();
 820:   }
 821: 
 822:   /**
 823:    * This method adds a ChangeListener to the JTabbedPane.
 824:    *
 825:    * @param l The ChangeListener to add.
 826:    */
 827:   public void addChangeListener(ChangeListener l)
 828:   {
 829:     listenerList.add(ChangeListener.class, l);
 830:   }
 831: 
 832:   /**
 833:    * This method removes a ChangeListener to the JTabbedPane.
 834:    *
 835:    * @param l The ChangeListener to remove.
 836:    */
 837:   public void removeChangeListener(ChangeListener l)
 838:   {
 839:     listenerList.remove(ChangeListener.class, l);
 840:   }
 841: 
 842:   /**
 843:    * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners.
 844:    */
 845:   protected void fireStateChanged()
 846:   {
 847:     Object[] changeListeners = listenerList.getListenerList();
 848:     if (changeEvent == null)
 849:       changeEvent = new ChangeEvent(this);
 850:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 851:       {
 852:     if (changeListeners[i] == ChangeListener.class)
 853:       ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 854:       }
 855:   }
 856: 
 857:   /**
 858:    * This method returns all ChangeListeners registered with the JTabbedPane.
 859:    *
 860:    * @return The ChangeListeners registered with the JTabbedPane.
 861:    */
 862:   public ChangeListener[] getChangeListeners()
 863:   {
 864:     return (ChangeListener[]) super.getListeners(ChangeListener.class);
 865:   }
 866: 
 867:   /**
 868:    * This method returns the model used with the JTabbedPane.
 869:    *
 870:    * @return The JTabbedPane's model.
 871:    */
 872:   public SingleSelectionModel getModel()
 873:   {
 874:     return model;
 875:   }
 876: 
 877:   /**
 878:    * This method changes the model property of the JTabbedPane.
 879:    *
 880:    * @param model The new model to use with the JTabbedPane.
 881:    */
 882:   public void setModel(SingleSelectionModel model)
 883:   {
 884:     if (model != this.model)
 885:       {
 886:     SingleSelectionModel oldModel = this.model;
 887:     this.model.removeChangeListener(changeListener);
 888:     this.model = model;
 889:     this.model.addChangeListener(changeListener);
 890:     firePropertyChange("model", oldModel, this.model);
 891:       }
 892:   }
 893: 
 894:   /**
 895:    * This method returns the tabPlacement.
 896:    *
 897:    * @return The tabPlacement used with the JTabbedPane.
 898:    */
 899:   public int getTabPlacement()
 900:   {
 901:     return tabPlacement;
 902:   }
 903: 
 904:   /**
 905:    * This method changes the tabPlacement property of the JTabbedPane.
 906:    *
 907:    * @param tabPlacement The tabPlacement to use.
 908:    *
 909:    * @throws IllegalArgumentException If tabPlacement is not one of TOP,
 910:    *         BOTTOM, LEFT, or RIGHT.
 911:    */
 912:   public void setTabPlacement(int tabPlacement)
 913:   {
 914:     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
 915:         && tabPlacement != LEFT)
 916:       throw new IllegalArgumentException("tabPlacement is not valid.");
 917:     if (tabPlacement != this.tabPlacement)
 918:       {
 919:     int oldPlacement = this.tabPlacement;
 920:     this.tabPlacement = tabPlacement;
 921:     firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement);
 922:       }
 923:   }
 924: 
 925:   /**
 926:    * This method returns the tabLayoutPolicy.
 927:    *
 928:    * @return The tabLayoutPolicy.
 929:    */
 930:   public int getTabLayoutPolicy()
 931:   {
 932:     return layoutPolicy;
 933:   }
 934: 
 935:   /**
 936:    * This method changes the tabLayoutPolicy property of the JTabbedPane.
 937:    *
 938:    * @param tabLayoutPolicy The tabLayoutPolicy to use.
 939:    *
 940:    * @throws IllegalArgumentException If tabLayoutPolicy is not one of
 941:    *         SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT.
 942:    */
 943:   public void setTabLayoutPolicy(int tabLayoutPolicy)
 944:   {
 945:     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
 946:         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
 947:       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
 948:     if (tabLayoutPolicy != layoutPolicy)
 949:       {
 950:     int oldPolicy = layoutPolicy;
 951:     layoutPolicy = tabLayoutPolicy;
 952:     firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy);
 953:       }
 954:   }
 955: 
 956:   /**
 957:    * This method returns the index of the tab that is currently selected.
 958:    *
 959:    * @return The index of the selected tab.
 960:    */
 961:   public int getSelectedIndex()
 962:   {
 963:     return model.getSelectedIndex();
 964:   }
 965: 
 966:   /**
 967:    * This method checks the index.
 968:    *
 969:    * @param index The index to check.
 970:    * @param start DOCUMENT ME!
 971:    * @param end DOCUMENT ME!
 972:    *
 973:    * @throws IndexOutOfBoundsException DOCUMENT ME!
 974:    */
 975:   private void checkIndex(int index, int start, int end)
 976:   {
 977:     if (index < start || index >= end)
 978:       throw new IndexOutOfBoundsException("Index < " + start + " || Index >= "
 979:                                           + end);
 980:   }
 981: 
 982:   /**
 983:    * This method sets the selected index. This method will hide the old
 984:    * component and show the new component.
 985:    *
 986:    * @param index The index to set it at.
 987:    */
 988:   public void setSelectedIndex(int index)
 989:   {
 990:     checkIndex(index, -1, tabs.size());
 991:     if (index != getSelectedIndex())
 992:       {
 993:         // Hiding and showing the involved components
 994:         // is done by the JTabbedPane's UI.
 995:     model.setSelectedIndex(index);
 996:       }
 997:   }
 998: 
 999:   /**
1000:    * This method returns the component at the selected index.
1001:    *
1002:    * @return The component at the selected index.
1003:    */
1004:   public Component getSelectedComponent()
1005:   {
1006:     int selectedIndex = getSelectedIndex();
1007:     Component selected = null;
1008:     if (selectedIndex >= 0)
1009:       selected = getComponentAt(selectedIndex);
1010:     return selected;
1011:   }
1012: 
1013:   /**
1014:    * This method sets the component at the selected index.
1015:    *
1016:    * @param c The component associated with the selected index.
1017:    */
1018:   public void setSelectedComponent(Component c)
1019:   {
1020:     if (c.getParent() == this)
1021:       setSelectedIndex(indexOfComponent(c));
1022:     else
1023:       setComponentAt(getSelectedIndex(), c);
1024:   }
1025: 
1026:   /**
1027:    * This method inserts tabs into JTabbedPane. This includes adding the
1028:    * component to the JTabbedPane and hiding it.
1029:    *
1030:    * @param title the title of the tab; may be <code>null</code>
1031:    * @param icon the tab's icon; may be <code>null</code>
1032:    * @param component the component associated with the tab
1033:    * @param tip the tooltip for the tab
1034:    * @param index the index to insert the tab at
1035:    */
1036:   public void insertTab(String title, Icon icon, Component component,
1037:                         String tip, int index)
1038:   {
1039:     if (title == null)
1040:       title = "";
1041:     Page p = new Page(title, icon, component, tip);
1042:     tabs.insertElementAt(p, index);
1043: 
1044:     // Hide the component so we don't see it. Do it before we parent it
1045:     // so we don't trigger a repaint.
1046:     if (component != null)
1047:       {
1048:     component.hide();
1049:     super.add(component);
1050:       }
1051: 
1052:     if (getSelectedIndex() == -1)
1053:       setSelectedIndex(0);
1054: 
1055:     revalidate();
1056:     repaint();
1057:   }
1058: 
1059:   /**
1060:    * This method adds a tab to the JTabbedPane.
1061:    *
1062:    * @param title the title of the tab; may be <code>null</code>
1063:    * @param icon the icon for the tab; may be <code>null</code>
1064:    * @param component the associated component
1065:    * @param tip the associated tooltip
1066:    */
1067:   public void addTab(String title, Icon icon, Component component, String tip)
1068:   {
1069:     insertTab(title, icon, component, tip, tabs.size());
1070:   }
1071: 
1072:   /**
1073:    * This method adds a tab to the JTabbedPane.
1074:    *
1075:    * @param title the title of the tab; may be <code>null</code>
1076:    * @param icon the icon for the tab; may be <code>null</code>
1077:    * @param component the associated component
1078:    */
1079:   public void addTab(String title, Icon icon, Component component)
1080:   {
1081:     insertTab(title, icon, component, null, tabs.size());
1082:   }
1083: 
1084:   /**
1085:    * This method adds a tab to the JTabbedPane.
1086:    *
1087:    * @param title the title of the tab; may be <code>null</code>
1088:    * @param component the associated component
1089:    */
1090:   public void addTab(String title, Component component)
1091:   {
1092:     insertTab(title, null, component, null, tabs.size());
1093:   }
1094: 
1095:   /**
1096:    * This method adds a tab to the JTabbedPane. The title of the tab is the
1097:    * Component's name. If the Component is an instance of UIResource, it
1098:    * doesn't add the tab and instead add the component directly to the
1099:    * JTabbedPane.
1100:    *
1101:    * @param component The associated component.
1102:    *
1103:    * @return The Component that was added.
1104:    */
1105:   public Component add(Component component)
1106:   {
1107:     if (component instanceof UIResource)
1108:       super.add(component);
1109:     else
1110:       insertTab(component.getName(), null, component, null, tabs.size());
1111:     
1112:     return component;
1113:   }
1114: 
1115:   /**
1116:    * This method adds a tab to the JTabbedPane. If the Component is an
1117:    * instance of UIResource, it doesn't add the tab and instead add the
1118:    * component directly to the JTabbedPane.
1119:    *
1120:    * @param title the title of the tab; may be <code>null</code>
1121:    * @param component the associated component
1122:    *
1123:    * @return The Component that was added.
1124:    */
1125:   public Component add(String title, Component component)
1126:   {
1127:     if (component instanceof UIResource)
1128:       super.add(component);
1129:     else
1130:       insertTab(title, null, component, null, tabs.size());
1131:     return component;
1132:   }
1133: 
1134:   /**
1135:    * This method adds a tab to the JTabbedPane. If the Component is an
1136:    * instance of UIResource, it doesn't add the tab and instead add the
1137:    * component directly to the JTabbedPane.
1138:    *
1139:    * @param component The associated component.
1140:    * @param index The index to insert the tab at.
1141:    *
1142:    * @return The Component that was added.
1143:    */
1144:   public Component add(Component component, int index)
1145:   {
1146:     if (component instanceof UIResource)
1147:       super.add(component);
1148:     else
1149:       insertTab(component.getName(), null, component, null, index);
1150:     return component;
1151:   }
1152: 
1153:   /**
1154:    * This method adds a tab to the JTabbedPane. If the Component is an
1155:    * instance of UIResource, it doesn't add the tab and instead add the
1156:    * component directly to the JTabbedPane. If the constraints object is an
1157:    * icon, it will be used as the tab's icon. If the constraints object is a
1158:    * string, we will use it as the title.
1159:    *
1160:    * @param component The associated component.
1161:    * @param constraints The constraints object.
1162:    */
1163:   public void add(Component component, Object constraints)
1164:   {
1165:     add(component, constraints, tabs.size());
1166:   }
1167: 
1168:   /**
1169:    * This method adds a tab to the JTabbedPane. If the Component is an
1170:    * instance of UIResource, it doesn't add the tab and instead add the
1171:    * component directly to the JTabbedPane. If the constraints object is an
1172:    * icon, it will be used as the tab's icon. If the constraints object is a
1173:    * string, we will use it as the title.
1174:    *
1175:    * @param component The associated component.
1176:    * @param constraints The constraints object.
1177:    * @param index The index to insert the tab at.
1178:    */
1179:   public void add(Component component, Object constraints, int index)
1180:   {
1181:     if (component instanceof UIResource)
1182:       super.add(component);
1183:     else
1184:       {
1185:     if (constraints instanceof String)
1186:       insertTab((String) constraints, null, component, null, index);
1187:     else
1188:       insertTab(component.getName(),
1189:                 (constraints instanceof Icon) ? (Icon) constraints : null,
1190:                 component, null, index);
1191:       }
1192:   }
1193: 
1194:   /**
1195:    * Removes the tab at index. After the component associated with 
1196:    * index is removed, its visibility is reset to true to ensure it 
1197:    * will be visible if added to other containers.
1198:    *
1199:    * @param index The index of the tab to remove.
1200:    */
1201:   public void removeTabAt(int index)
1202:   {
1203:     checkIndex(index, 0, tabs.size());
1204: 
1205:     // We need to adjust the selection if we remove a tab that comes
1206:     // before the selected tab or if the selected tab is removed.
1207:     // This decrements the selected index by 1 if any of this is the case.
1208:     // Note that this covers all cases:
1209:     // - When the selected tab comes after the removed tab, this simply
1210:     //   adjusts the selection so that after the removal the selected tab
1211:     //   is still the same.
1212:     // - When we remove the currently selected tab, then the tab before the
1213:     //   selected tab gets selected.
1214:     // - When the last tab is removed, then we have an index==0, which gets
1215:     //   decremented to -1, which means no selection, which is 100% perfect.
1216:     int selectedIndex = getSelectedIndex();
1217:     if (selectedIndex >= index)
1218:       setSelectedIndex(selectedIndex - 1);
1219: 
1220:     Component comp = getComponentAt(index);
1221: 
1222:     // Remove the tab object.
1223:     tabs.remove(index);
1224: 
1225:     // Remove the component. I think we cannot assume that the tab order
1226:     // is equal to the component order, so we iterate over the children
1227:     // here to find the and remove the correct component.
1228:     if (comp != null)
1229:       {
1230:         Component[] children = getComponents();
1231:         for (int i = children.length - 1; i >= 0; --i)
1232:           {
1233:             if (children[i] == comp)
1234:               {
1235:                 super.remove(i);
1236:                 comp.setVisible(true);
1237:                 break;
1238:               }
1239:           }
1240:       }
1241:     revalidate();
1242:     repaint();
1243:   }
1244: 
1245:   /**
1246:    * Removes the specified Component from the JTabbedPane.
1247:    *
1248:    * @param component The Component to remove.
1249:    */
1250:   public void remove(Component component)
1251:   {
1252:     // Since components implementing UIResource
1253:     // are not added as regular tabs by the add()
1254:     // methods we have to take special care when
1255:     // removing these object. Especially 
1256:     // Container.remove(Component) cannot be used
1257:     // because it will call JTabbedPane.remove(int)
1258:     // later which is overridden and can only
1259:     // handle tab components.
1260:     // This implementation can even cope with a
1261:     // situation that someone called insertTab()
1262:     // with a component that implements UIResource.
1263:     int index = indexOfComponent(component);
1264:     
1265:     // If the component is not a tab component
1266:     // find out its Container-given index
1267:     // and call that class' implementation
1268:     // directly.
1269:     if (index == -1)
1270:       {
1271:         Component[] cs = getComponents();
1272:         for (int i = 0; i< cs.length; i++)
1273:           if (cs[i] == component)
1274:             super.remove(i);
1275:       }
1276:     else
1277:       removeTabAt(index);
1278:   }
1279: 
1280:   /**
1281:    * Removes the tab and component which corresponds to the specified index.
1282:    *
1283:    * @param index The index of the tab to remove.
1284:    */
1285:   public void remove(int index)
1286:   {
1287:     removeTabAt(index);
1288:   }
1289: 
1290:   /**
1291:    * This method removes all tabs and associated components from the
1292:    * JTabbedPane.
1293:    */
1294:   public void removeAll()
1295:   {
1296:     setSelectedIndex(-1);
1297:     for (int i = getTabCount() - 1; i >= 0; i--)
1298:       removeTabAt(i);
1299:   }
1300: 
1301:   /**
1302:    * This method returns how many tabs are in the JTabbedPane.
1303:    *
1304:    * @return The number of tabs in the JTabbedPane.
1305:    */
1306:   public int getTabCount()
1307:   {
1308:     return tabs.size();
1309:   }
1310: 
1311:   /**
1312:    * This method returns the number of runs used  to paint the JTabbedPane.
1313:    *
1314:    * @return The number of runs.
1315:    */
1316:   public int getTabRunCount()
1317:   {
1318:     return ((TabbedPaneUI) ui).getTabRunCount(this);
1319:   }
1320: 
1321:   /**
1322:    * This method returns the tab title given the index.
1323:    *
1324:    * @param index The index of the tab.
1325:    *
1326:    * @return The title for the tab.
1327:    */
1328:   public String getTitleAt(int index)
1329:   {
1330:     checkIndex(index, 0, tabs.size());
1331:     return ((Page) tabs.elementAt(index)).getTitle();
1332:   }
1333: 
1334:   /**
1335:    * This method returns the active icon given the index.
1336:    *
1337:    * @param index The index of the tab.
1338:    *
1339:    * @return The active icon for the tab.
1340:    */
1341:   public Icon getIconAt(int index)
1342:   {
1343:     checkIndex(index, 0, tabs.size());
1344:     return ((Page) tabs.elementAt(index)).getIcon();
1345:   }
1346: 
1347:   /**
1348:    * This method returns the disabled icon given the index.
1349:    *
1350:    * @param index The index of the tab.
1351:    *
1352:    * @return The disabled icon for the tab.
1353:    */
1354:   public Icon getDisabledIconAt(int index)
1355:   {
1356:     checkIndex(index, 0, tabs.size());
1357:     return ((Page) tabs.elementAt(index)).getDisabledIcon();
1358:   }
1359: 
1360:   /**
1361:    * This method returns the tooltip string for the tab.
1362:    *
1363:    * @param index The index of the tab.
1364:    *
1365:    * @return The tooltip string for the tab.
1366:    */
1367:   public String getToolTipTextAt(int index)
1368:   {
1369:     checkIndex(index, 0, tabs.size());
1370:     return ((Page) tabs.elementAt(index)).getTip();
1371:   }
1372: 
1373:   /**
1374:    * This method returns the foreground color for the tab.
1375:    *
1376:    * @param index The index of the tab.
1377:    *
1378:    * @return The foreground color for the tab.
1379:    */
1380:   public Color getForegroundAt(int index)
1381:   {
1382:     checkIndex(index, 0, tabs.size());
1383:     return ((Page) tabs.elementAt(index)).getForeground();
1384:   }
1385: 
1386:   /**
1387:    * This method returns the background color for the tab.
1388:    *
1389:    * @param index The index of the tab.
1390:    *
1391:    * @return The background color for the tab.
1392:    */
1393:   public Color getBackgroundAt(int index)
1394:   {
1395:     checkIndex(index, 0, tabs.size());
1396:     return ((Page) tabs.elementAt(index)).getBackground();
1397:   }
1398: 
1399:   /**
1400:    * This method returns the component associated with the tab.
1401:    *
1402:    * @param index The index of the tab.
1403:    *
1404:    * @return The component associated with the tab.
1405:    */
1406:   public Component getComponentAt(int index)
1407:   {
1408:     checkIndex(index, 0, tabs.size());
1409:     return ((Page) tabs.elementAt(index)).getComponent();
1410:   }
1411: 
1412:   /**
1413:    * This method returns whether this tab is enabled. Disabled tabs cannot be
1414:    * selected.
1415:    *
1416:    * @param index The index of the tab.
1417:    *
1418:    * @return Whether the tab is enabled.
1419:    */
1420:   public boolean isEnabledAt(int index)
1421:   {
1422:     checkIndex(index, 0, tabs.size());
1423:     return ((Page) tabs.elementAt(index)).isEnabled();
1424:   }
1425: 
1426:   /**
1427:    * This method returns the mnemonic for the tab.
1428:    *
1429:    * @param tabIndex The index of the tab.
1430:    *
1431:    * @return The mnemonic for the tab.
1432:    */
1433:   public int getMnemonicAt(int tabIndex)
1434:   {
1435:     checkIndex(tabIndex, 0, tabs.size());
1436:     return ((Page) tabs.elementAt(tabIndex)).getMnemonic();
1437:   }
1438: 
1439:   /**
1440:    * This method returns the mnemonic index for the tab.
1441:    *
1442:    * @param tabIndex The index of the tab.
1443:    *
1444:    * @return The mnemonic index for the tab.
1445:    */
1446:   public int getDisplayedMnemonicIndexAt(int tabIndex)
1447:   {
1448:     checkIndex(tabIndex, 0, tabs.size());
1449:     return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex();
1450:   }
1451: 
1452:   /**
1453:    * This method returns the bounds of the tab given the index.
1454:    *
1455:    * @param index The index of the tab.
1456:    *
1457:    * @return A rectangle describing the bounds of the tab.
1458:    */
1459:   public Rectangle getBoundsAt(int index)
1460:   {
1461:     checkIndex(index, 0, tabs.size());
1462:     return ((TabbedPaneUI) ui).getTabBounds(this, index);
1463:   }
1464: 
1465:   /**
1466:    * This method sets the title of the tab.
1467:    *
1468:    * @param index The index of the tab.
1469:    * @param title The new title.
1470:    */
1471:   public void setTitleAt(int index, String title)
1472:   {
1473:     checkIndex(index, 0, tabs.size());
1474:     ((Page) tabs.elementAt(index)).setTitle(title);
1475:   }
1476: 
1477:   /**
1478:    * This method sets the icon of the tab.
1479:    *
1480:    * @param index The index of the tab.
1481:    * @param icon The new icon.
1482:    */
1483:   public void setIconAt(int index, Icon icon)
1484:   {
1485:     checkIndex(index, 0, tabs.size());
1486:     ((Page) tabs.elementAt(index)).setIcon(icon);
1487:   }
1488: 
1489:   /**
1490:    * This method sets the disabled icon of the tab.
1491:    *
1492:    * @param index The index of the tab.
1493:    * @param disabledIcon The new disabled icon.
1494:    */
1495:   public void setDisabledIconAt(int index, Icon disabledIcon)
1496:   {
1497:     checkIndex(index, 0, tabs.size());
1498:     ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon);
1499:   }
1500: 
1501:   /**
1502:    * This method sets the tooltip text of the tab.
1503:    *
1504:    * @param index The index of the tab.
1505:    * @param toolTipText The tooltip text.
1506:    */
1507:   public void setToolTipTextAt(int index, String toolTipText)
1508:   {
1509:     checkIndex(index, 0, tabs.size());
1510:     ((Page) tabs.elementAt(index)).setTip(toolTipText);
1511:   }
1512: 
1513:   /**
1514:    * This method sets the background color of the tab.
1515:    *
1516:    * @param index The index of the tab.
1517:    * @param background The background color of the tab.
1518:    */
1519:   public void setBackgroundAt(int index, Color background)
1520:   {
1521:     checkIndex(index, 0, tabs.size());
1522:     ((Page) tabs.elementAt(index)).setBackground(background);
1523:   }
1524: 
1525:   /**
1526:    * This method sets the foreground color of the tab.
1527:    *
1528:    * @param index The index of the tab.
1529:    * @param foreground The foreground color of the tab.
1530:    */
1531:   public void setForegroundAt(int index, Color foreground)
1532:   {
1533:     checkIndex(index, 0, tabs.size());
1534:     ((Page) tabs.elementAt(index)).setForeground(foreground);
1535:   }
1536: 
1537:   /**
1538:    * This method sets whether the tab is enabled.
1539:    *
1540:    * @param index The index of the tab.
1541:    * @param enabled Whether the tab is enabled.
1542:    */
1543:   public void setEnabledAt(int index, boolean enabled)
1544:   {
1545:     checkIndex(index, 0, tabs.size());
1546:     ((Page) tabs.elementAt(index)).setEnabled(enabled);
1547:   }
1548: 
1549:   /**
1550:    * This method sets the component associated with the tab.
1551:    *
1552:    * @param index The index of the tab.
1553:    * @param component The component associated with the tab.
1554:    */
1555:   public void setComponentAt(int index, Component component)
1556:   {
1557:     checkIndex(index, 0, tabs.size());
1558:     ((Page) tabs.elementAt(index)).setComponent(component);
1559:   }
1560: 
1561:   /**
1562:    * This method sets the displayed mnemonic index of the tab.
1563:    *
1564:    * @param tabIndex The index of the tab.
1565:    * @param mnemonicIndex The mnemonic index.
1566:    */
1567:   public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex)
1568:   {
1569:     checkIndex(tabIndex, 0, tabs.size());
1570:     ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex);
1571:   }
1572: 
1573:   /**
1574:    * This method sets the mnemonic for the tab.
1575:    *
1576:    * @param tabIndex The index of the tab.
1577:    * @param mnemonic The mnemonic.
1578:    */
1579:   public void setMnemonicAt(int tabIndex, int mnemonic)
1580:   {
1581:     checkIndex(tabIndex, 0, tabs.size());
1582:     ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic);
1583:   }
1584: 
1585:   /**
1586:    * This method finds the index of a tab given the title.
1587:    *
1588:    * @param title The title that belongs to a tab.
1589:    *
1590:    * @return The index of the tab that has the title or -1 if not found.
1591:    */
1592:   public int indexOfTab(String title)
1593:   {
1594:     int index = -1;
1595:     for (int i = 0; i < tabs.size(); i++)
1596:       {
1597:     if (((Page) tabs.elementAt(i)).getTitle().equals(title))
1598:       {
1599:         index = i;
1600:         break;
1601:       }
1602:       }
1603:     return index;
1604:   }
1605: 
1606:   /**
1607:    * This method finds the index of a tab given the icon.
1608:    *
1609:    * @param icon The icon that belongs to a tab.
1610:    *
1611:    * @return The index of the tab that has the icon or -1 if not found.
1612:    */
1613:   public int indexOfTab(Icon icon)
1614:   {
1615:     int index = -1;
1616:     for (int i = 0; i < tabs.size(); i++)
1617:       {
1618:     if (((Page) tabs.elementAt(i)).getIcon() == icon)
1619:       {
1620:         index = i;
1621:         break;
1622:       }
1623:       }
1624:     return index;
1625:   }
1626: 
1627:   /**
1628:    * This method finds the index of a tab given the component.
1629:    *
1630:    * @param component A component associated with a tab.
1631:    *
1632:    * @return The index of the tab that has this component or -1 if not found.
1633:    */
1634:   public int indexOfComponent(Component component)
1635:   {
1636:     int index = -1;
1637:     for (int i = 0; i < tabs.size(); i++)
1638:       {
1639:     if (((Page) tabs.elementAt(i)).getComponent() == component)
1640:       {
1641:         index = i;
1642:         break;
1643:       }
1644:       }
1645:     return index;
1646:   }
1647: 
1648:   /**
1649:    * This method returns a tab index given an (x,y) location. The origin of
1650:    * the (x,y) pair will be the JTabbedPane's top left position. The  tab
1651:    * returned will be the one that contains the point. This method is
1652:    * delegated to the UI.
1653:    *
1654:    * @param x The x coordinate of the point.
1655:    * @param y The y coordinate of the point.
1656:    *
1657:    * @return The index of the tab that contains the point.
1658:    */
1659:   public int indexAtLocation(int x, int y)
1660:   {
1661:     return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y);
1662:   }
1663: 
1664:   /**
1665:    * This method returns the tooltip text given a mouse event.
1666:    *
1667:    * @param event The mouse event.
1668:    *
1669:    * @return The tool tip text that is associated with this mouse event.
1670:    */
1671:   public String getToolTipText(MouseEvent event)
1672:   {
1673:     int index = indexAtLocation(event.getX(), event.getY());
1674:     return ((Page) tabs.elementAt(index)).getTip();
1675:   }
1676: 
1677:   /**
1678:    * Returns a string describing the attributes for the 
1679:    * <code>JTabbedPane</code> component, for use in debugging.  The return 
1680:    * value is guaranteed to be non-<code>null</code>, but the format of the 
1681:    * string may vary between implementations.
1682:    *
1683:    * @return A string describing the attributes of the 
1684:    *     <code>JTabbedPane</code>.
1685:    */
1686:   protected String paramString()
1687:   {
1688:     StringBuffer sb = new StringBuffer(super.paramString());
1689:     sb.append(",tabPlacement=");
1690:     if (tabPlacement == TOP)
1691:       sb.append("TOP");
1692:     if (tabPlacement == BOTTOM)
1693:       sb.append("BOTTOM");
1694:     if (tabPlacement == LEFT)
1695:       sb.append("LEFT");
1696:     if (tabPlacement == RIGHT)
1697:       sb.append("RIGHT");
1698:     return sb.toString();
1699:   }
1700: 
1701:   /**
1702:    * Returns the object that provides accessibility features for this
1703:    * <code>JTabbedPane</code> component.
1704:    *
1705:    * @return The accessible context (an instance of 
1706:    *         {@link AccessibleJTabbedPane}).
1707:    */
1708:   public AccessibleContext getAccessibleContext()
1709:   {
1710:     if (accessibleContext == null)
1711:       {
1712:         AccessibleJTabbedPane ctx = new AccessibleJTabbedPane();
1713:         addChangeListener(ctx);
1714:         accessibleContext = ctx;
1715:       }
1716: 
1717:     return accessibleContext;
1718:   }
1719: }