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