Source for javax.swing.JTabbedPane

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