1. /*
  2. * %W% %E%
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing;
  11. import java.awt.*;
  12. import java.awt.event.*;
  13. import java.beans.*;
  14. import java.util.*;
  15. import javax.swing.event.*;
  16. import javax.swing.plaf.*;
  17. import javax.accessibility.*;
  18. import java.io.Serializable;
  19. import java.io.ObjectOutputStream;
  20. import java.io.ObjectInputStream;
  21. import java.io.IOException;
  22. /**
  23. * A component that lets the user switch between a group of components by
  24. * clicking on a tab with a given title and/or icon.
  25. * For examples and information on using tabbed panes see
  26. * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/tabbedpane.html">How to Use Tabbed Panes</a>,
  27. * a section in <em>The Java Tutorial</em>.
  28. * <p>
  29. * Tabs/components are added to a <code>TabbedPane</code> object by using the
  30. * addTab and
  31. * insertTab methods. A tab is represented by an index corresponding
  32. * to the position it was added in, where the first tab has an index equal to 0
  33. * and the last tab has an index equal to the tab count minus 1.
  34. * <p>
  35. * The <code>TabbedPane</code> uses a <code>SingleSelectionModel</code>
  36. * to represent the set
  37. * of tab indices and the currently selected index. If the tab count
  38. * is greater than 0, then there will always be a selected index, which
  39. * by default will be initialized to the first tab. If the tab count is
  40. * 0, then the selected index will be -1.
  41. * <p>
  42. * For the keyboard keys used by this component in the standard Look and
  43. * Feel (L&F) renditions, see the
  44. * <a href="doc-files/Key-Index.html#JTabbedPane">JTabbedPane</a> key assignments.
  45. * <p>
  46. * <strong>Warning:</strong>
  47. * Serialized objects of this class will not be compatible with
  48. * future Swing releases. The current serialization support is appropriate
  49. * for short term storage or RMI between applications running the same
  50. * version of Swing. A future release of Swing will provide support for
  51. * long term persistence.
  52. *
  53. * @beaninfo
  54. * attribute: isContainer true
  55. * description: A component which provides a tab folder metaphor for
  56. * displaying one component from a set of components.
  57. *
  58. * @version %I% %G%
  59. * @author Dave Moore
  60. * @author Philip Milne
  61. * @author Amy Fowler
  62. *
  63. * @see SingleSelectionModel
  64. */
  65. public class JTabbedPane extends JComponent
  66. implements Serializable, Accessible, SwingConstants {
  67. /**
  68. * @see #getUIClassID
  69. * @see #readObject
  70. */
  71. private static final String uiClassID = "TabbedPaneUI";
  72. /**
  73. * Where the tabs are placed.
  74. * @see #setTabPlacement
  75. */
  76. protected int tabPlacement = TOP;
  77. /** The default selection model */
  78. protected SingleSelectionModel model;
  79. private boolean haveRegistered;
  80. /**
  81. * The changeListener is the listener we add to the
  82. * model.
  83. */
  84. protected ChangeListener changeListener = null;
  85. Vector pages;
  86. /**
  87. * Only one <code>ChangeEvent</code> is needed per <code>TabPane</code>
  88. * instance since the
  89. * event's only (read-only) state is the source property. The source
  90. * of events generated here is always "this".
  91. */
  92. protected transient ChangeEvent changeEvent = null;
  93. /**
  94. * Creates an empty <code>TabbedPane</code>. The default
  95. * tab placement is TOP.
  96. * @see #addTab
  97. */
  98. public JTabbedPane() {
  99. this(TOP);
  100. }
  101. /**
  102. * Creates an empty <code>TabbedPane</code> with the specified tab placement
  103. * of either: TOP, BOTTOM, LEFT, or RIGHT.
  104. * @param tabPlacement the placement for the tabs relative to the content
  105. * @see #addTab
  106. */
  107. public JTabbedPane(int tabPlacement) {
  108. setTabPlacement(tabPlacement);
  109. pages = new Vector(1);
  110. setModel(new DefaultSingleSelectionModel());
  111. updateUI();
  112. }
  113. /**
  114. * Returns the UI object which implements the L&F for this component.
  115. * @see #setUI
  116. */
  117. public TabbedPaneUI getUI() {
  118. return (TabbedPaneUI)ui;
  119. }
  120. /**
  121. * Sets the UI object which implements the L&F for this component.
  122. * @param ui the new UI object
  123. * @see UIDefaults#getUI
  124. * @beaninfo
  125. * bound: true
  126. * hidden: true
  127. * attribute: visualUpdate true
  128. * description: The UI object that implements the tabbedpane's LookAndFeel
  129. */
  130. public void setUI(TabbedPaneUI ui) {
  131. super.setUI(ui);
  132. }
  133. /**
  134. * Notification from the <code>UIManager</code> that the L&F has changed.
  135. * Called to replace the UI with the latest version from the
  136. * default <code>UIFactory</code>.
  137. *
  138. * @see JComponent#updateUI
  139. */
  140. public void updateUI() {
  141. setUI((TabbedPaneUI)UIManager.getUI(this));
  142. }
  143. /**
  144. * Returns the name of the UI class that implements the
  145. * L&F for this component.
  146. *
  147. * @return the string "TabbedPaneUI"
  148. * @see JComponent#getUIClassID
  149. * @see UIDefaults#getUI
  150. */
  151. public String getUIClassID() {
  152. return uiClassID;
  153. }
  154. /**
  155. * We pass <code>ModelChanged</code> events along to the listeners with
  156. * the tabbedpane (instead of the model itself) as the event source.
  157. */
  158. protected class ModelListener implements ChangeListener, Serializable {
  159. public void stateChanged(ChangeEvent e) {
  160. fireStateChanged();
  161. }
  162. }
  163. /**
  164. * Subclasses that want to handle <code>ChangeEvents</code> differently
  165. * can override this to return a subclass of <code>ModelListener</code> or
  166. * another <code>ChangeListener</code> implementation.
  167. *
  168. * @see #fireStateChanged
  169. */
  170. protected ChangeListener createChangeListener() {
  171. return new ModelListener();
  172. }
  173. /**
  174. * Adds a <code>ChangeListener</code> to this tabbedpane.
  175. *
  176. * @param l the <code>ChangeListener</code> to add
  177. * @see #fireStateChanged
  178. * @see #removeChangeListener
  179. */
  180. public void addChangeListener(ChangeListener l) {
  181. listenerList.add(ChangeListener.class, l);
  182. }
  183. /**
  184. * Removes a <code>ChangeListener</code> from this tabbedpane.
  185. *
  186. * @param l the ChangeListener to remove
  187. * @see #fireStateChanged
  188. * @see #addChangeListener
  189. */
  190. public void removeChangeListener(ChangeListener l) {
  191. listenerList.remove(ChangeListener.class, l);
  192. }
  193. /**
  194. * Send a <code>ChangeEvent</code>, whose source is this tabbedpane, to
  195. * each listener. This method method is called each time
  196. * a <code>ChangeEvent</code> is received from the model.
  197. *
  198. * @see #addChangeListener
  199. * @see EventListenerList
  200. */
  201. protected void fireStateChanged() {
  202. // Guaranteed to return a non-null array
  203. Object[] listeners = listenerList.getListenerList();
  204. // Process the listeners last to first, notifying
  205. // those that are interested in this event
  206. for (int i = listeners.length-2; i>=0; i-=2) {
  207. if (listeners[i]==ChangeListener.class) {
  208. // Lazily create the event:
  209. if (changeEvent == null)
  210. changeEvent = new ChangeEvent(this);
  211. ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  212. }
  213. }
  214. }
  215. /**
  216. * Returns the model associated with this tabbedpane.
  217. *
  218. * @see #setModel
  219. */
  220. public SingleSelectionModel getModel() {
  221. return model;
  222. }
  223. /**
  224. * Sets the model to be used with this tabbedpane.
  225. * @param model the model to be used
  226. *
  227. * @see #getModel
  228. * @beaninfo
  229. * bound: true
  230. * description: The tabbedpane's SingleSelectionModel.
  231. */
  232. public void setModel(SingleSelectionModel model) {
  233. SingleSelectionModel oldModel = getModel();
  234. if (oldModel != null) {
  235. oldModel.removeChangeListener(changeListener);
  236. changeListener = null;
  237. }
  238. this.model = model;
  239. if (model != null) {
  240. changeListener = createChangeListener();
  241. model.addChangeListener(changeListener);
  242. }
  243. firePropertyChange("model", oldModel, model);
  244. repaint();
  245. }
  246. /**
  247. * Returns the placement of the tabs for this tabbedpane.
  248. * @see #setTabPlacement
  249. */
  250. public int getTabPlacement() {
  251. return tabPlacement;
  252. }
  253. /**
  254. * Sets the tab placement for this tabbedpane.
  255. * Possible values are:<ul>
  256. * <li>SwingConstants.TOP
  257. * <li>SwingConstants.BOTTOM
  258. * <li>SwingConstants.LEFT
  259. * <li>SwingConstants.RIGHT
  260. * </ul>
  261. * The default value, if not set, is <code>SwingConstants.TOP</code>.
  262. *
  263. * @param tabPlacement the placement for the tabs relative to the content
  264. * @exception IllegalArgumentException if tab placement value isn't one
  265. * of the above valid values
  266. *
  267. * @beaninfo
  268. * preferred: true
  269. * bound: true
  270. * attribute: visualUpdate true
  271. * enum: TOP JTabbedPane.TOP
  272. * LEFT JTabbedPane.LEFT
  273. * BOTTOM JTabbedPane.BOTTOM
  274. * RIGHT JTabbedPane.RIGHT
  275. * description: The tabbedpane's tab placement.
  276. *
  277. */
  278. public void setTabPlacement(int tabPlacement) {
  279. if (tabPlacement != TOP && tabPlacement != LEFT &&
  280. tabPlacement != BOTTOM && tabPlacement != RIGHT) {
  281. throw new IllegalArgumentException("illegal tab placement: must be TOP, BOTTOM, LEFT, or RIGHT");
  282. }
  283. if (this.tabPlacement != tabPlacement) {
  284. int oldValue = this.tabPlacement;
  285. this.tabPlacement = tabPlacement;
  286. firePropertyChange("tabPlacement", oldValue, tabPlacement);
  287. revalidate();
  288. repaint();
  289. }
  290. }
  291. /**
  292. * Returns the currently selected index for this tabbedpane.
  293. * Returns -1 if there is no currently selected tab.
  294. *
  295. * @return the index of the selected tab
  296. * @see #setSelectedIndex
  297. */
  298. public int getSelectedIndex() {
  299. return model.getSelectedIndex();
  300. }
  301. /**
  302. * Sets the selected index for this tabbedpane.
  303. *
  304. * @param index the index to be selected
  305. * @exception IllegalArgumentException if index is out of bounds
  306. *
  307. * @see #getSelectedIndex
  308. * @see SingleSelectionModel#setSelectedIndex
  309. * @beaninfo
  310. * preferred: true
  311. * description: The tabbedpane's selected tab index.
  312. */
  313. public void setSelectedIndex(int index) {
  314. int oldIndex = model.getSelectedIndex();
  315. model.setSelectedIndex(index);
  316. if ((oldIndex >= 0) && (oldIndex != index)) {
  317. Page oldPage = (Page) pages.elementAt(oldIndex);
  318. if (accessibleContext != null) {
  319. accessibleContext.firePropertyChange(
  320. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  321. AccessibleState.SELECTED, null);
  322. }
  323. }
  324. if ((index >= 0) && (oldIndex != index)) {
  325. Page newPage = (Page) pages.elementAt(index);
  326. if (accessibleContext != null) {
  327. accessibleContext.firePropertyChange(
  328. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  329. null, AccessibleState.SELECTED);
  330. }
  331. }
  332. }
  333. /**
  334. * Returns the currently selected component for this tabbedpane.
  335. * Returns <code>null</code> if there is no currently selected tab.
  336. *
  337. * @return the component corresponding to the selected tab
  338. * @see #setSelectedComponent
  339. */
  340. public Component getSelectedComponent() {
  341. int index = getSelectedIndex();
  342. if (index == -1) {
  343. return null;
  344. }
  345. return getComponentAt(index);
  346. }
  347. /**
  348. * Sets the selected component for this tabbedpane. This
  349. * will automatically set the <code>selectedIndex</code> to the index
  350. * corresponding to the specified component.
  351. *
  352. * @exception IllegalArgumentException if component not found in tabbed
  353. * pane
  354. * @see #getSelectedComponent
  355. * @beaninfo
  356. * preferred: true
  357. * description: The tabbedpane's selected component.
  358. */
  359. public void setSelectedComponent(Component c) {
  360. int index = indexOfComponent(c);
  361. if (index != -1) {
  362. setSelectedIndex(index);
  363. } else {
  364. throw new IllegalArgumentException("component not found in tabbed pane");
  365. }
  366. }
  367. /**
  368. * Inserts a <code>component</code>, at <code>index</code>,
  369. * represented by a
  370. * <code>title</code> and/or <code>icon</code>, either of which may be
  371. * <code>null</code>.
  372. * Uses java.util.Vector internally, see <code>insertElementAt</code>
  373. * for details of insertion conventions.
  374. *
  375. * @param title the title to be displayed in this tab
  376. * @param icon the icon to be displayed in this tab
  377. * @param component The component to be displayed when this tab is clicked.
  378. * @param tip the tooltip to be displayed for this tab
  379. * @param index the position to insert this new tab
  380. *
  381. * @see #addTab
  382. * @see #removeTabAt
  383. */
  384. public void insertTab(String title, Icon icon, Component component, String tip, int index) {
  385. Icon disabledIcon = null;
  386. if (icon != null && icon instanceof ImageIcon) {
  387. disabledIcon = new ImageIcon(
  388. GrayFilter.createDisabledImage(
  389. ((ImageIcon)icon).getImage()));
  390. }
  391. // If component already exists, remove corresponding
  392. // tab so that new tab gets added correctly
  393. // Note: we are allowing component=null because of compatibility,
  394. // but we really should throw an exception because much of the
  395. // rest of the JTabbedPane implementation isn't designed to deal
  396. // with null components for tabs.
  397. int i;
  398. if (component != null && (i = indexOfComponent(component)) != -1) {
  399. removeTabAt(i);
  400. }
  401. pages.insertElementAt(new Page(this, title != null? title : "", icon, disabledIcon,
  402. component, tip), index);
  403. if (component != null) {
  404. component.setVisible(false);
  405. addImpl(component, null, -1);
  406. }
  407. if (pages.size() == 1) {
  408. setSelectedIndex(0);
  409. }
  410. if (!haveRegistered && tip != null) {
  411. ToolTipManager.sharedInstance().registerComponent(this);
  412. haveRegistered = true;
  413. }
  414. if (accessibleContext != null) {
  415. accessibleContext.firePropertyChange(
  416. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  417. null, component);
  418. }
  419. revalidate();
  420. repaint();
  421. }
  422. /**
  423. * Adds a <code>component</code> and <code>tip</code>
  424. * represented by a <code>title</code>
  425. * and/or <code>icon</code>, either of which can be <code>null</code>.
  426. * Cover method for <code>insertTab</code>.
  427. *
  428. * @param title the title to be displayed in this tab
  429. * @param icon the icon to be displayed in this tab
  430. * @param component The component to be displayed when this tab is clicked.
  431. * @param tip the tooltip to be displayed for this tab
  432. *
  433. * @see #insertTab
  434. * @see #removeTabAt
  435. */
  436. public void addTab(String title, Icon icon, Component component, String tip) {
  437. insertTab(title, icon, component, tip, pages.size());
  438. }
  439. /**
  440. * Adds a <code>component</code> represented by a <code>title</code> and/or
  441. * <code>icon</code>,
  442. * either of which can be <code>null</code>.
  443. * Cover method for <code>insertTab</code>.
  444. *
  445. * @param title the title to be displayed in this tab
  446. * @param icon the icon to be displayed in this tab
  447. * @param component the component to be displayed when this tab is clicked
  448. *
  449. * @see #insertTab
  450. * @see #removeTabAt
  451. */
  452. public void addTab(String title, Icon icon, Component component) {
  453. insertTab(title, icon, component, null, pages.size());
  454. }
  455. /**
  456. * Adds a <code>component</code> represented by a <code>title</code>
  457. * and no icon.
  458. * Cover method for <code>insertTab</code>.
  459. *
  460. * @param title the title to be displayed in this tab
  461. * @param component The component to be displayed when this tab is clicked.
  462. *
  463. * @see #insertTab
  464. * @see #removeTabAt
  465. */
  466. public void addTab(String title, Component component) {
  467. insertTab(title, null, component, null, pages.size());
  468. }
  469. /**
  470. * Adds a <code>component</code> with a tab title defaulting to
  471. * the name of the component.
  472. * Cover method for <code>insertTab</code>.
  473. *
  474. * @param component the component to be displayed when this tab is clicked
  475. * @return the component
  476. *
  477. * @see #insertTab
  478. * @see #removeTabAt
  479. */
  480. public Component add(Component component) {
  481. addTab(component.getName(), component);
  482. return component;
  483. }
  484. /**
  485. * Adds a <code>component</code> with the specified tab title.
  486. * Cover method for <code>insertTab</code>.
  487. *
  488. * @param title the title to be displayed in this tab
  489. * @param component the component to be displayed when this tab is clicked
  490. * @return the component
  491. *
  492. * @see #insertTab
  493. * @see #removeTabAt
  494. */
  495. public Component add(String title, Component component) {
  496. addTab(title, component);
  497. return component;
  498. }
  499. /**
  500. * Adds a <code>component</code> at the specified tab index with a tab
  501. * title defaulting to the name of the component.
  502. * Cover method for <code>insertTab</code>.
  503. *
  504. * @param component the component to be displayed when this tab is clicked
  505. * @param index the position to insert this new tab
  506. * @return the component
  507. *
  508. * @see #insertTab
  509. * @see #removeTabAt
  510. */
  511. public Component add(Component component, int index) {
  512. // Container.add() interprets -1 as "append", so convert
  513. // the index appropriately to be handled by the vector
  514. insertTab(component.getName(), null, component, null,
  515. index == -1? getTabCount() : index);
  516. return component;
  517. }
  518. /**
  519. * Adds a <code>component</code> to the tabbed pane.
  520. * If <code>constraints</code> is a <code>String</code> or an
  521. * <code>Icon</code>, it will be used for the tab title,
  522. * otherwise the component's name will be used as the tab title.
  523. * Cover method for <code>insertTab</code>.
  524. *
  525. * @param component the component to be displayed when this tab is clicked
  526. * @param constraints the object to be displayed in the tab
  527. *
  528. * @see #insertTab
  529. * @see #removeTabAt
  530. */
  531. public void add(Component component, Object constraints) {
  532. if (constraints instanceof String) {
  533. addTab((String)constraints, component);
  534. } else if (constraints instanceof Icon) {
  535. addTab(null, (Icon)constraints, component);
  536. } else {
  537. add(component);
  538. }
  539. }
  540. /**
  541. * Adds a <code>component</code> at the specified tab index.
  542. * If <code>constraints</code> is a <code>String</code> or an
  543. * <code>Icon</code>, it will be used for the tab title,
  544. * otherwise the component's name will be used as the tab title.
  545. * Cover method for <code>insertTab</code>.
  546. *
  547. * @param component the component to be displayed when this tab is clicked
  548. * @constraints the object to be displayed in the tab
  549. * @param index the position to insert this new tab
  550. *
  551. * @see #insertTab
  552. * @see #removeTabAt
  553. */
  554. public void add(Component component, Object constraints, int index) {
  555. Icon icon = constraints instanceof Icon? (Icon)constraints : null;
  556. String title = constraints instanceof String? (String)constraints : null;
  557. // Container.add() interprets -1 as "append", so convert
  558. // the index appropriately to be handled by the vector
  559. insertTab(title, icon, component, null, index == -1? getTabCount() : index);
  560. }
  561. /**
  562. * Removes the tab at <code>index</code>.
  563. * After the component associated with <code>index</code> is removed,
  564. * its visibility is reset to true to ensure it will be visible
  565. * if added to other containers.
  566. * @param index the index of the tab to be removed
  567. *
  568. * @see #addTab
  569. * @see #insertTab
  570. */
  571. public void removeTabAt(int index) {
  572. // If we are removing the currently selected tab AND
  573. // it happens to be the last tab in the bunch, then
  574. // select the previous tab
  575. int tabCount = getTabCount();
  576. int selected = getSelectedIndex();
  577. if (selected >= (tabCount - 1)) {
  578. setSelectedIndex(selected - 1);
  579. }
  580. Component component = getComponentAt(index);
  581. if (accessibleContext != null) {
  582. accessibleContext.firePropertyChange(
  583. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  584. component, null);
  585. }
  586. // We can't assume the tab indices correspond to the
  587. // container's children array indices, so make sure we
  588. // remove the correct child!
  589. if (component != null) {
  590. Component components[] = getComponents();
  591. for (int i = components.length; --i >= 0; ) {
  592. if (components[i] == component) {
  593. super.remove(i);
  594. component.setVisible(true);
  595. break;
  596. }
  597. }
  598. }
  599. pages.removeElementAt(index);
  600. revalidate();
  601. repaint();
  602. }
  603. /**
  604. * Removes the tab which corresponds to the specified component.
  605. *
  606. * @param component the component to remove from the tabbedpane
  607. * @see #addTab
  608. * @see #removeTabAt
  609. */
  610. public void remove(Component component) {
  611. int index = indexOfComponent(component);
  612. if (index != -1) {
  613. removeTabAt(index);
  614. }
  615. }
  616. /**
  617. * Removes the tab and component which corresponds to the specified index.
  618. *
  619. * @param index the index of the component to remove from the
  620. * <code>tabbedpane</code>
  621. * @see #addTab
  622. * @see #removeTabAt
  623. */
  624. public void remove(int index) {
  625. removeTabAt(index);
  626. }
  627. /**
  628. * Removes all the tabs and their corresponding components
  629. * from the <code>tabbedpane</code>.
  630. *
  631. * @see #addTab
  632. * @see #removeTabAt
  633. */
  634. public void removeAll() {
  635. setSelectedIndex(-1);
  636. int tabCount = getTabCount();
  637. for (int i = 0; i < tabCount; i++) {
  638. Component component = getComponentAt(i);
  639. // Reset visibility
  640. if (component != null) {
  641. component.setVisible(true);
  642. }
  643. if (accessibleContext != null) {
  644. accessibleContext.firePropertyChange(
  645. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  646. component, null);
  647. }
  648. }
  649. super.removeAll();
  650. pages.removeAllElements();
  651. revalidate();
  652. repaint();
  653. }
  654. /**
  655. * Returns the number of tabs in this <code>tabbedpane</code>.
  656. *
  657. * @return an integer specifying the number of tabbed pages
  658. */
  659. public int getTabCount() {
  660. return pages.size();
  661. }
  662. /**
  663. * Returns the number of tab runs currently used to display
  664. * the tabs.
  665. * @return an integer giving the number of rows if the
  666. * <code>tabPlacement</code>
  667. * is TOP or BOTTOM and the number of columns if
  668. * <code>tabPlacement</code>
  669. * is LEFT or RIGHT, or 0 if there is no UI set on this
  670. * <code>tabbedpane</code>
  671. */
  672. public int getTabRunCount() {
  673. if (ui != null) {
  674. return ((TabbedPaneUI)ui).getTabRunCount(this);
  675. }
  676. return 0;
  677. }
  678. // Getters for the Pages
  679. /**
  680. * Returns the tab title at <code>index</code>.
  681. *
  682. * @param index the index of the item being queried
  683. * @return the title at <code>index</code>
  684. * @exception IllegalArgumentException if index is out of bounds
  685. * @see #setTitleAt
  686. */
  687. public String getTitleAt(int index) {
  688. return ((Page)pages.elementAt(index)).title;
  689. }
  690. /**
  691. * Returns the tab icon at <code>index</code>.
  692. *
  693. * @param index the index of the item being queried
  694. * @return the icon at <code>index</code>
  695. * @exception IllegalArgumentException if index is out of bounds
  696. *
  697. * @see #setIconAt
  698. */
  699. public Icon getIconAt(int index) {
  700. return ((Page)pages.elementAt(index)).icon;
  701. }
  702. /**
  703. * Returns the tab disabled icon at <code>index</code>.
  704. *
  705. * @param index the index of the item being queried
  706. * @return the icon at <code>index</code>
  707. * @exception IllegalArgumentException if index is out of bounds
  708. *
  709. * @see #setDisabledIconAt
  710. */
  711. public Icon getDisabledIconAt(int index) {
  712. return ((Page)pages.elementAt(index)).disabledIcon;
  713. }
  714. /**
  715. * Returns the tab tooltip text at <code>index</code>.
  716. *
  717. * @param index the index of the item being queried
  718. * @return a string containing the tool tip text at <code>index</code>
  719. * @exception IllegalArgumentException if index is out of bounds
  720. *
  721. * @see #setToolTipTextAt
  722. */
  723. public String getToolTipTextAt(int index) {
  724. return ((Page)pages.elementAt(index)).tip;
  725. }
  726. /**
  727. * Returns the tab background color at <code>index</code>.
  728. *
  729. * @param index the index of the item being queried
  730. * @return the <code>Color</code> of the tab background at
  731. * <code>index</code>
  732. * @exception IllegalArgumentException if index is out of bounds
  733. *
  734. * @see #setBackgroundAt
  735. */
  736. public Color getBackgroundAt(int index) {
  737. return ((Page)pages.elementAt(index)).getBackground();
  738. }
  739. /**
  740. * Returns the tab foreground color at <code>index</code>.
  741. *
  742. * @param index the index of the item being queried
  743. * @return the <code>Color</code> of the tab foreground at
  744. * <code>index</code>
  745. * @exception IllegalArgumentException if index is out of bounds
  746. *
  747. * @see #setForegroundAt
  748. */
  749. public Color getForegroundAt(int index) {
  750. return ((Page)pages.elementAt(index)).getForeground();
  751. }
  752. /**
  753. * Returns whether or not the tab at <code>index</code> is
  754. * currently enabled.
  755. *
  756. * @param index the index of the item being queried
  757. * @return true if the tab at <code>index</code> is enabled;
  758. * false otherwise
  759. * @exception IllegalArgumentException if index is out of bounds
  760. *
  761. * @see #setEnabledAt
  762. */
  763. public boolean isEnabledAt(int index) {
  764. return ((Page)pages.elementAt(index)).isEnabled();
  765. }
  766. /**
  767. * Returns the component at <code>index</code>.
  768. *
  769. * @param index the index of the item being queried
  770. * @return the <code>Component</code> at <code>index</code>
  771. * @exception IllegalArgumentException if index is out of bounds
  772. *
  773. * @see #setComponentAt
  774. */
  775. public Component getComponentAt(int index) {
  776. return ((Page)pages.elementAt(index)).component;
  777. }
  778. /**
  779. * Returns the tab bounds at <code>index</code>. If the tab at
  780. * this index is not currently visible in the UI, then returns
  781. * <code>null</code>.
  782. * If there is no UI set on this <code>tabbedpane</code>,
  783. * then returns <code>null</code>.
  784. *
  785. * @param index the index to be queried
  786. * @return a <code>Rectangle</code> containing the tab bounds at
  787. * <code>index</code>, or <code>null</code> if tab at
  788. * <code>index</code> is not currently visible in the UI,
  789. * or if there is no UI set on this <code>tabbedpane</code>
  790. */
  791. public Rectangle getBoundsAt(int index) {
  792. if (ui != null) {
  793. return ((TabbedPaneUI)ui).getTabBounds(this, index);
  794. }
  795. return null;
  796. }
  797. // Setters for the Pages
  798. /**
  799. * Sets the title at <code>index</code> to <code>title</code> which
  800. * can be <code>null</code>.
  801. * An internal exception is raised if there is no tab at that index.
  802. *
  803. * @param index the tab index where the title should be set
  804. * @param title the title to be displayed in the tab
  805. * @exception IllegalArgumentException if index is out of bounds
  806. *
  807. * @see #getTitleAt
  808. * @beaninfo
  809. * preferred: true
  810. * attribute: visualUpdate true
  811. * description: The title at the specified tab index.
  812. */
  813. public void setTitleAt(int index, String title) {
  814. String oldTitle =((Page)pages.elementAt(index)).title;
  815. ((Page)pages.elementAt(index)).title = title;
  816. if ((oldTitle != title) && (accessibleContext != null)) {
  817. accessibleContext.firePropertyChange(
  818. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  819. oldTitle, title);
  820. }
  821. if (title == null || oldTitle == null ||
  822. !title.equals(oldTitle)) {
  823. revalidate();
  824. repaint();
  825. }
  826. }
  827. /**
  828. * Sets the icon at <code>index</code> to <code>icon</code> which can be
  829. * <code>null</code>.
  830. * An internal exception is raised if there is no tab at that index.
  831. *
  832. * @param index the tab index where the icon should be set
  833. * @param icon the icon to be displayed in the tab
  834. * @exception IllegalArgumentException if index is out of bounds
  835. *
  836. * @see #getIconAt
  837. * @beaninfo
  838. * preferred: true
  839. * attribute: visualUpdate true
  840. * description: The icon at the specified tab index.
  841. */
  842. public void setIconAt(int index, Icon icon) {
  843. Icon oldIcon = ((Page)pages.elementAt(index)).icon;
  844. ((Page)pages.elementAt(index)).icon = icon;
  845. AccessibleContext ac = getAccessibleContext();
  846. // Fire the accessibility Visible data change
  847. if ((oldIcon != icon) && (accessibleContext != null)) {
  848. accessibleContext.firePropertyChange(
  849. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  850. oldIcon, icon);
  851. }
  852. if (icon != oldIcon) {
  853. revalidate();
  854. repaint();
  855. }
  856. }
  857. /**
  858. * Sets the disabled icon at <code>index</code> to <code>icon</code>
  859. * which can be <code>null</code>.
  860. * An internal exception is raised if there is no tab at that index.
  861. *
  862. * @param index the tab index where the disabled icon should be set
  863. * @param icon the icon to be displayed in the tab when disabled
  864. * @exception IllegalArgumentException if index is out of bounds
  865. *
  866. * @see #getDisabledIconAt
  867. * @beaninfo
  868. * preferred: true
  869. * attribute: visualUpdate true
  870. * description: The disabled icon at the specified tab index.
  871. */
  872. public void setDisabledIconAt(int index, Icon disabledIcon) {
  873. Icon oldIcon = ((Page)pages.elementAt(index)).disabledIcon;
  874. ((Page)pages.elementAt(index)).disabledIcon = disabledIcon;
  875. if (disabledIcon != oldIcon && !isEnabledAt(index)) {
  876. revalidate();
  877. repaint();
  878. }
  879. }
  880. /**
  881. * Sets the tooltip text at <code>index</code> to <code>toolTipText</code>
  882. * which can be <code>null</code>.
  883. * An internal exception is raised if there is no tab at that index.
  884. *
  885. * @param index the tab index where the tooltip text should be set
  886. * @param toolTipText the tooltip text to be displayed for the tab
  887. * @exception IllegalArgumentException if index is out of bounds
  888. *
  889. * @see #getToolTipTextAt
  890. * @beaninfo
  891. * preferred: true
  892. * description: The tooltip text at the specified tab index.
  893. */
  894. public void setToolTipTextAt(int index, String toolTipText) {
  895. String oldToolTipText =((Page)pages.elementAt(index)).tip;
  896. ((Page)pages.elementAt(index)).tip = toolTipText;
  897. if ((oldToolTipText != toolTipText) && (accessibleContext != null)) {
  898. accessibleContext.firePropertyChange(
  899. AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  900. oldToolTipText, toolTipText);
  901. }
  902. if (!haveRegistered && toolTipText != null) {
  903. ToolTipManager.sharedInstance().registerComponent(this);
  904. haveRegistered = true;
  905. }
  906. }
  907. /**
  908. * Sets the background color at <code>index</code> to
  909. * <code>background</code>
  910. * which can be <code>null</code>, in which case the tab's background color
  911. * will default to the background color of the <code>tabbedpane</code>.
  912. * An internal exception is raised if there is no tab at that index.
  913. * @param index the tab index where the background should be set
  914. * @param background the color to be displayed in the tab's background
  915. * @exception IllegalArgumentException if index is out of bounds
  916. *
  917. * @see #getBackgroundAt
  918. * @beaninfo
  919. * preferred: true
  920. * attribute: visualUpdate true
  921. * description: The background color at the specified tab index.
  922. */
  923. public void setBackgroundAt(int index, Color background) {
  924. Color oldBg = ((Page)pages.elementAt(index)).background;
  925. ((Page)pages.elementAt(index)).setBackground(background);
  926. if (background == null || oldBg == null ||
  927. !background.equals(oldBg)) {
  928. Rectangle tabBounds = getBoundsAt(index);
  929. if (tabBounds != null) {
  930. repaint(tabBounds);
  931. }
  932. }
  933. }
  934. /**
  935. * Sets the foreground color at <code>index</code> to
  936. * <code>foreground</code> which can be
  937. * <code>null</code>, in which case the tab's foreground color
  938. * will default to the foreground color of this <code>tabbedpane</code>.
  939. * An internal exception is raised if there is no tab at that index.
  940. *
  941. * @param index the tab index where the foreground should be set
  942. * @param foreground the color to be displayed as the tab's foreground
  943. * @exception IllegalArgumentException if index is out of bounds
  944. *
  945. * @see #getForegroundAt
  946. * @beaninfo
  947. * preferred: true
  948. * attribute: visualUpdate true
  949. * description: The foreground color at the specified tab index.
  950. */
  951. public void setForegroundAt(int index, Color foreground) {
  952. Color oldFg = ((Page)pages.elementAt(index)).foreground;
  953. ((Page)pages.elementAt(index)).setForeground(foreground);
  954. if (foreground == null || oldFg == null ||
  955. !foreground.equals(oldFg)) {
  956. Rectangle tabBounds = getBoundsAt(index);
  957. if (tabBounds != null) {
  958. repaint(tabBounds);
  959. }
  960. }
  961. }
  962. /**
  963. * Sets whether or not the tab at <code>index</code> is enabled.
  964. * An internal exception is raised if there is no tab at that index.
  965. *
  966. * @param index the tab index which should be enabled/disabled
  967. * @param enabled whether or not the tab should be enabled
  968. * @exception IllegalArgumentException if index is out of bounds
  969. *
  970. * @see #isEnabledAt
  971. */
  972. public void setEnabledAt(int index, boolean enabled) {
  973. boolean oldEnabled = ((Page)pages.elementAt(index)).isEnabled();
  974. ((Page)pages.elementAt(index)).setEnabled(enabled);
  975. if (enabled != oldEnabled) {
  976. repaint(getBoundsAt(index));
  977. }
  978. }
  979. /**
  980. * Sets the component at <code>index</code> to <code>component</code>.
  981. * An internal exception is raised if there is no tab at that index.
  982. *
  983. * @param index the tab index where this component is being placed
  984. * @param component the component for the tab
  985. * @exception IllegalArgumentException if index is out of bounds
  986. *
  987. * @see #getComponentAt
  988. * @beaninfo
  989. * attribute: visualUpdate true
  990. * description: The component at the specified tab index.
  991. */
  992. public void setComponentAt(int index, Component component) {
  993. Page page = (Page)pages.elementAt(index);
  994. if (component != page.component) {
  995. if (page.component != null) {
  996. // REMIND(aim): this is really silly;
  997. // why not if (page.component.getParent() == this) remove(component)
  998. synchronized(getTreeLock()) {
  999. int count = getComponentCount();
  1000. Component children[] = getComponents();
  1001. for (int i = 0; i < count; i++) {
  1002. if (children[i] == page.component) {
  1003. super.remove(i);
  1004. }
  1005. }
  1006. }
  1007. }
  1008. page.component = component;
  1009. component.setVisible(getSelectedIndex() == index);
  1010. addImpl(component, null, -1);
  1011. revalidate();
  1012. }
  1013. }
  1014. /**
  1015. * Returns the first tab index with a given <code>title</code>, or
  1016. * -1 if no tab has this title.
  1017. *
  1018. * @param title the title for the tab
  1019. * @return the first tab index which matches <code>title</code>, or
  1020. * -1 if no tab has this title
  1021. */
  1022. public int indexOfTab(String title) {
  1023. for(int i = 0; i < getTabCount(); i++) {
  1024. if (getTitleAt(i).equals(title == null? "" : title)) {
  1025. return i;
  1026. }
  1027. }
  1028. return -1;
  1029. }
  1030. /**
  1031. * Returns the first tab index with a given <code>icon</code>,
  1032. * or -1 if no tab has this icon.
  1033. *
  1034. * @param icon the icon for the tab
  1035. * @return the first tab index which matches <code>icon</code>,
  1036. * or -1 if no tab has this icon
  1037. */
  1038. public int indexOfTab(Icon icon) {
  1039. for(int i = 0; i < getTabCount(); i++) {
  1040. Icon tabIcon = getIconAt(i);
  1041. if ((tabIcon != null && tabIcon.equals(icon)) ||
  1042. (tabIcon == null && tabIcon == icon)) {
  1043. return i;
  1044. }
  1045. }
  1046. return -1;
  1047. }
  1048. /**
  1049. * Returns the index of the tab for the specified component.
  1050. * Returns -1 if there is no tab for this component.
  1051. *
  1052. * @param component the component for the tab
  1053. * @return the first tab which matches this component, or -1
  1054. * if there is no tab for this component
  1055. */
  1056. public int indexOfComponent(Component component) {
  1057. for(int i = 0; i < getTabCount(); i++) {
  1058. Component c = getComponentAt(i);
  1059. if ((c != null && c.equals(component)) ||
  1060. (c == null && c == component)) {
  1061. return i;
  1062. }
  1063. }
  1064. return -1;
  1065. }
  1066. /**
  1067. * Returns the tooltip text for the component determined by the
  1068. * mouse event location.
  1069. *
  1070. * @param event the <code>MouseEvent</code> that tells where the
  1071. * cursor is lingering
  1072. * @return the <code>String</code> containing the tooltip text
  1073. * @exception IllegalArgumentException if index is out of bounds
  1074. */
  1075. public String getToolTipText(MouseEvent event) {
  1076. if (ui != null) {
  1077. int index = ((TabbedPaneUI)ui).tabForCoordinate(this, event.getX(), event.getY());
  1078. if (index != -1) {
  1079. return ((Page)pages.elementAt(index)).tip;
  1080. }
  1081. }
  1082. return super.getToolTipText(event);
  1083. }
  1084. /**
  1085. * See <code>readObject</code> and <code>writeObject</code> in
  1086. * <code>JComponent</code> for more
  1087. * information about serialization in Swing.
  1088. */
  1089. private void writeObject(ObjectOutputStream s) throws IOException {
  1090. s.defaultWriteObject();
  1091. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  1092. ui.installUI(this);
  1093. }
  1094. }
  1095. /* Called from the <code>JComponent</code>'s
  1096. * <code>EnableSerializationFocusListener</code> to
  1097. * do any Swing-specific pre-serialization configuration.
  1098. */
  1099. void compWriteObjectNotify() {
  1100. super.compWriteObjectNotify();
  1101. // If ToolTipText != null, then the tooltip has already been
  1102. // unregistered by JComponent.compWriteObjectNotify()
  1103. if (getToolTipText() == null && haveRegistered) {
  1104. ToolTipManager.sharedInstance().unregisterComponent(this);
  1105. }
  1106. }
  1107. /**
  1108. * See <code>readObject</code> and <code>writeObject</code> in
  1109. * <code>JComponent</code> for more
  1110. * information about serialization in Swing.
  1111. */
  1112. private void readObject(ObjectInputStream s)
  1113. throws IOException, ClassNotFoundException
  1114. {
  1115. s.defaultReadObject();
  1116. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  1117. ui.installUI(this);
  1118. }
  1119. // If ToolTipText != null, then the tooltip has already been
  1120. // registered by JComponent.readObject()
  1121. if (getToolTipText() == null && haveRegistered) {
  1122. ToolTipManager.sharedInstance().registerComponent(this);
  1123. }
  1124. }
  1125. /**
  1126. * Returns a string representation of this <code>JTabbedPane</code>.
  1127. * This method
  1128. * is intended to be used only for debugging purposes, and the
  1129. * content and format of the returned string may vary between
  1130. * implementations. The returned string may be empty but may not
  1131. * be <code>null</code>.
  1132. *
  1133. * @return a string representation of this JTabbedPane.
  1134. */
  1135. protected String paramString() {
  1136. String tabPlacementString;
  1137. if (tabPlacement == TOP) {
  1138. tabPlacementString = "TOP";
  1139. } else if (tabPlacement == BOTTOM) {
  1140. tabPlacementString = "BOTTOM";
  1141. } else if (tabPlacement == LEFT) {
  1142. tabPlacementString = "LEFT";
  1143. } else if (tabPlacement == RIGHT) {
  1144. tabPlacementString = "RIGHT";
  1145. } else tabPlacementString = "";
  1146. String haveRegisteredString = (haveRegistered ?
  1147. "true" : "false");
  1148. return super.paramString() +
  1149. ",haveRegistered=" + haveRegisteredString +
  1150. ",tabPlacement=" + tabPlacementString;
  1151. }
  1152. /////////////////
  1153. // Accessibility support
  1154. ////////////////
  1155. /**
  1156. * Gets the AccessibleContext associated with this JTabbedPane.
  1157. * For tabbed panes, the AccessibleContext takes the form of an
  1158. * AccessibleJTabbedPane.
  1159. * A new AccessibleJTabbedPane instance is created if necessary.
  1160. *
  1161. * @return an AccessibleJTabbedPane that serves as the
  1162. * AccessibleContext of this JTabbedPane
  1163. */
  1164. public AccessibleContext getAccessibleContext() {
  1165. if (accessibleContext == null) {
  1166. accessibleContext = new AccessibleJTabbedPane();
  1167. }
  1168. return accessibleContext;
  1169. }
  1170. /**
  1171. * This class implements accessibility support for the
  1172. * <code>JTabbedPane</code> class. It provides an implementation of the
  1173. * Java Accessibility API appropriate to tabbed pane user-interface
  1174. * elements.
  1175. * <p>
  1176. * <strong>Warning:</strong>
  1177. * Serialized objects of this class will not be compatible with
  1178. * future Swing releases. The current serialization support is appropriate
  1179. * for short term storage or RMI between applications running the same
  1180. * version of Swing. A future release of Swing will provide support for
  1181. * long term persistence.
  1182. */
  1183. protected class AccessibleJTabbedPane extends AccessibleJComponent
  1184. implements AccessibleSelection, ChangeListener {
  1185. /**
  1186. * Constructs an AccessibleJTabbedPane
  1187. */
  1188. public AccessibleJTabbedPane() {
  1189. super();
  1190. JTabbedPane.this.model.addChangeListener(this);
  1191. }
  1192. public void stateChanged(ChangeEvent e) {
  1193. Object o = e.getSource();
  1194. firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  1195. null, o);
  1196. }
  1197. /**
  1198. * Get the role of this object.
  1199. *
  1200. * @return an instance of AccessibleRole describing the role of
  1201. * the object
  1202. */
  1203. public AccessibleRole getAccessibleRole() {
  1204. return AccessibleRole.PAGE_TAB_LIST;
  1205. }
  1206. /**
  1207. * Returns the number of accessible children in the object.
  1208. *
  1209. * @return the number of accessible children in the object.
  1210. */
  1211. public int getAccessibleChildrenCount() {
  1212. return getTabCount();
  1213. }
  1214. /**
  1215. * Return the specified Accessible child of the object.
  1216. *
  1217. * @param i zero-based index of child
  1218. * @return the Accessible child of the object
  1219. * @exception IllegalArgumentException if index is out of bounds
  1220. */
  1221. public Accessible getAccessibleChild(int i) {
  1222. if (i < 0 || i >= getTabCount()) {
  1223. return null;
  1224. }
  1225. return (Accessible) pages.elementAt(i);
  1226. }
  1227. /**
  1228. * Get the AccessibleSelection associated with this object. In the
  1229. * implementation of the Java Accessibility API for this class,
  1230. * return this object, which is responsible for implementing the
  1231. * AccessibleSelection interface on behalf of itself.
  1232. *
  1233. * @return this object
  1234. */
  1235. public AccessibleSelection getAccessibleSelection() {
  1236. return this;
  1237. }
  1238. public Accessible getAccessibleAt(Point p) {
  1239. int tab = ((TabbedPaneUI) ui).tabForCoordinate(JTabbedPane.this,
  1240. p.x, p.y);
  1241. if (tab == -1) {
  1242. tab = getSelectedIndex();
  1243. }
  1244. return getAccessibleChild(tab);
  1245. }
  1246. public int getAccessibleSelectionCount() {
  1247. return 1;
  1248. }
  1249. public Accessible getAccessibleSelection(int i) {
  1250. int index = getSelectedIndex();
  1251. if (index == -1) {
  1252. return null;
  1253. }
  1254. return (Accessible) pages.elementAt(index);
  1255. }
  1256. public boolean isAccessibleChildSelected(int i) {
  1257. return (i == getSelectedIndex());
  1258. }
  1259. public void addAccessibleSelection(int i) {
  1260. setSelectedIndex(i);
  1261. }
  1262. public void removeAccessibleSelection(int i) {
  1263. // can't do
  1264. }
  1265. public void clearAccessibleSelection() {
  1266. // can't do
  1267. }
  1268. public void selectAllAccessibleSelection() {
  1269. // can't do
  1270. }
  1271. }
  1272. private class Page extends AccessibleContext
  1273. implements Serializable, Accessible, AccessibleComponent {
  1274. String title;
  1275. Color background;
  1276. Color foreground;
  1277. Icon icon;
  1278. Icon disabledIcon;
  1279. JTabbedPane parent;
  1280. Component component;
  1281. String tip;
  1282. boolean enabled = true;
  1283. boolean needsUIUpdate;
  1284. Page(JTabbedPane parent,
  1285. String title, Icon icon, Icon disabledIcon, Component component, String tip) {
  1286. this.title = title;
  1287. this.icon = icon;
  1288. this.disabledIcon = disabledIcon;
  1289. this.parent = parent;
  1290. this.setAccessibleParent(parent);
  1291. this.component = component;
  1292. this.tip = tip;
  1293. if (component instanceof Accessible) {
  1294. AccessibleContext ac;
  1295. ac = ((Accessible) component).getAccessibleContext();
  1296. if (ac != null) {
  1297. ac.setAccessibleParent(this);
  1298. }
  1299. }
  1300. }
  1301. /////////////////
  1302. // Accessibility support
  1303. ////////////////
  1304. public AccessibleContext getAccessibleContext() {
  1305. return this;
  1306. }
  1307. // AccessibleContext methods
  1308. public String getAccessibleName() {
  1309. if (accessibleName != null) {
  1310. return accessibleName;
  1311. } else if (title != null) {
  1312. return title;
  1313. }
  1314. return null;
  1315. }
  1316. public String getAccessibleDescription() {
  1317. if (accessibleDescription != null) {
  1318. return accessibleDescription;
  1319. } else if (tip != null) {
  1320. return tip;
  1321. }
  1322. return null;
  1323. }
  1324. public AccessibleRole getAccessibleRole() {
  1325. return AccessibleRole.PAGE_TAB;
  1326. }
  1327. public AccessibleStateSet getAccessibleStateSet() {
  1328. AccessibleStateSet states;
  1329. states = parent.getAccessibleContext().getAccessibleStateSet();
  1330. states.add(AccessibleState.SELECTABLE);
  1331. int i = parent.indexOfTab(title);
  1332. if (i == parent.getSelectedIndex()) {
  1333. states.add(AccessibleState.SELECTED);
  1334. }
  1335. return states;
  1336. }
  1337. public int getAccessibleIndexInParent() {
  1338. return parent.indexOfTab(title);
  1339. }
  1340. public int getAccessibleChildrenCount() {
  1341. if (component instanceof Accessible) {
  1342. return 1;
  1343. } else {
  1344. return 0;
  1345. }
  1346. }
  1347. public Accessible getAccessibleChild(int i) {
  1348. if (component instanceof Accessible) {
  1349. return (Accessible) component;
  1350. } else {
  1351. return null;
  1352. }
  1353. }
  1354. public Locale getLocale() {
  1355. return parent.getLocale();
  1356. }
  1357. public AccessibleComponent getAccessibleComponent() {
  1358. return this;
  1359. }
  1360. // AccessibleComponent methods
  1361. public Color getBackground() {
  1362. return background != null? background : parent.getBackground();
  1363. }
  1364. public void setBackground(Color c) {
  1365. background = c;
  1366. }
  1367. public Color getForeground() {
  1368. return foreground != null? foreground : parent.getForeground();
  1369. }
  1370. public void setForeground(Color c) {
  1371. foreground = c;
  1372. }
  1373. public Cursor getCursor() {
  1374. return parent.getCursor();
  1375. }
  1376. public void setCursor(Cursor c) {
  1377. parent.setCursor(c);
  1378. }
  1379. public Font getFont() {
  1380. return parent.getFont();
  1381. }
  1382. public void setFont(Font f) {
  1383. parent.setFont(f);
  1384. }
  1385. public FontMetrics getFontMetrics(Font f) {
  1386. return parent.getFontMetrics(f);
  1387. }
  1388. public boolean isEnabled() {
  1389. return enabled;
  1390. }
  1391. public void setEnabled(boolean b) {
  1392. enabled = b;
  1393. }
  1394. public boolean isVisible() {
  1395. return parent.isVisible();
  1396. }
  1397. public void setVisible(boolean b) {
  1398. parent.setVisible(b);
  1399. }
  1400. public boolean isShowing() {
  1401. return parent.isShowing();
  1402. }
  1403. public boolean contains(Point p) {
  1404. Rectangle r = getBounds();
  1405. return r.contains(p);
  1406. }
  1407. public Point getLocationOnScreen() {
  1408. Point parentLocation = parent.getLocationOnScreen();
  1409. Point componentLocation = getLocation();
  1410. componentLocation.translate(parentLocation.x, parentLocation.y);
  1411. return componentLocation;
  1412. }
  1413. public Point getLocation() {
  1414. Rectangle r = getBounds();
  1415. return new Point(r.x, r.y);
  1416. }
  1417. public void setLocation(Point p) {
  1418. // do nothing
  1419. }
  1420. public Rectangle getBounds() {
  1421. return parent.getUI().getTabBounds(parent,
  1422. parent.indexOfTab(title));
  1423. }
  1424. public void setBounds(Rectangle r) {
  1425. // do nothing
  1426. }
  1427. public Dimension getSize() {
  1428. Rectangle r = getBounds();
  1429. return new Dimension(r.width, r.height);
  1430. }
  1431. public void setSize(Dimension d) {
  1432. // do nothing
  1433. }
  1434. public Accessible getAccessibleAt(Point p) {
  1435. if (component instanceof Accessible) {
  1436. return (Accessible) component;
  1437. } else {
  1438. return null;
  1439. }
  1440. }
  1441. public boolean isFocusTraversable() {
  1442. return false;
  1443. }
  1444. public void requestFocus() {
  1445. // do nothing
  1446. }
  1447. public void addFocusListener(FocusListener l) {
  1448. // do nothing
  1449. }
  1450. public void removeFocusListener(FocusListener l) {
  1451. // do nothing
  1452. }
  1453. }
  1454. }