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:       remove(component);
 341:       this.component = c;
 342:       add(c);
 343:     }
 344: 
 345:     /**
 346:      * This method returns the tooltip string.
 347:      *
 348:      * @return The tooltip string.
 349:      */
 350:     public String getTip()
 351:     {
 352:       return tip;
 353:     }
 354: 
 355:     /**
 356:      * This method sets the tooltip string.
 357:      *
 358:      * @param tip The tooltip string.
 359:      */
 360:     public void setTip(String tip)
 361:     {
 362:       this.tip = tip;
 363:     }
 364: 
 365:     /**
 366:      * This method returns the background color.
 367:      *
 368:      * @return The background color.
 369:      */
 370:     public Color getBackground()
 371:     {
 372:       return bg;
 373:     }
 374: 
 375:     /**
 376:      * This method sets the background color.
 377:      *
 378:      * @param background The background color.
 379:      */
 380:     public void setBackground(Color background)
 381:     {
 382:       bg = background;
 383:     }
 384: 
 385:     /**
 386:      * This method returns the foreground color.
 387:      *
 388:      * @return The foreground color.
 389:      */
 390:     public Color getForeground()
 391:     {
 392:       return fg;
 393:     }
 394: 
 395:     /**
 396:      * This method sets the foreground color.
 397:      *
 398:      * @param foreground The foreground color.
 399:      */
 400:     public void setForeground(Color foreground)
 401:     {
 402:       fg = foreground;
 403:     }
 404: 
 405:     /**
 406:      * This method returns the title associated with the tab.
 407:      *
 408:      * @return The title of the tab.
 409:      */
 410:     public String getTitle()
 411:     {
 412:       return title;
 413:     }
 414: 
 415:     /** DOCUMENT ME! */
 416:     private static final long serialVersionUID = 1614381073220130939L;
 417: 
 418:     /**
 419:      * This method sets the title of the tab.
 420:      *
 421:      * @param text The title of the tab.
 422:      */
 423:     public void setTitle(String text)
 424:     {
 425:       title = text;
 426:       if (title != null && title.length() <= underlinedChar)
 427:     setDisplayedMnemonicIndex(title.length() - 1);
 428:     }
 429: 
 430:     /**
 431:      * This method returns the active icon.
 432:      *
 433:      * @return The active icon.
 434:      */
 435:     public Icon getIcon()
 436:     {
 437:       return icon;
 438:     }
 439: 
 440:     /**
 441:      * This method sets the active icon.
 442:      *
 443:      * @param icon The active icon.
 444:      */
 445:     public void setIcon(Icon icon)
 446:     {
 447:       this.icon = icon;
 448:     }
 449: 
 450:     /**
 451:      * This method returns the disabled icon.
 452:      *
 453:      * @return The disabled icon.
 454:      */
 455:     public Icon getDisabledIcon()
 456:     {
 457:       if (disabledIcon == null && icon instanceof ImageIcon)
 458:     setDisabledIcon(icon);
 459:       return disabledIcon;
 460:     }
 461: 
 462:     /**
 463:      * This method sets the disabled icon.
 464:      *
 465:      * @param disabledIcon The disabled icon.
 466:      */
 467:     public void setDisabledIcon(Icon disabledIcon)
 468:     {
 469:       this.disabledIcon = disabledIcon;
 470:     }
 471: 
 472:     /**
 473:      * This method returns whether the tab is enabled.
 474:      *
 475:      * @return Whether the tab is enabled.
 476:      */
 477:     public boolean isEnabled()
 478:     {
 479:       return enabled;
 480:     }
 481: 
 482:     /**
 483:      * This method sets whether the tab is enabled.
 484:      *
 485:      * @param enabled Whether this tab is enabled.
 486:      */
 487:     public void setEnabled(boolean enabled)
 488:     {
 489:       this.enabled = enabled;
 490:     }
 491: 
 492:     /**
 493:      * This method returns the mnemonic.
 494:      *
 495:      * @return The mnemonic.
 496:      */
 497:     public int getMnemonic()
 498:     {
 499:       return (int) mnemonicKey;
 500:     }
 501: 
 502:     /**
 503:      * This method sets the mnemonic. If the title is set, it will update the
 504:      * mnemonicIndex.
 505:      *
 506:      * @param key The mnemonic.
 507:      */
 508:     public void setMnemonic(int key)
 509:     {
 510:       setMnemonic((char) key);
 511:     }
 512: 
 513:     /**
 514:      * This method sets the mnemonic. If the title is set, it will update the
 515:      * mnemonicIndex.
 516:      *
 517:      * @param aChar The mnemonic.
 518:      */
 519:     public void setMnemonic(char aChar)
 520:     {
 521:       mnemonicKey = aChar;
 522:       if (title != null)
 523:     setDisplayedMnemonicIndex(title.indexOf(mnemonicKey));
 524:     }
 525: 
 526:     /**
 527:      * This method returns the mnemonicIndex.
 528:      *
 529:      * @return The mnemonicIndex.
 530:      */
 531:     public int getDisplayedMnemonicIndex()
 532:     {
 533:       return underlinedChar;
 534:     }
 535: 
 536:     /**
 537:      * This method sets the mnemonicIndex.
 538:      *
 539:      * @param index The mnemonicIndex.
 540:      *
 541:      * @throws IllegalArgumentException If index less than -1 || index greater
 542:      *         or equal to title.length.
 543:      */
 544:     public void setDisplayedMnemonicIndex(int index)
 545:       throws IllegalArgumentException
 546:     {
 547:       if (index < -1 || title != null && index >= title.length())
 548:     throw new IllegalArgumentException();
 549: 
 550:       if (title == null || mnemonicKey == 0 || (index > -1 && title.charAt(index) != mnemonicKey))
 551:     index = -1;
 552: 
 553:       underlinedChar = index;
 554:     }
 555:   }
 556: 
 557:   private static final long serialVersionUID = 1614381073220130939L;
 558: 
 559:   /** The changeEvent used to fire changes to listeners. */
 560:   protected ChangeEvent changeEvent;
 561: 
 562:   /** The listener that listens to the model. */
 563:   protected ChangeListener changeListener;
 564: 
 565:   /** The model that describes this JTabbedPane. */
 566:   protected SingleSelectionModel model;
 567: 
 568:   /** Indicates that the TabbedPane is in scrolling mode. */
 569:   public static final int SCROLL_TAB_LAYOUT = 1;
 570: 
 571:   /** Indicates that the TabbedPane is in wrap mode. */
 572:   public static final int WRAP_TAB_LAYOUT = 0;
 573: 
 574:   /** The current tabPlacement of the TabbedPane. */
 575:   protected int tabPlacement = SwingConstants.TOP;
 576: 
 577:   /** The current tabLayoutPolicy of the TabbedPane. */
 578:   private transient int layoutPolicy;
 579: 
 580:   /** The list of tabs associated with the TabbedPane. */
 581:   transient Vector tabs = new Vector();
 582: 
 583:   /**
 584:    * Creates a new JTabbedPane object with tabs on top and using wrap tab
 585:    * layout.
 586:    */
 587:   public JTabbedPane()
 588:   {
 589:     this(SwingConstants.TOP, WRAP_TAB_LAYOUT);
 590:   }
 591: 
 592:   /**
 593:    * Creates a new JTabbedPane object using wrap tab layout  and the given
 594:    * tabPlacement.
 595:    *
 596:    * @param tabPlacement Where the tabs will be placed.
 597:    */
 598:   public JTabbedPane(int tabPlacement)
 599:   {
 600:     this(tabPlacement, WRAP_TAB_LAYOUT);
 601:   }
 602: 
 603:   /**
 604:    * Creates a new JTabbedPane object with the given tabPlacement and
 605:    * tabLayoutPolicy.
 606:    *
 607:    * @param tabPlacement Where the tabs will be placed.
 608:    * @param tabLayoutPolicy The way tabs will be placed.
 609:    *
 610:    * @throws IllegalArgumentException If tabLayoutPolicy or tabPlacement are
 611:    *         not valid.
 612:    */
 613:   public JTabbedPane(int tabPlacement, int tabLayoutPolicy)
 614:   {
 615:     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
 616:         && tabPlacement != LEFT)
 617:       throw new IllegalArgumentException("tabPlacement is not valid.");
 618:     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
 619:         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
 620:       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
 621:     this.tabPlacement = tabPlacement;
 622:     layoutPolicy = tabLayoutPolicy;
 623: 
 624:     changeEvent = new ChangeEvent(this);
 625:     changeListener = createChangeListener();
 626: 
 627:     model = new DefaultSingleSelectionModel();
 628:     model.addChangeListener(changeListener);
 629: 
 630:     updateUI();
 631:   }
 632: 
 633:   /**
 634:    * This method returns the UI used to display the JTabbedPane.
 635:    *
 636:    * @return The UI used to display the JTabbedPane.
 637:    */
 638:   public TabbedPaneUI getUI()
 639:   {
 640:     return (TabbedPaneUI) ui;
 641:   }
 642: 
 643:   /**
 644:    * This method sets the UI used to display the JTabbedPane.
 645:    *
 646:    * @param ui The UI used to display the JTabbedPane.
 647:    */
 648:   public void setUI(TabbedPaneUI ui)
 649:   {
 650:     super.setUI(ui);
 651:   }
 652: 
 653:   /**
 654:    * This method restores the UI to the defaults given by the UIManager.
 655:    */
 656:   public void updateUI()
 657:   {
 658:     setUI((TabbedPaneUI) UIManager.getUI(this));
 659:     invalidate();
 660:   }
 661: 
 662:   /**
 663:    * This method returns a string identifier that  is used to determine which
 664:    * UI will be used with  the JTabbedPane.
 665:    *
 666:    * @return A string identifier for the UI.
 667:    */
 668:   public String getUIClassID()
 669:   {
 670:     return "TabbedPaneUI";
 671:   }
 672: 
 673:   /**
 674:    * This method creates a ChangeListener that is used to  listen to the model
 675:    * for events.
 676:    *
 677:    * @return A ChangeListener to listen to the model.
 678:    */
 679:   protected ChangeListener createChangeListener()
 680:   {
 681:     return new ModelListener();
 682:   }
 683: 
 684:   /**
 685:    * This method adds a ChangeListener to the JTabbedPane.
 686:    *
 687:    * @param l The ChangeListener to add.
 688:    */
 689:   public void addChangeListener(ChangeListener l)
 690:   {
 691:     listenerList.add(ChangeListener.class, l);
 692:   }
 693: 
 694:   /**
 695:    * This method removes a ChangeListener to the JTabbedPane.
 696:    *
 697:    * @param l The ChangeListener to remove.
 698:    */
 699:   public void removeChangeListener(ChangeListener l)
 700:   {
 701:     listenerList.remove(ChangeListener.class, l);
 702:   }
 703: 
 704:   /**
 705:    * This method fires a ChangeEvent to all the JTabbedPane's ChangeListeners.
 706:    */
 707:   protected void fireStateChanged()
 708:   {
 709:     Object[] changeListeners = listenerList.getListenerList();
 710:     if (changeEvent == null)
 711:       changeEvent = new ChangeEvent(this);
 712:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 713:       {
 714:     if (changeListeners[i] == ChangeListener.class)
 715:       ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 716:       }
 717:   }
 718: 
 719:   /**
 720:    * This method returns all ChangeListeners registered with the JTabbedPane.
 721:    *
 722:    * @return The ChangeListeners registered with the JTabbedPane.
 723:    */
 724:   public ChangeListener[] getChangeListeners()
 725:   {
 726:     return (ChangeListener[]) super.getListeners(ChangeListener.class);
 727:   }
 728: 
 729:   /**
 730:    * This method returns the model used with the JTabbedPane.
 731:    *
 732:    * @return The JTabbedPane's model.
 733:    */
 734:   public SingleSelectionModel getModel()
 735:   {
 736:     return model;
 737:   }
 738: 
 739:   /**
 740:    * This method changes the model property of the JTabbedPane.
 741:    *
 742:    * @param model The new model to use with the JTabbedPane.
 743:    */
 744:   public void setModel(SingleSelectionModel model)
 745:   {
 746:     if (model != this.model)
 747:       {
 748:     SingleSelectionModel oldModel = this.model;
 749:     this.model.removeChangeListener(changeListener);
 750:     this.model = model;
 751:     this.model.addChangeListener(changeListener);
 752:     firePropertyChange("model", oldModel, this.model);
 753:       }
 754:   }
 755: 
 756:   /**
 757:    * This method returns the tabPlacement.
 758:    *
 759:    * @return The tabPlacement used with the JTabbedPane.
 760:    */
 761:   public int getTabPlacement()
 762:   {
 763:     return tabPlacement;
 764:   }
 765: 
 766:   /**
 767:    * This method changes the tabPlacement property of the JTabbedPane.
 768:    *
 769:    * @param tabPlacement The tabPlacement to use.
 770:    *
 771:    * @throws IllegalArgumentException If tabPlacement is not one of TOP,
 772:    *         BOTTOM, LEFT, or RIGHT.
 773:    */
 774:   public void setTabPlacement(int tabPlacement)
 775:   {
 776:     if (tabPlacement != TOP && tabPlacement != BOTTOM && tabPlacement != RIGHT
 777:         && tabPlacement != LEFT)
 778:       throw new IllegalArgumentException("tabPlacement is not valid.");
 779:     if (tabPlacement != this.tabPlacement)
 780:       {
 781:     int oldPlacement = this.tabPlacement;
 782:     this.tabPlacement = tabPlacement;
 783:     firePropertyChange("tabPlacement", oldPlacement, this.tabPlacement);
 784:       }
 785:   }
 786: 
 787:   /**
 788:    * This method returns the tabLayoutPolicy.
 789:    *
 790:    * @return The tabLayoutPolicy.
 791:    */
 792:   public int getTabLayoutPolicy()
 793:   {
 794:     return layoutPolicy;
 795:   }
 796: 
 797:   /**
 798:    * This method changes the tabLayoutPolicy property of the JTabbedPane.
 799:    *
 800:    * @param tabLayoutPolicy The tabLayoutPolicy to use.
 801:    *
 802:    * @throws IllegalArgumentException If tabLayoutPolicy is not one of
 803:    *         SCROLL_TAB_LAYOUT or WRAP_TAB_LAYOUT.
 804:    */
 805:   public void setTabLayoutPolicy(int tabLayoutPolicy)
 806:   {
 807:     if (tabLayoutPolicy != SCROLL_TAB_LAYOUT
 808:         && tabLayoutPolicy != WRAP_TAB_LAYOUT)
 809:       throw new IllegalArgumentException("tabLayoutPolicy is not valid.");
 810:     if (tabLayoutPolicy != layoutPolicy)
 811:       {
 812:     int oldPolicy = layoutPolicy;
 813:     layoutPolicy = tabLayoutPolicy;
 814:     firePropertyChange("tabLayoutPolicy", oldPolicy, layoutPolicy);
 815:       }
 816:   }
 817: 
 818:   /**
 819:    * This method returns the index of the tab that is currently selected.
 820:    *
 821:    * @return The index of the selected tab.
 822:    */
 823:   public int getSelectedIndex()
 824:   {
 825:     return model.getSelectedIndex();
 826:   }
 827: 
 828:   /**
 829:    * This method checks the index.
 830:    *
 831:    * @param index The index to check.
 832:    * @param start DOCUMENT ME!
 833:    * @param end DOCUMENT ME!
 834:    *
 835:    * @throws IndexOutOfBoundsException DOCUMENT ME!
 836:    */
 837:   private void checkIndex(int index, int start, int end)
 838:   {
 839:     if (index < start || index >= end)
 840:       throw new IndexOutOfBoundsException("Index < " + start + " || Index >= "
 841:                                           + end);
 842:   }
 843: 
 844:   /**
 845:    * This method sets the selected index. This method will hide the old
 846:    * component and show the new component.
 847:    *
 848:    * @param index The index to set it at.
 849:    */
 850:   public void setSelectedIndex(int index)
 851:   {
 852:     checkIndex(index, -1, tabs.size());
 853:     if (index != getSelectedIndex())
 854:       {
 855:     if (getSelectedIndex() != -1 && getSelectedComponent() != null)
 856:       getSelectedComponent().hide();
 857:     if (index != -1 && getComponentAt(index) != null)
 858:       getComponentAt(index).show();
 859:     model.setSelectedIndex(index);
 860:       }
 861:   }
 862: 
 863:   /**
 864:    * This method returns the component at the selected index.
 865:    *
 866:    * @return The component at the selected index.
 867:    */
 868:   public Component getSelectedComponent()
 869:   {
 870:     return getComponentAt(getSelectedIndex());
 871:   }
 872: 
 873:   /**
 874:    * This method sets the component at the selected index.
 875:    *
 876:    * @param c The component associated with the selected index.
 877:    */
 878:   public void setSelectedComponent(Component c)
 879:   {
 880:     if (c.getParent() == this)
 881:       setSelectedIndex(indexOfComponent(c));
 882:     else
 883:       setComponentAt(getSelectedIndex(), c);
 884:   }
 885: 
 886:   /**
 887:    * This method inserts tabs into JTabbedPane. This includes adding the
 888:    * component to the JTabbedPane and hiding it.
 889:    *
 890:    * @param title the title of the tab; may be <code>null</code>
 891:    * @param icon the tab's icon; may be <code>null</code>
 892:    * @param component the component associated with the tab
 893:    * @param tip the tooltip for the tab
 894:    * @param index the index to insert the tab at
 895:    */
 896:   public void insertTab(String title, Icon icon, Component component,
 897:                         String tip, int index)
 898:   {
 899:     if (title == null)
 900:       title = "";
 901:     Page p = new Page(title, icon, component, tip);
 902:     tabs.insertElementAt(p, index);
 903: 
 904:     // Hide the component so we don't see it. Do it before we parent it
 905:     // so we don't trigger a repaint.
 906:     if (component != null)
 907:       {
 908:     component.hide();
 909:     super.add(component);
 910:       }
 911: 
 912:     if (getSelectedIndex() == -1)
 913:       setSelectedIndex(0);
 914: 
 915:     layout();
 916:     repaint();
 917:   }
 918: 
 919:   /**
 920:    * This method adds a tab to the JTabbedPane.
 921:    *
 922:    * @param title the title of the tab; may be <code>null</code>
 923:    * @param icon the icon for the tab; may be <code>null</code>
 924:    * @param component the associated component
 925:    * @param tip the associated tooltip
 926:    */
 927:   public void addTab(String title, Icon icon, Component component, String tip)
 928:   {
 929:     insertTab(title, icon, component, tip, tabs.size());
 930:   }
 931: 
 932:   /**
 933:    * This method adds a tab to the JTabbedPane.
 934:    *
 935:    * @param title the title of the tab; may be <code>null</code>
 936:    * @param icon the icon for the tab; may be <code>null</code>
 937:    * @param component the associated component
 938:    */
 939:   public void addTab(String title, Icon icon, Component component)
 940:   {
 941:     insertTab(title, icon, component, null, tabs.size());
 942:   }
 943: 
 944:   /**
 945:    * This method adds a tab to the JTabbedPane.
 946:    *
 947:    * @param title the title of the tab; may be <code>null</code>
 948:    * @param component the associated component
 949:    */
 950:   public void addTab(String title, Component component)
 951:   {
 952:     insertTab(title, null, component, null, tabs.size());
 953:   }
 954: 
 955:   /**
 956:    * This method adds a tab to the JTabbedPane. The title of the tab is the
 957:    * Component's name. If the Component is an instance of UIResource, it
 958:    * doesn't add the tab and instead add the component directly to the
 959:    * JTabbedPane.
 960:    *
 961:    * @param component The associated component.
 962:    *
 963:    * @return The Component that was added.
 964:    */
 965:   public Component add(Component component)
 966:   {
 967:     if (component instanceof UIResource)
 968:       super.add(component);
 969:     else
 970:       insertTab(component.getName(), null, component, null, tabs.size());
 971:     return component;
 972:   }
 973: 
 974:   /**
 975:    * This method adds a tab to the JTabbedPane. If the Component is an
 976:    * instance of UIResource, it doesn't add the tab and instead add the
 977:    * component directly to the JTabbedPane.
 978:    *
 979:    * @param title the title of the tab; may be <code>null</code>
 980:    * @param component the associated component
 981:    *
 982:    * @return The Component that was added.
 983:    */
 984:   public Component add(String title, Component component)
 985:   {
 986:     if (component instanceof UIResource)
 987:       super.add(component);
 988:     else
 989:       insertTab(title, null, component, null, tabs.size());
 990:     return component;
 991:   }
 992: 
 993:   /**
 994:    * This method adds a tab to the JTabbedPane. If the Component is an
 995:    * instance of UIResource, it doesn't add the tab and instead add the
 996:    * component directly to the JTabbedPane.
 997:    *
 998:    * @param component The associated component.
 999:    * @param index The index to insert the tab at.
1000:    *
1001:    * @return The Component that was added.
1002:    */
1003:   public Component add(Component component, int index)
1004:   {
1005:     if (component instanceof UIResource)
1006:       super.add(component);
1007:     else
1008:       insertTab(component.getName(), null, component, null, index);
1009:     return component;
1010:   }
1011: 
1012:   /**
1013:    * This method adds a tab to the JTabbedPane. If the Component is an
1014:    * instance of UIResource, it doesn't add the tab and instead add the
1015:    * component directly to the JTabbedPane. If the constraints object is an
1016:    * icon, it will be used as the tab's icon. If the constraints object is a
1017:    * string, we will use it as the title.
1018:    *
1019:    * @param component The associated component.
1020:    * @param constraints The constraints object.
1021:    */
1022:   public void add(Component component, Object constraints)
1023:   {
1024:     add(component, constraints, tabs.size());
1025:   }
1026: 
1027:   /**
1028:    * This method adds a tab to the JTabbedPane. If the Component is an
1029:    * instance of UIResource, it doesn't add the tab and instead add the
1030:    * component directly to the JTabbedPane. If the constraints object is an
1031:    * icon, it will be used as the tab's icon. If the constraints object is a
1032:    * string, we will use it as the title.
1033:    *
1034:    * @param component The associated component.
1035:    * @param constraints The constraints object.
1036:    * @param index The index to insert the tab at.
1037:    */
1038:   public void add(Component component, Object constraints, int index)
1039:   {
1040:     if (component instanceof UIResource)
1041:       super.add(component);
1042:     else
1043:       {
1044:     if (constraints instanceof String)
1045:       insertTab((String) constraints, null, component, null, index);
1046:     else
1047:       insertTab(component.getName(),
1048:                 (constraints instanceof Icon) ? (Icon) constraints : null,
1049:                 component, null, index);
1050:       }
1051:   }
1052: 
1053:   /**
1054:    * The tab and it's associated component are removed. After the component
1055:    * has been removed from the JTabbedPane, it's set visible to ensure that
1056:    * it can be seen.
1057:    *
1058:    * @param index The index of the tab to remove.
1059:    */
1060:   public void removeTabAt(int index)
1061:   {
1062:     checkIndex(index, 0, tabs.size());
1063:     Component c = getComponentAt(index);
1064:     super.remove(index);
1065:     c.show();
1066:     tabs.remove(index);
1067:   }
1068: 
1069:   /**
1070:    * This method removes the component from the JTabbedPane. After the
1071:    * component has been removed from the JTabbedPane, it's  set visible to
1072:    * ensure that it can be seen.
1073:    *
1074:    * @param component The Component to remove.
1075:    */
1076:   public void remove(Component component)
1077:   {
1078:     // This simply removes the component.
1079:     int index = indexOfComponent(component);
1080:     super.remove(component);
1081:     component.show();
1082:     setComponentAt(index, null);
1083:   }
1084: 
1085:   /**
1086:    * This method removes the tab and component from the JTabbedPane. It simply
1087:    * calls removeTabAt(int index).
1088:    *
1089:    * @param index The index of the tab to remove.
1090:    */
1091:   public void remove(int index)
1092:   {
1093:     removeTabAt(index);
1094:   }
1095: 
1096:   /**
1097:    * This method removes all tabs and associated components from the
1098:    * JTabbedPane.
1099:    */
1100:   public void removeAll()
1101:   {
1102:     for (int i = tabs.size() - 1; i >= 0; i--)
1103:       removeTabAt(i);
1104:   }
1105: 
1106:   /**
1107:    * This method returns how many tabs are in the JTabbedPane.
1108:    *
1109:    * @return The number of tabs in the JTabbedPane.
1110:    */
1111:   public int getTabCount()
1112:   {
1113:     return tabs.size();
1114:   }
1115: 
1116:   /**
1117:    * This method returns the number of runs used  to paint the JTabbedPane.
1118:    *
1119:    * @return The number of runs.
1120:    */
1121:   public int getTabRunCount()
1122:   {
1123:     return ((TabbedPaneUI) ui).getTabRunCount(this);
1124:   }
1125: 
1126:   /**
1127:    * This method returns the tab title given the index.
1128:    *
1129:    * @param index The index of the tab.
1130:    *
1131:    * @return The title for the tab.
1132:    */
1133:   public String getTitleAt(int index)
1134:   {
1135:     checkIndex(index, 0, tabs.size());
1136:     return ((Page) tabs.elementAt(index)).getTitle();
1137:   }
1138: 
1139:   /**
1140:    * This method returns the active icon given the index.
1141:    *
1142:    * @param index The index of the tab.
1143:    *
1144:    * @return The active icon for the tab.
1145:    */
1146:   public Icon getIconAt(int index)
1147:   {
1148:     checkIndex(index, 0, tabs.size());
1149:     return ((Page) tabs.elementAt(index)).getIcon();
1150:   }
1151: 
1152:   /**
1153:    * This method returns the disabled icon given the index.
1154:    *
1155:    * @param index The index of the tab.
1156:    *
1157:    * @return The disabled icon for the tab.
1158:    */
1159:   public Icon getDisabledIconAt(int index)
1160:   {
1161:     checkIndex(index, 0, tabs.size());
1162:     return ((Page) tabs.elementAt(index)).getDisabledIcon();
1163:   }
1164: 
1165:   /**
1166:    * This method returns the tooltip string for the tab.
1167:    *
1168:    * @param index The index of the tab.
1169:    *
1170:    * @return The tooltip string for the tab.
1171:    */
1172:   public String getToolTipTextAt(int index)
1173:   {
1174:     checkIndex(index, 0, tabs.size());
1175:     return ((Page) tabs.elementAt(index)).getTip();
1176:   }
1177: 
1178:   /**
1179:    * This method returns the foreground color for the tab.
1180:    *
1181:    * @param index The index of the tab.
1182:    *
1183:    * @return The foreground color for the tab.
1184:    */
1185:   public Color getForegroundAt(int index)
1186:   {
1187:     checkIndex(index, 0, tabs.size());
1188:     return ((Page) tabs.elementAt(index)).getForeground();
1189:   }
1190: 
1191:   /**
1192:    * This method returns the background color for the tab.
1193:    *
1194:    * @param index The index of the tab.
1195:    *
1196:    * @return The background color for the tab.
1197:    */
1198:   public Color getBackgroundAt(int index)
1199:   {
1200:     checkIndex(index, 0, tabs.size());
1201:     return ((Page) tabs.elementAt(index)).getBackground();
1202:   }
1203: 
1204:   /**
1205:    * This method returns the component associated with the tab.
1206:    *
1207:    * @param index The index of the tab.
1208:    *
1209:    * @return The component associated with the tab.
1210:    */
1211:   public Component getComponentAt(int index)
1212:   {
1213:     checkIndex(index, 0, tabs.size());
1214:     return ((Page) tabs.elementAt(index)).getComponent();
1215:   }
1216: 
1217:   /**
1218:    * This method returns whether this tab is enabled. Disabled tabs cannot be
1219:    * selected.
1220:    *
1221:    * @param index The index of the tab.
1222:    *
1223:    * @return Whether the tab is enabled.
1224:    */
1225:   public boolean isEnabledAt(int index)
1226:   {
1227:     checkIndex(index, 0, tabs.size());
1228:     return ((Page) tabs.elementAt(index)).isEnabled();
1229:   }
1230: 
1231:   /**
1232:    * This method returns the mnemonic for the tab.
1233:    *
1234:    * @param tabIndex The index of the tab.
1235:    *
1236:    * @return The mnemonic for the tab.
1237:    */
1238:   public int getMnemonicAt(int tabIndex)
1239:   {
1240:     checkIndex(tabIndex, 0, tabs.size());
1241:     return ((Page) tabs.elementAt(tabIndex)).getMnemonic();
1242:   }
1243: 
1244:   /**
1245:    * This method returns the mnemonic index for the tab.
1246:    *
1247:    * @param tabIndex The index of the tab.
1248:    *
1249:    * @return The mnemonic index for the tab.
1250:    */
1251:   public int getDisplayedMnemonicIndexAt(int tabIndex)
1252:   {
1253:     checkIndex(tabIndex, 0, tabs.size());
1254:     return ((Page) tabs.elementAt(tabIndex)).getDisplayedMnemonicIndex();
1255:   }
1256: 
1257:   /**
1258:    * This method returns the bounds of the tab given the index.
1259:    *
1260:    * @param index The index of the tab.
1261:    *
1262:    * @return A rectangle describing the bounds of the tab.
1263:    */
1264:   public Rectangle getBoundsAt(int index)
1265:   {
1266:     checkIndex(index, 0, tabs.size());
1267:     return ((TabbedPaneUI) ui).getTabBounds(this, index);
1268:   }
1269: 
1270:   /**
1271:    * This method sets the title of the tab.
1272:    *
1273:    * @param index The index of the tab.
1274:    * @param title The new title.
1275:    */
1276:   public void setTitleAt(int index, String title)
1277:   {
1278:     checkIndex(index, 0, tabs.size());
1279:     ((Page) tabs.elementAt(index)).setTitle(title);
1280:   }
1281: 
1282:   /**
1283:    * This method sets the icon of the tab.
1284:    *
1285:    * @param index The index of the tab.
1286:    * @param icon The new icon.
1287:    */
1288:   public void setIconAt(int index, Icon icon)
1289:   {
1290:     checkIndex(index, 0, tabs.size());
1291:     ((Page) tabs.elementAt(index)).setIcon(icon);
1292:   }
1293: 
1294:   /**
1295:    * This method sets the disabled icon of the tab.
1296:    *
1297:    * @param index The index of the tab.
1298:    * @param disabledIcon The new disabled icon.
1299:    */
1300:   public void setDisabledIconAt(int index, Icon disabledIcon)
1301:   {
1302:     checkIndex(index, 0, tabs.size());
1303:     ((Page) tabs.elementAt(index)).setDisabledIcon(disabledIcon);
1304:   }
1305: 
1306:   /**
1307:    * This method sets the tooltip text of the tab.
1308:    *
1309:    * @param index The index of the tab.
1310:    * @param toolTipText The tooltip text.
1311:    */
1312:   public void setToolTipTextAt(int index, String toolTipText)
1313:   {
1314:     checkIndex(index, 0, tabs.size());
1315:     ((Page) tabs.elementAt(index)).setTip(toolTipText);
1316:   }
1317: 
1318:   /**
1319:    * This method sets the background color of the tab.
1320:    *
1321:    * @param index The index of the tab.
1322:    * @param background The background color of the tab.
1323:    */
1324:   public void setBackgroundAt(int index, Color background)
1325:   {
1326:     checkIndex(index, 0, tabs.size());
1327:     ((Page) tabs.elementAt(index)).setBackground(background);
1328:   }
1329: 
1330:   /**
1331:    * This method sets the foreground color of the tab.
1332:    *
1333:    * @param index The index of the tab.
1334:    * @param foreground The foreground color of the tab.
1335:    */
1336:   public void setForegroundAt(int index, Color foreground)
1337:   {
1338:     checkIndex(index, 0, tabs.size());
1339:     ((Page) tabs.elementAt(index)).setForeground(foreground);
1340:   }
1341: 
1342:   /**
1343:    * This method sets whether the tab is enabled.
1344:    *
1345:    * @param index The index of the tab.
1346:    * @param enabled Whether the tab is enabled.
1347:    */
1348:   public void setEnabledAt(int index, boolean enabled)
1349:   {
1350:     checkIndex(index, 0, tabs.size());
1351:     ((Page) tabs.elementAt(index)).setEnabled(enabled);
1352:   }
1353: 
1354:   /**
1355:    * This method sets the component associated with the tab.
1356:    *
1357:    * @param index The index of the tab.
1358:    * @param component The component associated with the tab.
1359:    */
1360:   public void setComponentAt(int index, Component component)
1361:   {
1362:     checkIndex(index, 0, tabs.size());
1363:     ((Page) tabs.elementAt(index)).setComponent(component);
1364:   }
1365: 
1366:   /**
1367:    * This method sets the displayed mnemonic index of the tab.
1368:    *
1369:    * @param tabIndex The index of the tab.
1370:    * @param mnemonicIndex The mnemonic index.
1371:    */
1372:   public void setDisplayedMnemonicIndexAt(int tabIndex, int mnemonicIndex)
1373:   {
1374:     checkIndex(tabIndex, 0, tabs.size());
1375:     ((Page) tabs.elementAt(tabIndex)).setDisplayedMnemonicIndex(mnemonicIndex);
1376:   }
1377: 
1378:   /**
1379:    * This method sets the mnemonic for the tab.
1380:    *
1381:    * @param tabIndex The index of the tab.
1382:    * @param mnemonic The mnemonic.
1383:    */
1384:   public void setMnemonicAt(int tabIndex, int mnemonic)
1385:   {
1386:     checkIndex(tabIndex, 0, tabs.size());
1387:     ((Page) tabs.elementAt(tabIndex)).setMnemonic(mnemonic);
1388:   }
1389: 
1390:   /**
1391:    * This method finds the index of a tab given the title.
1392:    *
1393:    * @param title The title that belongs to a tab.
1394:    *
1395:    * @return The index of the tab that has the title or -1 if not found.
1396:    */
1397:   public int indexOfTab(String title)
1398:   {
1399:     int index = -1;
1400:     for (int i = 0; i < tabs.size(); i++)
1401:       {
1402:     if (((Page) tabs.elementAt(i)).getTitle().equals(title))
1403:       {
1404:         index = i;
1405:         break;
1406:       }
1407:       }
1408:     return index;
1409:   }
1410: 
1411:   /**
1412:    * This method finds the index of a tab given the icon.
1413:    *
1414:    * @param icon The icon that belongs to a tab.
1415:    *
1416:    * @return The index of the tab that has the icon or -1 if not found.
1417:    */
1418:   public int indexOfTab(Icon icon)
1419:   {
1420:     int index = -1;
1421:     for (int i = 0; i < tabs.size(); i++)
1422:       {
1423:     if (((Page) tabs.elementAt(i)).getIcon() == icon)
1424:       {
1425:         index = i;
1426:         break;
1427:       }
1428:       }
1429:     return index;
1430:   }
1431: 
1432:   /**
1433:    * This method finds the index of a tab given the component.
1434:    *
1435:    * @param component A component associated with a tab.
1436:    *
1437:    * @return The index of the tab that has this component or -1 if not found.
1438:    */
1439:   public int indexOfComponent(Component component)
1440:   {
1441:     int index = -1;
1442:     for (int i = 0; i < tabs.size(); i++)
1443:       {
1444:     if (((Page) tabs.elementAt(i)).getComponent() == component)
1445:       {
1446:         index = i;
1447:         break;
1448:       }
1449:       }
1450:     return index;
1451:   }
1452: 
1453:   /**
1454:    * This method returns a tab index given an (x,y) location. The origin of
1455:    * the (x,y) pair will be the JTabbedPane's top left position. The  tab
1456:    * returned will be the one that contains the point. This method is
1457:    * delegated to the UI.
1458:    *
1459:    * @param x The x coordinate of the point.
1460:    * @param y The y coordinate of the point.
1461:    *
1462:    * @return The index of the tab that contains the point.
1463:    */
1464:   public int indexAtLocation(int x, int y)
1465:   {
1466:     return ((TabbedPaneUI) ui).tabForCoordinate(this, x, y);
1467:   }
1468: 
1469:   /**
1470:    * This method returns the tooltip text given a mouse event.
1471:    *
1472:    * @param event The mouse event.
1473:    *
1474:    * @return The tool tip text that is associated with this mouse event.
1475:    */
1476:   public String getToolTipText(MouseEvent event)
1477:   {
1478:     int index = indexAtLocation(event.getX(), event.getY());
1479:     return ((Page) tabs.elementAt(index)).getTip();
1480:   }
1481: 
1482:   /**
1483:    * This method returns a string representation of this JTabbedPane. It is
1484:    * mainly used for debugging purposes.
1485:    *
1486:    * @return A string representation of this JTabbedPane.
1487:    */
1488:   protected String paramString()
1489:   {
1490:     return "JTabbedPane";
1491:   }
1492: 
1493:   /**
1494:    * DOCUMENT ME!
1495:    *
1496:    * @return DOCUMENT ME!
1497:    */
1498:   public AccessibleContext getAccessibleContext()
1499:   {
1500:     if (accessibleContext == null)
1501:       accessibleContext = new AccessibleJTabbedPane();
1502:     return accessibleContext;
1503:   }
1504: }