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