1. /*
  2. * @(#)JComponent.java 2.113 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.util.Hashtable;
  9. import java.util.Dictionary;
  10. import java.util.Enumeration;
  11. import java.util.Locale;
  12. import java.util.Vector;
  13. import java.awt.*;
  14. import java.awt.event.*;
  15. import java.beans.*;
  16. import java.applet.Applet;
  17. import java.io.Serializable;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. import java.io.ObjectInputValidation;
  22. import java.io.InvalidObjectException;
  23. import javax.swing.border.*;
  24. import javax.swing.event.*;
  25. import javax.swing.plaf.*;
  26. import javax.accessibility.*;
  27. import java.awt.Graphics2D;
  28. /**
  29. * The base class for the Swing components. JComponent provides:
  30. * <ul>
  31. * <li>A "pluggable look and feel" (l&f) that can be specified by the
  32. * programmer or (optionally) selected by the user at runtime.
  33. * <li>Components that are designed to be combined and extended in order
  34. * to create custom components.
  35. * <li>Comprehensive keystroke-handling that works with nested components.
  36. * <li>Action objects, for single-point control of program actions initiated
  37. * by multiple components.
  38. * <li>A border property that implicitly defines the component's insets.
  39. * <li>The ability to set the preferred, minimim, and maximum size for a
  40. * component.
  41. * <li>ToolTips -- short descriptions that pop up when the cursor lingers
  42. * over a component.
  43. * <li>Autoscrolling -- automatic scrolling in a list, table, or tree that
  44. * occurs when the user is dragging the mouse.
  45. * <li>Simple, easy dialog construction using static methods in the JOptionPane
  46. * class that let you display information and query the user.
  47. * <li>Slow-motion graphics rendering using debugGraphics so you can see
  48. * what is being displayed on screen and whether or not it is being
  49. * overwritten.
  50. * <li>Support for Accessibility.
  51. * <li>Support for international Localization.
  52. * </ul>
  53. * For more information on these subjects, see the
  54. * <a href="package-summary.html#package_description">Swing package description</a>
  55. * <p>
  56. * <strong>Warning:</strong>
  57. * Serialized objects of this class will not be compatible with
  58. * future Swing releases. The current serialization support is appropriate
  59. * for short term storage or RMI between applications running the same
  60. * version of Swing. A future release of Swing will provide support for
  61. * long term persistence.
  62. *
  63. * @see KeyStroke
  64. * @see Action
  65. * @see #setBorder
  66. * @see #registerKeyboardAction
  67. * @see JOptionPane
  68. * @see #setDebugGraphicsOptions
  69. * @see #setToolTipText
  70. * @see #setAutoscrolls
  71. *
  72. * @version 2.113 11/29/01
  73. * @author Hans Muller
  74. * @author Arnaud Weber
  75. */
  76. public abstract class JComponent extends Container implements Serializable
  77. {
  78. /**
  79. * @see #getUIClassID
  80. * @see #writeObject
  81. */
  82. private static final String uiClassID = "ComponentUI";
  83. /**
  84. * @see ReadObjectCallback
  85. * @se #readObject
  86. */
  87. private static final Hashtable readObjectCallbacks = new Hashtable(1);
  88. /* The following fields support set methods for the corresponding
  89. * java.awt.Component properties.
  90. */
  91. private Dimension preferredSize;
  92. private Dimension minimumSize;
  93. private Dimension maximumSize;
  94. private Float alignmentX;
  95. private Float alignmentY;
  96. private AncestorNotifier ancestorNotifier;
  97. Rectangle _bounds = new Rectangle();
  98. /* Backing store for JComponent properties and listeners
  99. */
  100. protected transient ComponentUI ui;
  101. protected EventListenerList listenerList = new EventListenerList();
  102. private Hashtable clientProperties;
  103. private VetoableChangeSupport vetoableChangeSupport;
  104. private Autoscroller autoscroller;
  105. private Border border;
  106. private int flags;
  107. /* A "scratch pad" rectangle used by the painting code.
  108. */
  109. private transient Rectangle tmpRect;
  110. /** Set in _paintImmediately. Will indicate the child that initiated
  111. * the painting operation. If paintingChild is opaque, no need to paint
  112. * any child components after paintingChild. Test used in paintChildren. */
  113. transient Component paintingChild;
  114. /**
  115. * Constant used for registerKeyboardAction() which
  116. * means that the command should be invoked when
  117. * the component has the focus.
  118. */
  119. public static final int WHEN_FOCUSED = 0;
  120. /**
  121. * Constant used for registerKeyboardAction() which
  122. * means that the comand should be invoked when the receiving
  123. * component is an ancestor of the focused component or is
  124. * itself the focused component.
  125. */
  126. public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
  127. /**
  128. * Constant used for registerKeyboardAction() which
  129. * means that the command should be invoked when
  130. * the receiving component is in the window that has the focus
  131. * or is itself the focused component.
  132. */
  133. public static final int WHEN_IN_FOCUSED_WINDOW = 2;
  134. /**
  135. * Constant used by some of the apis to mean that no condition is defined.
  136. */
  137. public static final int UNDEFINED_CONDITION = -1;
  138. /**
  139. * The key used by JComponent to access keyboard bindings.
  140. */
  141. private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
  142. /**
  143. * The comment to display when the cursor is over the component,
  144. * also known as a "value tip", "flyover help", or "flyover label".
  145. */
  146. public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
  147. private static final String NEXT_FOCUS = "nextFocus";
  148. /** Private flags **/
  149. private static final int REQUEST_FOCUS_DISABLED = 0;
  150. private static final int IS_DOUBLE_BUFFERED = 1;
  151. private static final int ANCESTOR_USING_BUFFER = 2;
  152. private static final int IS_PAINTING_TILE = 3;
  153. private static final int HAS_FOCUS = 4;
  154. private static final int IS_OPAQUE = 5;
  155. private static final int IS_PRINTING = 12;
  156. private static final int IS_PRINTING_ALL = 13;
  157. /**
  158. * Default JComponent constructor. This constructor does
  159. * no initialization beyond calling the Container constructor,
  160. * e.g. the initial layout manager is null.
  161. */
  162. public JComponent() {
  163. super();
  164. enableEvents(AWTEvent.FOCUS_EVENT_MASK);
  165. enableSerialization();
  166. }
  167. /**
  168. * Resets the UI property to a value from the current look and feel.
  169. * JComponent subclasses must override this method like this:
  170. * <pre>
  171. * public void updateUI() {
  172. * setUI((SliderUI)UIManager.getUI(this);
  173. * }
  174. * </pre>
  175. *
  176. * @see #setUI
  177. * @see UIManager#getLookAndFeel
  178. * @see UIManager#getUI
  179. */
  180. public void updateUI() {}
  181. /**
  182. * Set the look and feel delegate for this component.
  183. * JComponent subclasses generally override this method
  184. * to narrow the argument type, e.g. in JSlider:
  185. * <pre>
  186. * public void setUI(SliderUI newUI) {
  187. * super.setUI(newUI);
  188. * }
  189. * </pre>
  190. * <p>
  191. * Additionaly JComponent subclasses must provide a getUI
  192. * method that returns the correct type, e.g.
  193. * <pre>
  194. * public SliderUI getUI() {
  195. * return (SliderUI)ui;
  196. * }
  197. * </pre>
  198. *
  199. * @see #updateUI
  200. * @see UIManager#getLookAndFeel
  201. * @see UIManager#getUI
  202. * @beaninfo
  203. * bound: true
  204. * attribute: visualUpdate true
  205. * description: The component's look and feel delegate
  206. */
  207. protected void setUI(ComponentUI newUI) {
  208. /* We do not check that the UI instance is different
  209. * before allowing the switch in order to enable the
  210. * same UI instance *with different default settings*
  211. * to be installed.
  212. */
  213. if (ui != null) {
  214. ui.uninstallUI(this);
  215. }
  216. ComponentUI oldUI = ui;
  217. ui = newUI;
  218. if (ui != null) {
  219. ui.installUI(this);
  220. }
  221. firePropertyChange("UI", oldUI, newUI);
  222. revalidate();
  223. repaint();
  224. }
  225. /**
  226. * Return the UIDefaults key used to look up the name of the
  227. * swing.plaf.ComponentUI class that defines the look and feel
  228. * for this component. Most applications will never need to
  229. * call this method. Subclasses of JComponent that support
  230. * pluggable look and feel should override this method to
  231. * return a UIDefaults key that maps to the ComponentUI subclass
  232. * that defines their look and feel.
  233. *
  234. * @return The UIDefaults key for a ComponentUI subclass.
  235. * @see UIDefaults#getUI
  236. * @beaninfo
  237. * expert: true
  238. * description: UIClassID
  239. */
  240. public String getUIClassID() {
  241. return uiClassID;
  242. }
  243. /**
  244. * Returns the graphics object used to paint this component.
  245. * If DebugGraphics is turned on we create a new DebugGraphics
  246. * object if neccessary otherwise we just configure the
  247. * specified graphics objects foreground and font.
  248. *
  249. * @return A Graphics object configured for this component
  250. */
  251. protected Graphics getComponentGraphics(Graphics g) {
  252. Graphics componentGraphics = g;
  253. if (ui != null) {
  254. if ((DebugGraphics.debugComponentCount() != 0) &&
  255. (shouldDebugGraphics() != 0) &&
  256. !(g instanceof DebugGraphics)) {
  257. if(g instanceof SwingGraphics) {
  258. if(!(((SwingGraphics)g).subGraphics() instanceof DebugGraphics)) {
  259. componentGraphics = new DebugGraphics(((SwingGraphics)g).subGraphics(),this);
  260. componentGraphics = SwingGraphics.createSwingGraphics(componentGraphics);
  261. }
  262. } else {
  263. componentGraphics = new DebugGraphics(g,this);
  264. }
  265. }
  266. }
  267. componentGraphics.setColor(getForeground());
  268. componentGraphics.setFont(getFont());
  269. return componentGraphics;
  270. }
  271. /**
  272. * If the UI delegate is non-null, call its paint
  273. * method. We pass the delegate a copy of the Graphics
  274. * object to protect the rest of the paint code from
  275. * irrevocable changes (e.g. Graphics.translate()).
  276. *
  277. * @see #paint
  278. */
  279. protected void paintComponent(Graphics g) {
  280. if (ui != null) {
  281. Graphics scratchGraphics = SwingGraphics.createSwingGraphics(g);
  282. try {
  283. ui.update(scratchGraphics, this);
  284. }
  285. finally {
  286. scratchGraphics.dispose();
  287. }
  288. }
  289. }
  290. /**
  291. * Paint this component's children.
  292. * If shouldUseBuffer is true, no component ancestor has a buffer and
  293. * the component children can use a buffer if they have one.
  294. * Otherwise, one ancestor has a buffer currently in use and children
  295. * should not use a buffer to paint.
  296. * @see #paint
  297. * @see java.awt.Container#paint
  298. */
  299. protected void paintChildren(Graphics g) {
  300. boolean isJComponent;
  301. Graphics sg = null;
  302. try {
  303. synchronized(getTreeLock()) {
  304. boolean printing = getFlag(IS_PRINTING);
  305. int i = getComponentCount() - 1;
  306. if (i < 0) {
  307. return;
  308. }
  309. sg = SwingGraphics.createSwingGraphics(g);
  310. // If we are only to paint to a specific child, determine
  311. // its index.
  312. if (paintingChild != null &&
  313. (paintingChild instanceof JComponent) &&
  314. ((JComponent)paintingChild).isOpaque()) {
  315. for (; i >= 0; i--) {
  316. if (getComponent(i) == paintingChild){
  317. break;
  318. }
  319. }
  320. }
  321. if(tmpRect == null) {
  322. tmpRect = new Rectangle();
  323. }
  324. boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
  325. checkIfChildObscuredBySibling());
  326. Rectangle clipBounds = null;
  327. if (checkSiblings) {
  328. clipBounds = sg.getClipBounds();
  329. if (clipBounds == null) {
  330. clipBounds = new Rectangle(0, 0, _bounds.width,
  331. _bounds.height);
  332. }
  333. }
  334. for (; i >= 0 ; i--) {
  335. Component comp = getComponent(i);
  336. if (comp != null && isLightweightComponent(comp) &&
  337. (comp.isVisible() == true)) {
  338. Rectangle cr;
  339. isJComponent = (comp instanceof JComponent);
  340. if(isJComponent) {
  341. cr = tmpRect;
  342. ((JComponent)comp).getBounds(cr);
  343. } else {
  344. cr = comp.getBounds();
  345. }
  346. boolean hitClip =
  347. g.hitClip(cr.x, cr.y, cr.width, cr.height);
  348. if (hitClip) {
  349. if (checkSiblings && i > 0) {
  350. int x = cr.x;
  351. int y = cr.y;
  352. int width = cr.width;
  353. int height = cr.height;
  354. SwingUtilities.computeIntersection
  355. (clipBounds.x, clipBounds.y,
  356. clipBounds.width, clipBounds.height, cr);
  357. if(rectangleIsObscuredBySibling(i, cr.x, cr.y,
  358. cr.width, cr.height)) {
  359. continue;
  360. }
  361. cr.x = x;
  362. cr.y = y;
  363. cr.width = width;
  364. cr.height = height;
  365. }
  366. Graphics cg = SwingGraphics.createSwingGraphics(
  367. sg, cr.x, cr.y, cr.width, cr.height);
  368. cg.setColor(comp.getForeground());
  369. cg.setFont(comp.getFont());
  370. boolean shouldSetFlagBack = false;
  371. try {
  372. if(isJComponent) {
  373. if(getFlag(ANCESTOR_USING_BUFFER)) {
  374. ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,true);
  375. shouldSetFlagBack = true;
  376. }
  377. if(getFlag(IS_PAINTING_TILE)) {
  378. ((JComponent)comp).setFlag(IS_PAINTING_TILE,true);
  379. shouldSetFlagBack = true;
  380. }
  381. if(!printing) {
  382. ((JComponent)comp).paint(cg);
  383. }
  384. else {
  385. if (!getFlag(IS_PRINTING_ALL)) {
  386. comp.print(cg);
  387. }
  388. else {
  389. comp.printAll(cg);
  390. }
  391. }
  392. } else {
  393. if (!printing) {
  394. comp.paint(cg);
  395. }
  396. else {
  397. if (!getFlag(IS_PRINTING_ALL)) {
  398. comp.print(cg);
  399. }
  400. else {
  401. comp.printAll(cg);
  402. }
  403. }
  404. }
  405. } finally {
  406. cg.dispose();
  407. if(shouldSetFlagBack) {
  408. ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,false);
  409. ((JComponent)comp).setFlag(IS_PAINTING_TILE,false);
  410. }
  411. }
  412. }
  413. }
  414. }
  415. }
  416. } finally {
  417. if (sg != null) {
  418. sg.dispose();
  419. }
  420. }
  421. }
  422. /**
  423. * Paint the component's border.
  424. *
  425. * @see #paint
  426. * @see #setBorder
  427. */
  428. protected void paintBorder(Graphics g) {
  429. Border border = getBorder();
  430. if (border != null) {
  431. border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
  432. }
  433. }
  434. /**
  435. * Calls paint(g). Doesn't clear the background but see
  436. * ComponentUI.update() which is called by paintComponent.
  437. *
  438. * @see #paint
  439. * @see #paintComponent
  440. * @see javax.swing.plaf.ComponentUI
  441. */
  442. public void update(Graphics g) {
  443. paint(g);
  444. }
  445. /**
  446. * This method is invoked by Swing to draw components.
  447. * Applications should not invoke paint directly,
  448. * but should instead use the <code>repaint</code> method to
  449. * schedule the component for redrawing.
  450. * <p>
  451. * This method actually delegates the work of painting to three
  452. * protected methods: <code>paintComponent</code>, <code>paintBorder</code>,
  453. * and <code>paintChildren</code>. They're called in the order
  454. * listed to ensure that children appear on top of component itself.
  455. * Generally speaking, the component and its children should not
  456. * paint in the insets area allocated to the border. Subclasses can
  457. * just override this method, as always. A subclass that just
  458. * wants to specialize the UI (look and feel) delegates paint
  459. * method should just override <code>paintComponent</code>.
  460. *
  461. * @see #paintComponent
  462. * @see #paintBorder
  463. * @see #paintChildren
  464. * @see #getComponentGraphics
  465. * @see #repaint
  466. */
  467. public void paint(Graphics g) {
  468. boolean shouldClearPaintFlags = false;
  469. if ((getWidth() <= 0) || (getHeight() <= 0)) {
  470. return;
  471. }
  472. Graphics componentGraphics = getComponentGraphics(g);
  473. Graphics co = SwingGraphics.createSwingGraphics(componentGraphics);
  474. try {
  475. Image offscr = null;
  476. RepaintManager repaintManager = RepaintManager.currentManager(this);
  477. Rectangle clipRect = co.getClipBounds();
  478. int clipX;
  479. int clipY;
  480. int clipW;
  481. int clipH;
  482. if (clipRect == null) {
  483. clipX = clipY = 0;
  484. clipW = _bounds.width;
  485. clipH = _bounds.height;
  486. }
  487. else {
  488. clipX = clipRect.x;
  489. clipY = clipRect.y;
  490. clipW = clipRect.width;
  491. clipH = clipRect.height;
  492. }
  493. if(clipW > getWidth()) {
  494. clipW = getWidth();
  495. }
  496. if(clipH > getHeight()) {
  497. clipH = getHeight();
  498. }
  499. if(getParent() != null && !(getParent() instanceof JComponent)) {
  500. adjustPaintFlags();
  501. shouldClearPaintFlags = true;
  502. }
  503. int bw,bh;
  504. boolean printing = getFlag(IS_PRINTING);
  505. if(!printing && repaintManager.isDoubleBufferingEnabled() &&
  506. !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
  507. (offscr = repaintManager.getOffscreenBuffer
  508. (this,clipW,clipH)) != null &&
  509. (bw = offscr.getWidth(null)) > 0 &&
  510. (bh = offscr.getHeight(null)) > 0) {
  511. int x,y,maxx,maxy;
  512. Graphics sg =
  513. SwingGraphics.createSwingGraphics(offscr.getGraphics());
  514. try {
  515. sg.translate(-clipX,-clipY);
  516. bw = offscr.getWidth(null);
  517. bh = offscr.getHeight(null);
  518. if (bw > clipW) {
  519. bw = clipW;
  520. }
  521. if (bh > clipH) {
  522. bh = clipH;
  523. }
  524. setFlag(ANCESTOR_USING_BUFFER,true);
  525. setFlag(IS_PAINTING_TILE,true);
  526. for(x = 0, maxx = clipW; x < maxx ; x += bw ) {
  527. for(y=0, maxy = clipH; y < maxy ; y += bh) {
  528. if((y+bh) >= maxy && (x+bw) >= maxx)
  529. setFlag(IS_PAINTING_TILE,false);
  530. sg.translate(-x,-y);
  531. sg.setClip(clipX+x,clipY + y,bw,bh);
  532. if(!rectangleIsObscured(clipX,clipY,bw,bh)) {
  533. paintComponent(sg);
  534. paintBorder(sg);
  535. }
  536. paintChildren(sg);
  537. co.drawImage(offscr,clipX + x,clipY + y,this);
  538. sg.translate(x,y);
  539. }
  540. }
  541. } finally {
  542. setFlag(ANCESTOR_USING_BUFFER,false);
  543. setFlag(IS_PAINTING_TILE,false);
  544. sg.dispose();
  545. }
  546. } else {
  547. if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
  548. paintComponent(co);
  549. paintBorder(co);
  550. }
  551. paintChildren(co);
  552. }
  553. } finally {
  554. co.dispose();
  555. if(shouldClearPaintFlags) {
  556. setFlag(ANCESTOR_USING_BUFFER,false);
  557. setFlag(IS_PAINTING_TILE,false);
  558. setFlag(IS_PRINTING,false);
  559. setFlag(IS_PRINTING_ALL,false);
  560. }
  561. }
  562. }
  563. private void adjustPaintFlags() {
  564. JComponent jparent = null;
  565. Container parent;
  566. for(parent = getParent() ; parent != null ; parent =
  567. parent.getParent()) {
  568. if(parent instanceof JComponent) {
  569. jparent = (JComponent) parent;
  570. if(jparent.getFlag(ANCESTOR_USING_BUFFER))
  571. setFlag(ANCESTOR_USING_BUFFER, true);
  572. if(jparent.getFlag(IS_PAINTING_TILE))
  573. setFlag(IS_PAINTING_TILE, true);
  574. if(jparent.getFlag(IS_PRINTING))
  575. setFlag(IS_PRINTING, true);
  576. if(jparent.getFlag(IS_PRINTING_ALL))
  577. setFlag(IS_PRINTING_ALL, true);
  578. break;
  579. }
  580. }
  581. }
  582. public void printAll(Graphics g) {
  583. setFlag(IS_PRINTING_ALL, true);
  584. try {
  585. print(g);
  586. }
  587. finally {
  588. setFlag(IS_PRINTING_ALL, false);
  589. }
  590. }
  591. public void print(Graphics g) {
  592. setFlag(IS_PRINTING, true);
  593. try {
  594. paint(g);
  595. }
  596. finally {
  597. setFlag(IS_PRINTING, false);
  598. }
  599. }
  600. /**
  601. * Returns true if the receiving component is currently painting a tile.
  602. * If this method returns true, paint will be called again for another
  603. * tile. This method returns false if you are not painting a tile or
  604. * if the last tile is painted.
  605. * Use this method to keep some state you might need between tiles.
  606. */
  607. public boolean isPaintingTile() {
  608. return getFlag(IS_PAINTING_TILE);
  609. }
  610. /**
  611. * Override this method and return true if your component is the root of
  612. * of a component tree with its own focus cycle.
  613. */
  614. public boolean isFocusCycleRoot() {
  615. return false;
  616. }
  617. /**
  618. * Override this method and return true if your JComponent manages focus.
  619. * If your component manages focus, the focus manager will handle your
  620. * component's children. All key event will be sent to your key listener
  621. * including TAB and SHIFT+TAB. CONTROL + TAB and CONTROL + SHIFT + TAB
  622. * will move the focus to the next / previous component.
  623. */
  624. public boolean isManagingFocus() {
  625. return false;
  626. }
  627. /**
  628. * Specifies the next component to get the focus after this one,
  629. * for example, when the tab key is pressed. Invoke this method
  630. * to override the default focus-change sequence.
  631. * @beaninfo
  632. * expert: true
  633. * description: The next component to get focus after this one.
  634. */
  635. public void setNextFocusableComponent(Component aComponent) {
  636. putClientProperty(NEXT_FOCUS,aComponent);
  637. }
  638. /**
  639. * Return the next focusable component or null if the focus manager
  640. * should choose the next focusable component automatically
  641. */
  642. public Component getNextFocusableComponent() {
  643. return (Component) getClientProperty(NEXT_FOCUS);
  644. }
  645. /**
  646. * Set whether the receiving component can obtain the focus by
  647. * calling requestFocus. The default value is true.
  648. * Note: Setting this property to false will not prevent the focus
  649. * manager from setting the focus to this component, it will prevent
  650. * the component from getting the focus when the focus is requested
  651. * explicitly. Override isFocusTraversable and return false if the
  652. * component should never get the focus.
  653. * @beaninfo
  654. * expert: true
  655. * description: Whether the component can obtain the focus by calling requestFocus.
  656. */
  657. public void setRequestFocusEnabled(boolean aFlag) {
  658. setFlag(REQUEST_FOCUS_DISABLED,(aFlag ? false:true));
  659. }
  660. /** Return whether the receiving component can obtain the focus by
  661. * calling requestFocus
  662. * @see #setRequestFocusEnabled
  663. */
  664. public boolean isRequestFocusEnabled() {
  665. return (getFlag(REQUEST_FOCUS_DISABLED) ? false : true);
  666. }
  667. /** Set focus on the receiving component if isRequestFocusEnabled returns true **/
  668. public void requestFocus() {
  669. /* someone other then the focus manager is requesting focus,
  670. so we clear the focus manager's idea of focus history */
  671. FocusManager focusManager = FocusManager.getCurrentManager();
  672. if (focusManager instanceof DefaultFocusManager)
  673. ((DefaultFocusManager)focusManager).clearHistory();
  674. if(isRequestFocusEnabled()) {
  675. super.requestFocus();
  676. }
  677. }
  678. /** Set the focus on the receiving component. This method is for focus managers, you
  679. * rarely want to call this method, use requestFocus() enstead.
  680. */
  681. public void grabFocus() {
  682. super.requestFocus();
  683. }
  684. /**
  685. * Set the preferred size of the receiving component.
  686. * if <code>preferredSize</code> is null, the UI will
  687. * be asked for the preferred size
  688. * @beaninfo
  689. * preferred: true
  690. * bound: true
  691. * description: The preferred size of the component.
  692. */
  693. public void setPreferredSize(Dimension preferredSize) {
  694. Dimension old = this.preferredSize;
  695. this.preferredSize = preferredSize;
  696. firePropertyChange("preferredSize", old, preferredSize);
  697. }
  698. /**
  699. * If the preferredSize has been set to a non-null value
  700. * just return it. If the UI delegates getPreferredSize()
  701. * method returns a non null then value return that, otherwise
  702. * defer to the components layout manager.
  703. *
  704. * @return the value of the preferredSize property.
  705. * @see #setPreferredSize
  706. */
  707. public Dimension getPreferredSize() {
  708. if (preferredSize != null) {
  709. return preferredSize;
  710. }
  711. Dimension size = null;
  712. if (ui != null) {
  713. size = ui.getPreferredSize(this);
  714. }
  715. return (size != null) ? size : super.getPreferredSize();
  716. }
  717. /**
  718. * Sets the maximumSize of this component to a constant
  719. * value. Subsequent calls to getMaximumSize will always
  720. * return this value, the components UI will not be asked
  721. * to compute it. Setting the maximumSize to null
  722. * restores the default behavior.
  723. *
  724. * @see #getMaximumSize
  725. * @beaninfo
  726. * bound: true
  727. * description: The maximum size of the component.
  728. */
  729. public void setMaximumSize(Dimension maximumSize) {
  730. Dimension old = this.maximumSize;
  731. this.maximumSize = maximumSize;
  732. firePropertyChange("maximumSize", old, maximumSize);
  733. }
  734. /**
  735. * If the maximumSize has been set to a non-null value
  736. * just return it. If the UI delegates getMaximumSize()
  737. * method returns a non null value then return that, otherwise
  738. * defer to the components layout manager.
  739. *
  740. * @return the value of the maximumSize property.
  741. * @see #setMaximumSize
  742. */
  743. public Dimension getMaximumSize() {
  744. if (maximumSize != null) {
  745. return maximumSize;
  746. }
  747. Dimension size = null;
  748. if (ui != null) {
  749. size = ui.getMaximumSize(this);
  750. }
  751. return (size != null) ? size : super.getMaximumSize();
  752. }
  753. /**
  754. * Sets the minimumSize of this component to a constant
  755. * value. Subsequent calls to getMinimumSize will always
  756. * return this value, the components UI will not be asked
  757. * to compute it. Setting the minimumSize to null
  758. * restores the default behavior.
  759. *
  760. * @see #getMinimumSize
  761. * @beaninfo
  762. * bound: true
  763. * description: The minimum size of the component.
  764. */
  765. public void setMinimumSize(Dimension minimumSize) {
  766. Dimension old = this.minimumSize;
  767. this.minimumSize = minimumSize;
  768. firePropertyChange("minimumSize", old, minimumSize);
  769. }
  770. /**
  771. * If the minimumSize has been set to a non-null value
  772. * just return it. If the UI delegates getMinimumSize()
  773. * method returns a non null value then return that, otherwise
  774. * defer to the components layout manager.
  775. *
  776. * @return the value of the minimumSize property.
  777. * @see #setMinimumSize
  778. */
  779. public Dimension getMinimumSize() {
  780. if (minimumSize != null) {
  781. return minimumSize;
  782. }
  783. Dimension size = null;
  784. if (ui != null) {
  785. size = ui.getMinimumSize(this);
  786. }
  787. return (size != null) ? size : super.getMinimumSize();
  788. }
  789. /**
  790. * Give the UI delegate an opportunity to define the precise
  791. * shape of this component for the sake of mouse processing.
  792. *
  793. * @return true if this component logically contains x,y.
  794. * @see java.awt.Component#contains(int, int)
  795. */
  796. public boolean contains(int x, int y) {
  797. return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
  798. }
  799. /**
  800. * Sets the border of this component. The Border object is
  801. * responsible for defining the insets for the component
  802. * (overriding any insets set directly on the component) and
  803. * for optionally rendering any border decorations within the
  804. * bounds of those insets. Borders should be used (rather
  805. * than insets) for creating both decorative and non-decorative
  806. * (e.g. margins and padding) regions for a swing component.
  807. * Compound borders can be used to nest multiple borders within a
  808. * single component.
  809. * <p>
  810. * This is a bound property.
  811. *
  812. * @param border the border to be rendered for this component
  813. * @see Border
  814. * @see CompoundBorder
  815. * @beaninfo
  816. * bound: true
  817. * preferred: true
  818. * attribute: visualUpdate true
  819. * description: The component's border.
  820. */
  821. public void setBorder(Border border) {
  822. Border oldBorder = this.border;
  823. this.border = border;
  824. firePropertyChange("border", oldBorder, border);
  825. if (border != oldBorder) {
  826. if (border == null || oldBorder == null ||
  827. !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
  828. revalidate();
  829. }
  830. repaint();
  831. }
  832. }
  833. /**
  834. * Returns the border of this component or null if no border is
  835. * currently set.
  836. *
  837. * @return the border object for this component
  838. * @see #setBorder
  839. */
  840. public Border getBorder() {
  841. return border;
  842. }
  843. /**
  844. * If a border has been set on this component, returns the
  845. * border's insets, else calls super.getInsets.
  846. *
  847. * @return the value of the insets property.
  848. * @see #setBorder
  849. */
  850. public Insets getInsets() {
  851. if (border != null) {
  852. return border.getBorderInsets(this);
  853. }
  854. return super.getInsets();
  855. }
  856. /**
  857. * Returns an Insets object containing this component's inset
  858. * values. The passed-in Insets object will be reused if possible.
  859. * Calling methods cannot assume that the same object will be returned,
  860. * however. All existing values within this object are overwritten.
  861. *
  862. * @param insets the Insets object which can be reused.
  863. * @see #getInsets
  864. * @beaninfo
  865. * expert: true
  866. */
  867. public Insets getInsets(Insets insets) {
  868. if (border != null) {
  869. if (border instanceof AbstractBorder) {
  870. return ((AbstractBorder)border).getBorderInsets(this, insets);
  871. } else {
  872. // Can't reuse border insets because the Border interface
  873. // can't be enhanced.
  874. return border.getBorderInsets(this);
  875. }
  876. } else {
  877. // super.getInsets() always returns an Insets object with
  878. // all of its value zeroed. No need for a new object here.
  879. insets.left = insets.top = insets.right = insets.bottom = 0;
  880. return insets;
  881. }
  882. }
  883. /**
  884. * Overrides <code>Container.getAlignmentY</code> to return
  885. * the horizontal alignment.
  886. *
  887. * @return the value of the alignmentY property.
  888. * @see #setAlignmentY
  889. * @see java.awt.Component#getAlignmentY
  890. */
  891. public float getAlignmentY() {
  892. return (alignmentY != null) ? alignmentY.floatValue() : super.getAlignmentY();
  893. }
  894. /**
  895. * Set the the horizontal alignment.
  896. *
  897. * @see #getAlignmentY
  898. * @beaninfo
  899. * description: The preferred vertical alignment of the component
  900. */
  901. public void setAlignmentY(float alignmentY) {
  902. this.alignmentY = new Float(alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY);
  903. }
  904. /**
  905. * Overrides <code>Container.getAlignmentX</code> to return
  906. * the vertical alignment.
  907. *
  908. * @return the value of the alignmentX property.
  909. * @see #setAlignmentX
  910. * @see java.awt.Component#getAlignmentX
  911. */
  912. public float getAlignmentX() {
  913. return (alignmentX != null) ? alignmentX.floatValue() : super.getAlignmentX();
  914. }
  915. /**
  916. * Set the the vertical alignment.
  917. *
  918. * @see #getAlignmentX
  919. * @beaninfo
  920. * description: The preferred horizontal alignment of the component
  921. */
  922. public void setAlignmentX(float alignmentX) {
  923. this.alignmentX = new Float(alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX);
  924. }
  925. /**
  926. * Returns this component's graphics context, which lets you draw
  927. * on a component. Use this method get a Graphics object and
  928. * then invoke oeprations on that object to draw on the component.
  929. */
  930. public Graphics getGraphics() {
  931. if (shouldDebugGraphics() != 0) {
  932. DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
  933. this);
  934. return graphics;
  935. }
  936. return super.getGraphics();
  937. }
  938. /** Enables or disables diagnostic information about every graphics
  939. * operation performed within the component or one of its children. The
  940. * value of <b>debugOptions</b> determines how the component should
  941. * display this information:
  942. * <ul>
  943. * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
  944. * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
  945. * times.
  946. * <li>DebugGraphics.BUFFERED_OPTION - creates an ExternalWindow that
  947. * displays the operations performed on the View's offscreen buffer.
  948. * </ul>
  949. * <b>debug</b> is bitwise OR'd into the current value.
  950. * DebugGraphics.NONE_OPTION disables debugging.
  951. * A value of 0 causes no changes to the debugging options.
  952. * @beaninfo
  953. * preferred: true
  954. * description: Diagnostic options for graphics operations.
  955. */
  956. public void setDebugGraphicsOptions(int debugOptions) {
  957. DebugGraphics.setDebugOptions(this, debugOptions);
  958. }
  959. /** Returns the state of graphics debugging.
  960. * @see #setDebugGraphicsOptions
  961. */
  962. public int getDebugGraphicsOptions() {
  963. return DebugGraphics.getDebugOptions(this);
  964. }
  965. /**
  966. * Returns <b>true</b> if debug information is enabled for this JComponent
  967. * or one if its parents.
  968. */
  969. int shouldDebugGraphics() {
  970. return DebugGraphics.shouldComponentDebug(this);
  971. }
  972. /**
  973. * Register a new keyboard action.
  974. * <b>anAction</b> will be invoked if a key event matching <b>aKeyStroke</b> occurs
  975. * and <b>aCondition</b> is verified. The KeyStroke object defines a
  976. * particular combination of a keyboard key and one or more modifiers
  977. * (alt, shift, ctrl, meta).
  978. * <p>
  979. * The <b>aCommand</b> will be set in the delivered event if specified.
  980. * <p>
  981. * The Condition can be one of:
  982. * <blockquote>
  983. * <DL>
  984. * <DT>WHEN_FOCUSED
  985. * <DD>The action will be invoked only when the keystroke occurs
  986. * while the component has the focus.
  987. * <DT>WHEN_IN_FOCUSED_WINDOW
  988. * <DD>The action will be invoked when the keystroke occurs while
  989. * the component has the focus or if the component is in the
  990. * window that has the focus. Note that the component need not
  991. * be an immediate descendent of the window -- it can be
  992. * anywhere in the window's containment hierarchy. In other
  993. * words, whenever <em>any</em> component in the window has the focus,
  994. * the action registered with this component is invoked.
  995. * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
  996. * <DD>The action will be invoked when the keystroke occurs while the
  997. * component has the focus or if the component is an ancestor of
  998. * the component that has the focus.
  999. * </DL>
  1000. * </blockquote>
  1001. * <p>
  1002. * The combination of keystrokes and conditions lets you define high
  1003. * level (semantic) action events for a specified keystroke+modifier
  1004. * combination (using the KeyStroke class) and direct to a parent or
  1005. * child of a component that has the focus, or to the component itself.
  1006. * In other words, in any hierarchical structure of components, an
  1007. * arbitrary key-combination can be immediately directed to the
  1008. * appropriate component in the hierarchy, and cause a specific method
  1009. * to be invoked (usually by way of adapter objects).
  1010. * <p>
  1011. * If an action has already been registered for the receiving
  1012. * container, with the same charCode and the same modifiers,
  1013. * <b>anAction</b> will replace the action.
  1014. *
  1015. * @see KeyStroke
  1016. */
  1017. public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
  1018. Hashtable bindings;
  1019. boolean firstKeyboardAction = false;
  1020. synchronized(this) {
  1021. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1022. if(bindings == null) {
  1023. bindings = new Hashtable();
  1024. putClientProperty(KEYBOARD_BINDINGS_KEY,bindings);
  1025. firstKeyboardAction = true;
  1026. }
  1027. }
  1028. synchronized(bindings) {
  1029. bindings.put(aKeyStroke,new KeyboardBinding(anAction,aCommand,aKeyStroke,aCondition));
  1030. }
  1031. /* This is the first time a keyboard binding is added, let's order
  1032. * keyboard events...
  1033. * ALERT: we need to enable events. Adding a listener will not work since
  1034. * we want our listener to be after all other listeners.
  1035. */
  1036. if(firstKeyboardAction) {
  1037. enableEvents(AWTEvent.KEY_EVENT_MASK);
  1038. }
  1039. if (getParent() != null && aCondition == WHEN_IN_FOCUSED_WINDOW) {
  1040. registerWithKeyboardManager(aKeyStroke);
  1041. }
  1042. }
  1043. void registerWithKeyboardManager(KeyStroke aKeyStroke) {
  1044. KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke, this);
  1045. }
  1046. void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
  1047. KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke, this);
  1048. }
  1049. /**
  1050. * Calls registerKeyboardAction(ActionListener,String,KeyStroke,condition) with a null command.
  1051. */
  1052. public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
  1053. registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
  1054. }
  1055. private Hashtable keyboardBindings() {
  1056. Hashtable bindings;
  1057. synchronized(this) {
  1058. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1059. }
  1060. return bindings;
  1061. }
  1062. /**
  1063. * Unregister a keyboard action.
  1064. *
  1065. * @see #registerKeyboardAction
  1066. */
  1067. public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
  1068. Hashtable bindings = keyboardBindings();
  1069. KeyboardBinding aBinding;
  1070. if(bindings == null)
  1071. return;
  1072. synchronized(bindings) {
  1073. aBinding = (KeyboardBinding)bindings.remove(aKeyStroke);
  1074. }
  1075. if(bindings.size() == 0) {
  1076. /** ALERT. We need a way to disable keyboard events only if there is no
  1077. * keyboard listener.
  1078. */
  1079. }
  1080. if ( aBinding != null && aBinding.condition == WHEN_IN_FOCUSED_WINDOW) {
  1081. unregisterWithKeyboardManager(aKeyStroke);
  1082. }
  1083. }
  1084. /**
  1085. * Return the KeyStrokes that will initiate registered actions.
  1086. *
  1087. * @return an array of KeyStroke objects
  1088. * @see #registerKeyboardAction
  1089. */
  1090. public KeyStroke[] getRegisteredKeyStrokes() {
  1091. Hashtable bindings = keyboardBindings();
  1092. KeyStroke result[];
  1093. int i;
  1094. Enumeration keys;
  1095. if(bindings == null)
  1096. return new KeyStroke[0];
  1097. synchronized(bindings) {
  1098. result = new KeyStroke[bindings.size()];
  1099. i = 0;
  1100. keys = bindings.keys();
  1101. while(keys.hasMoreElements())
  1102. result[i++] = (KeyStroke) keys.nextElement();
  1103. }
  1104. return result;
  1105. }
  1106. /**
  1107. * Return the condition that determines whether a registered action
  1108. * occurs in response to the specified keystroke.
  1109. *
  1110. * @return the action-keystroke condition
  1111. * @see #registerKeyboardAction
  1112. */
  1113. public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
  1114. Hashtable bindings = keyboardBindings();
  1115. if(bindings == null)
  1116. return UNDEFINED_CONDITION;
  1117. synchronized(bindings) {
  1118. KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1119. if(kb != null) {
  1120. return kb.getCondition();
  1121. }
  1122. }
  1123. return UNDEFINED_CONDITION;
  1124. }
  1125. /**
  1126. * Return the object that will perform the action registered for a
  1127. * given keystroke.
  1128. *
  1129. * @return the ActionListener object invoked when the keystroke occurs
  1130. * @see #registerKeyboardAction
  1131. */
  1132. public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
  1133. Hashtable bindings = keyboardBindings();
  1134. if(bindings == null)
  1135. return null;
  1136. synchronized(bindings) {
  1137. KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1138. if(kb != null) {
  1139. return kb.getAction();
  1140. }
  1141. }
  1142. return null;
  1143. }
  1144. /**
  1145. * Unregister all keyboard actions
  1146. *
  1147. * @see #registerKeyboardAction
  1148. */
  1149. public void resetKeyboardActions() {
  1150. synchronized(this) {
  1151. Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1152. if(bindings != null) {
  1153. bindings.clear();
  1154. }
  1155. }
  1156. /* ALERT. We need a way to disable keyboard events only if there is no
  1157. * keyboard listener.
  1158. */
  1159. }
  1160. /**
  1161. * Request the focus for the component that should have the focus
  1162. * by default. The default implementation will recursively request
  1163. * the focus on the first component that is focus-traversable.
  1164. *
  1165. * @return false if the focus has not been set, otherwise
  1166. * return true
  1167. */
  1168. public boolean requestDefaultFocus() {
  1169. Component ca[] = getComponents();
  1170. int i;
  1171. for(i=0 ; i < ca.length ; i++) {
  1172. if(ca[i].isFocusTraversable()) {
  1173. if(ca[i] instanceof JComponent) {
  1174. ((JComponent)ca[i]).grabFocus();
  1175. } else {
  1176. ca[i].requestFocus();
  1177. }
  1178. return true;
  1179. }
  1180. if(ca[i] instanceof JComponent && !((JComponent)ca[i]).isManagingFocus()) {
  1181. if(((JComponent)(ca[i])).requestDefaultFocus()) {
  1182. return true;
  1183. }
  1184. }
  1185. }
  1186. return false;
  1187. }
  1188. /**
  1189. * Makes the component visible or invisible.
  1190. * Overrides <code>Component.setVisible</code>.
  1191. *
  1192. * @param aFlag true to make the component visible
  1193. *
  1194. * @beaninfo
  1195. * attribute: visualUpdate true
  1196. */
  1197. public void setVisible(boolean aFlag) {
  1198. if(aFlag != isVisible()) {
  1199. super.setVisible(aFlag);
  1200. Container parent = getParent();
  1201. if(parent != null) {
  1202. Rectangle r = getBounds();
  1203. parent.repaint(r.x,r.y,r.width,r.height);
  1204. }
  1205. // Some (all should) LayoutManagers do not consider components
  1206. // that are not visible. As such we need to revalidate when the
  1207. // visible bit changes.
  1208. revalidate();
  1209. if (accessibleContext != null) {
  1210. if (aFlag) {
  1211. accessibleContext.firePropertyChange(
  1212. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1213. null, AccessibleState.VISIBLE);
  1214. } else {
  1215. accessibleContext.firePropertyChange(
  1216. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1217. AccessibleState.VISIBLE, null);
  1218. }
  1219. }
  1220. }
  1221. }
  1222. /**
  1223. * Sets whether or not this component is enabled.
  1224. * A component which is enabled may respond to user input,
  1225. * while a component which is not enabled cannot respond to
  1226. * user input. Some components may alter their visual
  1227. * representation when they are disabled in order to
  1228. * provide feedback to the user that they cannot take input.
  1229. *
  1230. * @see java.awt.Component#isEnabled
  1231. *
  1232. * @beaninfo
  1233. * preferred: true
  1234. * bound: true
  1235. * attribute: visualUpdate true
  1236. * description: The enabled state of the component
  1237. */
  1238. public void setEnabled(boolean enabled) {
  1239. boolean oldEnabled = isEnabled();
  1240. super.setEnabled(enabled);
  1241. if (!enabled && hasFocus()) {
  1242. FocusManager.getCurrentManager().focusPreviousComponent(this);
  1243. }
  1244. firePropertyChange("enabled", oldEnabled, enabled);
  1245. if (enabled != oldEnabled) {
  1246. repaint();
  1247. }
  1248. }
  1249. /**
  1250. * Sets the foreground color of this component.
  1251. *
  1252. * @see java.awt.Component#getForeground
  1253. *
  1254. * @beaninfo
  1255. * preferred: true
  1256. * bound: true
  1257. * attribute: visualUpdate true
  1258. * description: The foreground color of the component.
  1259. */
  1260. public void setForeground(Color fg) {
  1261. Color oldFg = getForeground();
  1262. super.setForeground(fg);
  1263. if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) {
  1264. // foreground already bound in AWT1.2
  1265. if (!SwingUtilities.is1dot2) {
  1266. firePropertyChange("foreground", oldFg, fg);
  1267. }
  1268. repaint();
  1269. }
  1270. }
  1271. /**
  1272. * Sets the background color of this component.
  1273. *
  1274. * @see java.awt.Component#getBackground
  1275. *
  1276. * @beaninfo
  1277. * preferred: true
  1278. * bound: true
  1279. * attribute: visualUpdate true
  1280. * description: The background color of the component.
  1281. */
  1282. public void setBackground(Color bg) {
  1283. Color oldBg = getBackground();
  1284. super.setBackground(bg);
  1285. if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg.equals(oldBg))) {
  1286. // background already bound in AWT1.2
  1287. if (!SwingUtilities.is1dot2) {
  1288. firePropertyChange("background", oldBg, bg);
  1289. }
  1290. repaint();
  1291. }
  1292. }
  1293. /**
  1294. * Sets the font for this component.
  1295. *
  1296. * @see java.awt.Component#getFont
  1297. *
  1298. * @beaninfo
  1299. * preferred: true
  1300. * bound: true
  1301. * attribute: visualUpdate true
  1302. * description: The font for the component.
  1303. */
  1304. public void setFont(Font font) {
  1305. Font oldFont = getFont();
  1306. super.setFont(font);
  1307. // font already bound in AWT1.2
  1308. if (!SwingUtilities.is1dot2) {
  1309. firePropertyChange("font", oldFont, font);
  1310. }
  1311. if (font != oldFont) {
  1312. revalidate();
  1313. repaint();
  1314. }
  1315. }
  1316. /**
  1317. * Identifies whether or not this component can receive the focus.
  1318. * A disabled button, for example, would return false.
  1319. *
  1320. * @return true if this component can receive the focus
  1321. */
  1322. public boolean isFocusTraversable() {
  1323. boolean result = false;
  1324. Hashtable bindings;
  1325. synchronized(this) {
  1326. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1327. }
  1328. if(bindings != null) {
  1329. synchronized(bindings) {
  1330. Enumeration keys = bindings.keys();
  1331. KeyboardBinding b;
  1332. while(keys.hasMoreElements()) {
  1333. b = (KeyboardBinding) bindings.get(keys.nextElement());
  1334. if(b.getCondition() == WHEN_FOCUSED) {
  1335. result = true;
  1336. break;
  1337. }
  1338. }
  1339. }
  1340. }
  1341. return result;
  1342. }
  1343. protected void processFocusEvent(FocusEvent e) {
  1344. switch(e.getID()) {
  1345. case FocusEvent.FOCUS_GAINED:
  1346. setFlag(HAS_FOCUS, true);
  1347. break;
  1348. case FocusEvent.FOCUS_LOST:
  1349. setFlag(HAS_FOCUS, false);
  1350. break;
  1351. }
  1352. // Call super *after* setting flag, in case listener calls paint.
  1353. super.processFocusEvent(e);
  1354. }
  1355. /**
  1356. * Process any key events that the component itself
  1357. * recognizes. This will be called after the focus
  1358. * manager and any interested listeners have been
  1359. * given a chance to steal away the event. This
  1360. * method will only be called is the event has not
  1361. * yet been consumed. This method is called prior
  1362. * to the keyboard UI logic.
  1363. * <p>
  1364. * This is implemented to do nothing. Subclasses would
  1365. * normally override this method if they process some
  1366. * key events themselves. If the event is processed,
  1367. * it should be consumed.
  1368. */
  1369. protected void processComponentKeyEvent(KeyEvent e) {
  1370. }
  1371. /** Override processKeyEvent to process events **/
  1372. protected void processKeyEvent(KeyEvent e) {
  1373. // focus manager gets to steal the event if it wants it.
  1374. boolean result;
  1375. boolean shouldProcessKey = false;
  1376. if(FocusManager.isFocusManagerEnabled()) {
  1377. FocusManager focusManager = FocusManager.getCurrentManager();
  1378. focusManager.processKeyEvent(this,e);
  1379. if(e.isConsumed()) {
  1380. return;
  1381. }
  1382. }
  1383. // This gives the key event listeners a crack at the event
  1384. super.processKeyEvent(e);
  1385. // give the component itself a crack at the event
  1386. if (! e.isConsumed()) {
  1387. processComponentKeyEvent(e);
  1388. }
  1389. if(e.getID() == KeyEvent.KEY_PRESSED) {
  1390. shouldProcessKey = true;
  1391. if(!KeyboardState.keyIsPressed(e.getKeyCode()))
  1392. KeyboardState.registerKeyPressed(e.getKeyCode());
  1393. } else if(e.getID() == KeyEvent.KEY_RELEASED) {
  1394. if(KeyboardState.keyIsPressed(e.getKeyCode())) {
  1395. shouldProcessKey = true;
  1396. KeyboardState.registerKeyReleased(e.getKeyCode());
  1397. }
  1398. } else if(e.getID() == KeyEvent.KEY_TYPED) {
  1399. shouldProcessKey = true;
  1400. }
  1401. if(e.isConsumed()) {
  1402. return;
  1403. }
  1404. // (PENDING) Hania & Steve - take out this block? Do we need to do this pressed stuff?
  1405. // And, shouldProcessKey, do we need it?
  1406. if(shouldProcessKey && e.getID() == KeyEvent.KEY_PRESSED) {
  1407. result = processKeyBindings(e,true);
  1408. if(result)
  1409. e.consume();
  1410. } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_RELEASED) {
  1411. result = processKeyBindings(e,false);
  1412. if(result) {
  1413. e.consume();
  1414. }
  1415. } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_TYPED) {
  1416. result = processKeyBindings(e,false);
  1417. if(result) {
  1418. e.consume();
  1419. }
  1420. }
  1421. }
  1422. KeyboardBinding bindingForKeyStroke(KeyStroke ks,int condition) {
  1423. Hashtable bindings;
  1424. KeyboardBinding b;
  1425. KeyboardBinding result = null;
  1426. // synchronized(this) {
  1427. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1428. // }
  1429. if(bindings != null) {
  1430. // synchronized(bindings) {
  1431. b = (KeyboardBinding) bindings.get(ks);
  1432. // System.out.println("Bindings are " + bindings);
  1433. if(b != null) {
  1434. ActionListener action = b.getAction();
  1435. if((action instanceof Action) && !(((Action)action).isEnabled()))
  1436. action = null;
  1437. if(action != null) {
  1438. switch(b.getCondition()) {
  1439. case WHEN_FOCUSED:
  1440. if(condition == WHEN_FOCUSED)
  1441. result = b;
  1442. break;
  1443. case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
  1444. if(condition == WHEN_FOCUSED ||
  1445. condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1446. result = b;
  1447. break;
  1448. case WHEN_IN_FOCUSED_WINDOW:
  1449. if(condition == WHEN_FOCUSED ||
  1450. condition == WHEN_IN_FOCUSED_WINDOW ||
  1451. condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1452. result = b;
  1453. break;
  1454. }
  1455. }
  1456. }
  1457. // }
  1458. }
  1459. return result;
  1460. }
  1461. boolean processKeyBinding(KeyEvent e,int condition,boolean pressed) {
  1462. Hashtable bindings;
  1463. int i,c;
  1464. boolean onKeyRelease = (pressed?false:true);
  1465. KeyboardBinding binding = null;
  1466. KeyStroke ks;
  1467. if(isEnabled()) {
  1468. if(e.getID() == KeyEvent.KEY_TYPED) {
  1469. binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyChar())),condition);
  1470. } else {
  1471. binding = bindingForKeyStroke((ks=KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
  1472. onKeyRelease)), condition);
  1473. }
  1474. //System.out.println("e=" + e + "ks is " + ks);
  1475. if(binding != null) {
  1476. ActionListener listener = binding.getAction();
  1477. if(listener != null) {
  1478. listener.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,binding.getCommand()));
  1479. return true;
  1480. }
  1481. }
  1482. }
  1483. return false;
  1484. }
  1485. boolean processKeyBindings(KeyEvent e,boolean pressed) {
  1486. Container parent;
  1487. /* Do we have a key binding for e? */
  1488. if(processKeyBinding(e,WHEN_FOCUSED,pressed))
  1489. return true;
  1490. /* We have no key binding. Let's try the path from our parent to the window excluded
  1491. * We store the path components so we can avoid asking the same component twice.
  1492. */
  1493. parent = this.getParent();
  1494. while(parent != null && !(parent instanceof Window) && !(parent instanceof Applet) && !(parent instanceof JInternalFrame)) {
  1495. // maybe generalize from JInternalFrame (like isFocusCycleRoot).
  1496. if(parent instanceof JComponent) {
  1497. if(((JComponent)parent).processKeyBinding(e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,pressed))
  1498. return true;
  1499. }
  1500. parent = parent.getParent();
  1501. }
  1502. /* No components between the focused component and the window is actually interested
  1503. * by the key event. Let's try the other JComponent in this window.
  1504. */
  1505. if(parent != null) {
  1506. return JComponent.processKeyBindingsForAllComponents(e,parent,pressed);
  1507. }
  1508. return false;
  1509. }
  1510. static boolean processKeyBindingsForAllComponents(KeyEvent e,Container container, boolean pressed) {
  1511. return KeyboardManager.getCurrentManager().fireKeyboardAction(e, pressed, container);
  1512. /* int i;
  1513. Component subComponents[];
  1514. if(!container.isVisible() || !container.isEnabled()) {
  1515. return false;
  1516. }
  1517. if(container instanceof JComponent && !alreadyProcessed.contains(container)) {
  1518. if(((JComponent)container).processKeyBinding(e,WHEN_IN_FOCUSED_WINDOW,pressed))
  1519. return true;
  1520. }
  1521. subComponents = container.getComponents();
  1522. for(i=0 ; i < subComponents.length ; i++) {
  1523. if(subComponents[i].isVisible() && subComponents[i].isEnabled()) {
  1524. if(subComponents[i] instanceof Container) {
  1525. if(processKeyBindingsForAllComponents(e,(Container)subComponents[i],alreadyProcessed,pressed))
  1526. return true;
  1527. }
  1528. }
  1529. }
  1530. return false;*/
  1531. }
  1532. /**
  1533. * Registers the text to display in a tool tip.
  1534. * The text displays when the cursor lingers over the component.
  1535. * <p>
  1536. * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/tooltip.html">How to Use Tool Tips</a>
  1537. * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  1538. * for further documentation.
  1539. *
  1540. * @param text The string to display. If the text is null,
  1541. * the tool tip is turned off for this component.
  1542. * @see #TOOL_TIP_TEXT_KEY
  1543. * @beaninfo
  1544. * preferred: true
  1545. * description: The text to display in a tool tip.
  1546. */
  1547. public void setToolTipText(String text) {
  1548. putClientProperty(TOOL_TIP_TEXT_KEY, text);
  1549. ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  1550. if (text != null) {
  1551. toolTipManager.registerComponent(this);
  1552. } else {
  1553. toolTipManager.unregisterComponent(this);
  1554. }
  1555. }
  1556. /**
  1557. * Return the tooltip string that has been set with setToolTipText()
  1558. *
  1559. * @return the text of the tool tip
  1560. * @see #TOOL_TIP_TEXT_KEY
  1561. */
  1562. public String getToolTipText() {
  1563. return (String)getClientProperty(TOOL_TIP_TEXT_KEY);
  1564. }
  1565. /**
  1566. * Returns the string to be used as the tooltip for <i>event</i>. By default
  1567. * this returns any string set using setToolTipText(). If a component provides
  1568. * more extensize API to support differing tooltips at different locations,
  1569. * this method should be overridden.
  1570. */
  1571. public String getToolTipText(MouseEvent event) {
  1572. return getToolTipText();
  1573. }
  1574. /**
  1575. * Return the tooltip location in the receiving component coordinate system
  1576. * If null is returned, Swing will choose a location.
  1577. * The default implementation returns null.
  1578. *
  1579. * @param event the MouseEvent that caused the ToolTipManager to
  1580. * show the tooltip.
  1581. */
  1582. public Point getToolTipLocation(MouseEvent event) {
  1583. return null;
  1584. }
  1585. /**
  1586. * Returns the instance of JToolTip that should be used to display the tooltip.
  1587. * Components typically would not override this method, but it can be used to
  1588. * cause different tooltips to be displayed differently.
  1589. */
  1590. public JToolTip createToolTip() {
  1591. JToolTip tip = new JToolTip();
  1592. tip.setComponent(this);
  1593. return tip;
  1594. }
  1595. /**
  1596. * Forwards the <b>scrollRectToVisible()</b> message to the JComponent's
  1597. * parent. Components that can service the request, such as a JViewport,
  1598. * override this method and perform the scrolling.
  1599. *
  1600. * @see JViewport
  1601. */
  1602. public void scrollRectToVisible(Rectangle aRect) {
  1603. Container parent;
  1604. int dx = getX(), dy = getY();
  1605. for (parent = getParent();
  1606. !(parent == null) &&
  1607. !(parent instanceof JComponent) &&
  1608. !(parent instanceof CellRendererPane);
  1609. parent = parent.getParent()) {
  1610. Rectangle bounds = parent.getBounds();
  1611. dx += bounds.x;
  1612. dy += bounds.y;
  1613. }
  1614. if (!(parent == null) && !(parent instanceof CellRendererPane)) {
  1615. aRect.x += dx;
  1616. aRect.y += dy;
  1617. ((JComponent)parent).scrollRectToVisible(aRect);
  1618. aRect.x -= dx;
  1619. aRect.y -= dy;
  1620. }
  1621. }
  1622. /**
  1623. * If <i>true</i> this component will automatically scroll its contents when
  1624. * dragged, if contained in a component that supports scrolling, such as
  1625. * JViewport
  1626. *
  1627. * @see JViewport
  1628. * @see #getAutoscrolls
  1629. *
  1630. * @beaninfo
  1631. * expert: true
  1632. * description: Whether this component automatically scrolls its contents when dragged.
  1633. */
  1634. public void setAutoscrolls(boolean autoscrolls) {
  1635. if (autoscrolls) {
  1636. if (autoscroller == null) {
  1637. autoscroller = new Autoscroller(this);
  1638. }
  1639. } else {
  1640. if (autoscroller != null) {
  1641. autoscroller.dispose();
  1642. autoscroller = null;
  1643. }
  1644. }
  1645. }
  1646. /**
  1647. * Returns <i>true</i> if this component automatically scrolls its
  1648. * contents when dragged, (when contained in a component that supports
  1649. * scrolling, like JViewport
  1650. *
  1651. * @see JViewport
  1652. * @see #setAutoscrolls
  1653. */
  1654. public boolean getAutoscrolls() {
  1655. return autoscroller != null;
  1656. }
  1657. protected void processMouseMotionEvent(MouseEvent e) {
  1658. boolean dispatch = true;
  1659. if (autoscroller != null) {
  1660. if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
  1661. // We don't want to do the drags when the mouse moves if we're
  1662. // autoscrolling. It makes it feel spastic.
  1663. dispatch = !autoscroller.timer.isRunning();
  1664. autoscroller.mouseDragged(e);
  1665. }
  1666. }
  1667. if (dispatch) {
  1668. super.processMouseMotionEvent(e);
  1669. }
  1670. }
  1671. // Inner classes can't get at this method from a super class
  1672. void superProcessMouseMotionEvent(MouseEvent e) {
  1673. super.processMouseMotionEvent(e);
  1674. }
  1675. static class KeyboardBinding implements Serializable {
  1676. ActionListener action;
  1677. String command;
  1678. KeyStroke keyStroke;
  1679. int condition;
  1680. KeyboardBinding(ActionListener action,String aCommand,KeyStroke aKeyStroke,int condition) {
  1681. this.action = action;
  1682. this.command = aCommand;
  1683. this.keyStroke = aKeyStroke;
  1684. this.condition = condition;
  1685. }
  1686. ActionListener getAction() {
  1687. return action;
  1688. }
  1689. String getCommand() {
  1690. return command;
  1691. }
  1692. KeyStroke getKeyStroke() {
  1693. return keyStroke;
  1694. }
  1695. int getCondition() {
  1696. return condition;
  1697. }
  1698. public String toString() {
  1699. return "KeyBinding ("+action+","+keyStroke+","+condition+")";
  1700. }
  1701. }
  1702. // This class is used by the KeyboardState class to provide a single
  1703. // instance which can be stored in the AppContext.
  1704. static final class IntVector {
  1705. int array[] = null;
  1706. int count = 0;
  1707. int capacity = 0;
  1708. int size() {
  1709. return count;
  1710. }
  1711. int elementAt(int index) {
  1712. return array[index];
  1713. }
  1714. void addElement(int value) {
  1715. if (count == capacity) {
  1716. capacity = (capacity + 2) * 2;
  1717. int[] newarray = new int[capacity];
  1718. if (count > 0) {
  1719. System.arraycopy(array, 0, newarray, 0, count);
  1720. }
  1721. array = newarray;
  1722. }
  1723. array[count++] = value;
  1724. }
  1725. void setElementAt(int value, int index) {
  1726. array[index] = value;
  1727. }
  1728. }
  1729. static class KeyboardState implements Serializable {
  1730. private static final Object keyCodesKey =
  1731. JComponent.KeyboardState.class;
  1732. // Get the array of key codes from the AppContext.
  1733. static IntVector getKeyCodeArray() {
  1734. IntVector iv =
  1735. (IntVector)SwingUtilities.appContextGet(keyCodesKey);
  1736. if (iv == null) {
  1737. iv = new IntVector();
  1738. SwingUtilities.appContextPut(keyCodesKey, iv);
  1739. }
  1740. return iv;
  1741. }
  1742. static void registerKeyPressed(int keyCode) {
  1743. IntVector kca = getKeyCodeArray();
  1744. int count = kca.size();
  1745. int i;
  1746. for(i=0;i<count;i++) {
  1747. if(kca.elementAt(i) == -1){
  1748. kca.setElementAt(keyCode, i);
  1749. return;
  1750. }
  1751. }
  1752. kca.addElement(keyCode);
  1753. }
  1754. static void registerKeyReleased(int keyCode) {
  1755. IntVector kca = getKeyCodeArray();
  1756. int count = kca.size();
  1757. int i;
  1758. for(i=0;i<count;i++) {
  1759. if(kca.elementAt(i) == keyCode) {
  1760. kca.setElementAt(-1, i);
  1761. return;
  1762. }
  1763. }
  1764. }
  1765. static boolean keyIsPressed(int keyCode) {
  1766. IntVector kca = getKeyCodeArray();
  1767. int count = kca.size();
  1768. int i;
  1769. for(i=0;i<count;i++) {
  1770. if(kca.elementAt(i) == keyCode) {
  1771. return true;
  1772. }
  1773. }
  1774. return false;
  1775. }
  1776. }
  1777. /**
  1778. * --- Accessibility Support ---
  1779. *
  1780. * JComponent will contain all of the methods in interface Accessible,
  1781. * though it won't actally implement the interface - that will be up
  1782. * to the individual objects which extend JComponent.
  1783. */
  1784. protected AccessibleContext accessibleContext = null;
  1785. /**
  1786. * Get the AccessibleContext associated with this JComponent
  1787. *
  1788. * @return the AccessibleContext of this JComponent
  1789. */
  1790. public AccessibleContext getAccessibleContext() {
  1791. return accessibleContext;
  1792. }
  1793. /**
  1794. * Inner class of JComponent used to provide default support for
  1795. * accessibility. This class is not meant to be used directly by
  1796. * application developers, but is instead meant only to be
  1797. * subclassed by component developers. Due to a restriction that
  1798. * protected inner classes cannot be subclassed outside of a
  1799. * package, this inner class has been made public. When this
  1800. * restriction is lifted for JDK1.1.7, this class will be made
  1801. * protected.
  1802. * The class used to obtain the accessible role for this object.
  1803. * <p>
  1804. * <strong>Warning:</strong>
  1805. * Serialized objects of this class will not be compatible with
  1806. * future Swing releases. The current serialization support is appropriate
  1807. * for short term storage or RMI between applications running the same
  1808. * version of Swing. A future release of Swing will provide support for
  1809. * long term persistence.
  1810. */
  1811. public abstract class AccessibleJComponent extends AccessibleContext
  1812. implements Serializable, AccessibleComponent {
  1813. /**
  1814. * Though the class is abstract, this should be called by
  1815. * all sub-classes.
  1816. */
  1817. protected AccessibleJComponent() {
  1818. }
  1819. protected ContainerListener accessibleContainerHandler = null;
  1820. /**
  1821. * Fire PropertyChange listener, if one is registered,
  1822. * when children added/removed.
  1823. */
  1824. protected class AccessibleContainerHandler
  1825. implements ContainerListener {
  1826. public void componentAdded(ContainerEvent e) {
  1827. Component c = e.getChild();
  1828. if (c != null && c instanceof Accessible) {
  1829. AccessibleJComponent.this.firePropertyChange(
  1830. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  1831. null, ((Accessible) c).getAccessibleContext());
  1832. }
  1833. }
  1834. public void componentRemoved(ContainerEvent e) {
  1835. Component c = e.getChild();
  1836. if (c != null && c instanceof Accessible) {
  1837. AccessibleJComponent.this.firePropertyChange(
  1838. AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
  1839. ((Accessible) c).getAccessibleContext(), null);
  1840. }
  1841. }
  1842. }
  1843. /**
  1844. * Add a PropertyChangeListener to the listener list.
  1845. *
  1846. * @param listener The PropertyChangeListener to be added
  1847. */
  1848. public void addPropertyChangeListener(PropertyChangeListener listener) {
  1849. if (accessibleContainerHandler == null) {
  1850. accessibleContainerHandler = new AccessibleContainerHandler();
  1851. JComponent.this.addContainerListener(accessibleContainerHandler);
  1852. }
  1853. super.addPropertyChangeListener(listener);
  1854. }
  1855. /**
  1856. * Remove a PropertyChangeListener from the listener list.
  1857. * This removes a PropertyChangeListener that was registered
  1858. * for all properties.
  1859. *
  1860. * @param listener The PropertyChangeListener to be removed
  1861. */
  1862. public void removePropertyChangeListener(PropertyChangeListener listener) {
  1863. if (accessibleContainerHandler == null) {
  1864. JComponent.this.removeContainerListener(accessibleContainerHandler);
  1865. }
  1866. super.removePropertyChangeListener(listener);
  1867. }
  1868. /**
  1869. * Recursively search through the border hierarchy (if it exists)
  1870. * for a TitledBorder with a non-null title. This does a depth
  1871. * first search on first the inside borders then the outside borders.
  1872. * The assumption is that titles make really pretty inside borders
  1873. * but not very pretty outside borders in compound border situations.
  1874. * It's rather arbitrary, but hopefully decent UI programmers will
  1875. * not create multiple titled borders for the same component.
  1876. */
  1877. protected String getBorderTitle(Border b) {
  1878. String s;
  1879. if (b instanceof TitledBorder) {
  1880. return ((TitledBorder) b).getTitle();
  1881. } else if (b instanceof CompoundBorder) {
  1882. s = getBorderTitle(((CompoundBorder) b).getInsideBorder());
  1883. if (s == null) {
  1884. s = getBorderTitle(((CompoundBorder) b).getOutsideBorder());
  1885. }
  1886. return s;
  1887. } else {
  1888. return null;
  1889. }
  1890. }
  1891. // AccessibleContext methods
  1892. //
  1893. /**
  1894. * Get the accessible name of this object. This should almost never
  1895. * return java.awt.Component.getName(), as that generally isn't
  1896. * a localized name, and doesn't have meaning for the user. If the
  1897. * object is fundamentally a text object (e.g. a menu item), the
  1898. * accessible name should be the text of the object (e.g. "save").
  1899. * If the object has a tooltip, the tooltip text may also be an
  1900. * appropriate String to return.
  1901. *
  1902. * @return the localized name of the object -- can be null if this
  1903. * object does not have a name
  1904. * @see AccessibleContext#setAccessibleName
  1905. */
  1906. public String getAccessibleName() {
  1907. String name = accessibleName;
  1908. // fallback to the titled border if it exists
  1909. //
  1910. if (name == null) {
  1911. name = getBorderTitle(getBorder());
  1912. }
  1913. // fallback to the label labeling us if it exists
  1914. //
  1915. if (name == null) {
  1916. Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
  1917. if (o instanceof Accessible) {
  1918. AccessibleContext ac = ((Accessible) o).getAccessibleContext();
  1919. if (ac != null) {
  1920. name = ac.getAccessibleName();
  1921. }
  1922. }
  1923. }
  1924. return name;
  1925. }
  1926. /**
  1927. * Get the accessible description of this object. This should be
  1928. * a concise, localized description of what this object is - what
  1929. * is it's meaning to the user. If the object has a tooltip, the
  1930. * tooltip text may be an appropriate string to return, assuming
  1931. * it contains a concise description of the object (instead of just
  1932. * the name of the object - e.g. a "Save" icon on a toolbar that
  1933. * had "save" as the tooltip text shouldn't return the tooltip
  1934. * text as the description, but something like "Saves the current
  1935. * text document" instead).
  1936. *
  1937. * @return the localized description of the object -- can be null if
  1938. * this object does not have a description
  1939. * @see AccessibleContext#setAccessibleDescription
  1940. */
  1941. public String getAccessibleDescription() {
  1942. String description = accessibleDescription;
  1943. // fallback to the tool tip text if it exists
  1944. //
  1945. if (description == null) {
  1946. try {
  1947. description = getToolTipText(null);
  1948. } catch (Exception e) {
  1949. // Just in case the subclass overrode the
  1950. // getToolTipText method and actually
  1951. // requires a MouseEvent.
  1952. // [[[FIXME: WDW - we probably should require this
  1953. // method to take a MouseEvent and just pass it on
  1954. // to getToolTipText. The swing-feedback traffic
  1955. // leads me to believe getToolTipText might change,
  1956. // though, so I was hesitant to make this change at
  1957. // this time.]]]
  1958. }
  1959. }
  1960. // fallback to the label labeling us if it exists
  1961. //
  1962. if (description == null) {
  1963. Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
  1964. if (o instanceof Accessible) {
  1965. AccessibleContext ac = ((Accessible) o).getAccessibleContext();
  1966. if (ac != null) {
  1967. description = ac.getAccessibleDescription();
  1968. }
  1969. }
  1970. }
  1971. return description;
  1972. }
  1973. /**
  1974. * Get the role of this object.
  1975. *
  1976. * @return an instance of AccessibleRole describing the role of the
  1977. * object
  1978. * @see AccessibleRole
  1979. */
  1980. public AccessibleRole getAccessibleRole() {
  1981. return AccessibleRole.SWING_COMPONENT;
  1982. }
  1983. /**
  1984. * Get the state of this object.
  1985. *
  1986. * @return an instance of AccessibleStateSet containing the current
  1987. * state set of the object
  1988. * @see AccessibleState
  1989. */
  1990. public AccessibleStateSet getAccessibleStateSet() {
  1991. return SwingUtilities.getAccessibleStateSet(JComponent.this);
  1992. }
  1993. /**
  1994. * Get the Accessible parent of this object. If the parent of this
  1995. * object implements Accessible, this method should simply return
  1996. * getParent().
  1997. *
  1998. * @return the Accessible parent of this object -- can be null if this
  1999. * object does not have an Accessible parent
  2000. */
  2001. public Accessible getAccessibleParent() {
  2002. if (accessibleParent != null) {
  2003. return accessibleParent;
  2004. } else {
  2005. Container parent = getParent();
  2006. if (parent instanceof Accessible) {
  2007. return (Accessible) parent;
  2008. }
  2009. }
  2010. return null;
  2011. }
  2012. /**
  2013. * Get the index of this object in its accessible parent.
  2014. *
  2015. * @return the index of this object in its parent; -1 if this
  2016. * object does not have an accessible parent.
  2017. * @see #getAccessibleParent
  2018. */
  2019. public int getAccessibleIndexInParent() {
  2020. return SwingUtilities.getAccessibleIndexInParent(JComponent.this);
  2021. }
  2022. /**
  2023. * Returns the number of accessible children in the object. If all
  2024. * of the children of this object implement Accessible, than this
  2025. * method should return the number of children of this object.
  2026. *
  2027. * @return the number of accessible children in the object.
  2028. */
  2029. public int getAccessibleChildrenCount() {
  2030. // Always delegate to the UI if it exists
  2031. if (ui != null) {
  2032. return ui.getAccessibleChildrenCount(JComponent.this);
  2033. } else {
  2034. return SwingUtilities.getAccessibleChildrenCount(JComponent.this);
  2035. }
  2036. }
  2037. /**
  2038. * Return the nth Accessible child of the object.
  2039. *
  2040. * @param i zero-based index of child
  2041. * @return the nth Accessible child of the object
  2042. */
  2043. public Accessible getAccessibleChild(int i) {
  2044. // Always delegate to the UI if it exists
  2045. if (ui != null) {
  2046. return ui.getAccessibleChild(JComponent.this, i);
  2047. } else {
  2048. return SwingUtilities.getAccessibleChild(JComponent.this, i);
  2049. }
  2050. }
  2051. /**
  2052. * Return the locale of this object.
  2053. *
  2054. * @return the locale of this object
  2055. */
  2056. public Locale getLocale() {
  2057. return JComponent.this.getLocale();
  2058. }
  2059. /**
  2060. * Get the AccessibleComponent associated with this object if one
  2061. * exists. Otherwise return null.
  2062. *
  2063. * @return the component
  2064. */
  2065. public AccessibleComponent getAccessibleComponent() {
  2066. return this;
  2067. }
  2068. // AccessibleComponent methods
  2069. //
  2070. /**
  2071. * Get the background color of this object.
  2072. *
  2073. * @return the background color, if supported, of the object;
  2074. * otherwise, null
  2075. */
  2076. public Color getBackground() {
  2077. return JComponent.this.getBackground();
  2078. }
  2079. // NOTE: IN THE NEXT MAJOR RELEASE, isOpaque WILL MIGRATE
  2080. // TO java.awt.Component -- ADJUST @SEE LINK BELOW.
  2081. /**
  2082. * Set the background color of this object.
  2083. * (For transparency, see <code>isOpaque</code>.)
  2084. *
  2085. * @param c the new Color for the background
  2086. * @see JComponent#isOpaque
  2087. */
  2088. public void setBackground(Color c) {
  2089. JComponent.this.setBackground(c);
  2090. }
  2091. /**
  2092. * Get the foreground color of this object.
  2093. *
  2094. * @return the foreground color, if supported, of the object;
  2095. * otherwise, null
  2096. */
  2097. public Color getForeground() {
  2098. return JComponent.this.getForeground();
  2099. }
  2100. /**
  2101. * Set the foreground color of this object.
  2102. *
  2103. * @param c the new Color for the foreground
  2104. */
  2105. public void setForeground(Color c) {
  2106. JComponent.this.setForeground(c);
  2107. }
  2108. /**
  2109. * Get the Cursor of this object.
  2110. *
  2111. * @return the Cursor, if supported, of the object; otherwise, null
  2112. */
  2113. public Cursor getCursor() {
  2114. return JComponent.this.getCursor();
  2115. }
  2116. /**
  2117. * Set the Cursor of this object.
  2118. *
  2119. * @param c the new Cursor for the object
  2120. */
  2121. public void setCursor(Cursor cursor) {
  2122. JComponent.this.setCursor(cursor);
  2123. }
  2124. /**
  2125. * Get the Font of this object.
  2126. *
  2127. * @return the Font,if supported, for the object; otherwise, null
  2128. */
  2129. public Font getFont() {
  2130. return JComponent.this.getFont();
  2131. }
  2132. /**
  2133. * Set the Font of this object.
  2134. *
  2135. * @param f the new Font for the object
  2136. */
  2137. public void setFont(Font f) {
  2138. JComponent.this.setFont(f);
  2139. }
  2140. /**
  2141. * Get the FontMetrics of this object.
  2142. *
  2143. * @param f the Font
  2144. * @return the FontMetrics, if supported, the object; otherwise, null
  2145. * @see #getFont
  2146. */
  2147. public FontMetrics getFontMetrics(Font f) {
  2148. return JComponent.this.getFontMetrics(f);
  2149. }
  2150. /**
  2151. * Determine if the object is enabled.
  2152. *
  2153. * @return true if object is enabled; otherwise, false
  2154. */
  2155. public boolean isEnabled() {
  2156. return JComponent.this.isEnabled();
  2157. }
  2158. /**
  2159. * Set the enabled state of the object.
  2160. *
  2161. * @param b if true, enables this object; otherwise, disables it
  2162. */
  2163. public void setEnabled(boolean b) {
  2164. boolean old = JComponent.this.isEnabled();
  2165. JComponent.this.setEnabled(b);
  2166. if (b != old) {
  2167. if (accessibleContext != null) {
  2168. if (b) {
  2169. accessibleContext.firePropertyChange(
  2170. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2171. null, AccessibleState.ENABLED);
  2172. } else {
  2173. accessibleContext.firePropertyChange(
  2174. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2175. AccessibleState.ENABLED, null);
  2176. }
  2177. }
  2178. }
  2179. }
  2180. /**
  2181. * Determine if the object is visible. Note: this means that the
  2182. * object intends to be visible; however, it may not in fact be
  2183. * showing on the screen because one of the objects that this object
  2184. * is contained by is not visible. To determine if an object is
  2185. * showing on the screen, use isShowing().
  2186. *
  2187. * @return true if object is visible; otherwise, false
  2188. */
  2189. public boolean isVisible() {
  2190. return JComponent.this.isVisible();
  2191. }
  2192. /**
  2193. * Set the visible state of the object.
  2194. *
  2195. * @param b if true, shows this object; otherwise, hides it
  2196. */
  2197. public void setVisible(boolean b) {
  2198. boolean old = JComponent.this.isVisible();
  2199. JComponent.this.setVisible(b);
  2200. if (b != old) {
  2201. if (accessibleContext != null) {
  2202. if (b) {
  2203. accessibleContext.firePropertyChange(
  2204. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2205. null, AccessibleState.VISIBLE);
  2206. } else {
  2207. accessibleContext.firePropertyChange(
  2208. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  2209. AccessibleState.VISIBLE, null);
  2210. }
  2211. }
  2212. }
  2213. }
  2214. /**
  2215. * Determine if the object is showing. This is determined by checking
  2216. * the visibility of the object and ancestors of the object. Note:
  2217. * this will return true even if the object is obscured by another
  2218. * (for example, it happens to be underneath a menu that was pulled
  2219. * down).
  2220. *
  2221. * @return true if object is showing; otherwise, false
  2222. */
  2223. public boolean isShowing() {
  2224. return JComponent.this.isShowing();
  2225. }
  2226. /**
  2227. * Checks whether the specified point is within this object's bounds,
  2228. * where the point's x and y coordinates are defined to be relative to
  2229. * the coordinate system of the object.
  2230. *
  2231. * @param p the Point relative to the coordinate system of the object
  2232. * @return true if object contains Point; otherwise false
  2233. */
  2234. public boolean contains(Point p) {
  2235. return JComponent.this.contains(p);
  2236. }
  2237. /**
  2238. * Returns the location of the object on the screen.
  2239. *
  2240. * @return location of object on screen -- can be null if this object
  2241. * is not on the screen
  2242. */
  2243. public Point getLocationOnScreen() {
  2244. if (JComponent.this.isShowing()) {
  2245. return JComponent.this.getLocationOnScreen();
  2246. } else {
  2247. return null;
  2248. }
  2249. }
  2250. /**
  2251. * Gets the location of the object relative to the parent in the form
  2252. * of a point specifying the object's top-left corner in the screen's
  2253. * coordinate space.
  2254. *
  2255. * @return An instance of Point representing the top-left corner of
  2256. * the objects's bounds in the coordinate space of the screen; null if
  2257. * this object or its parent are not on the screen
  2258. */
  2259. public Point getLocation() {
  2260. return JComponent.this.getLocation();
  2261. }
  2262. /**
  2263. * Sets the location of the object relative to the parent.
  2264. */
  2265. public void setLocation(Point p) {
  2266. JComponent.this.setLocation(p);
  2267. }
  2268. /**
  2269. * Gets the bounds of this object in the form of a Rectangle object.
  2270. * The bounds specify this object's width, height, and location
  2271. * relative to its parent.
  2272. *
  2273. * @return A rectangle indicating this component's bounds; null if
  2274. * this object is not on the screen.
  2275. */
  2276. public Rectangle getBounds() {
  2277. return JComponent.this.getBounds();
  2278. }
  2279. /**
  2280. * Sets the bounds of this object in the form of a Rectangle object.
  2281. * The bounds specify this object's width, height, and location
  2282. * relative to its parent.
  2283. *
  2284. * @param A rectangle indicating this component's bounds
  2285. */
  2286. public void setBounds(Rectangle r) {
  2287. JComponent.this.setBounds(r);
  2288. }
  2289. /**
  2290. * Returns the size of this object in the form of a Dimension object.
  2291. * The height field of the Dimension object contains this objects's
  2292. * height, and the width field of the Dimension object contains this
  2293. * object's width.
  2294. *
  2295. * @return A Dimension object that indicates the size of this
  2296. * component; null if this object is not on the screen
  2297. */
  2298. public Dimension getSize() {
  2299. return JComponent.this.getSize();
  2300. }
  2301. /**
  2302. * Resizes this object so that it has width width and height.
  2303. *
  2304. * @param d - The dimension specifying the new size of the object.
  2305. */
  2306. public void setSize(Dimension d) {
  2307. JComponent.this.setSize(d);
  2308. }
  2309. /**
  2310. * Returns the Accessible child, if one exists, contained at the local
  2311. * coordinate Point.
  2312. *
  2313. * @param p The point defining the top-left corner of the Accessible,
  2314. * given in the coordinate space of the object's parent.
  2315. * @return the Accessible, if it exists, at the specified location;
  2316. * else null
  2317. */
  2318. public Accessible getAccessibleAt(Point p) {
  2319. return SwingUtilities.getAccessibleAt(JComponent.this, p);
  2320. }
  2321. /**
  2322. * Returns whether this object can accept focus or not.
  2323. *
  2324. * @return true if object can accept focus; otherwise false
  2325. */
  2326. public boolean isFocusTraversable() {
  2327. return JComponent.this.isFocusTraversable();
  2328. }
  2329. /**
  2330. * Requests focus for this object.
  2331. */
  2332. public void requestFocus() {
  2333. JComponent.this.requestFocus();
  2334. }
  2335. /**
  2336. * Adds the specified focus listener to receive focus events from this
  2337. * component.
  2338. *
  2339. * @param l the focus listener
  2340. */
  2341. public void addFocusListener(FocusListener l) {
  2342. JComponent.this.addFocusListener(l);
  2343. }
  2344. /**
  2345. * Removes the specified focus listener so it no longer receives focus
  2346. * events from this component.
  2347. *
  2348. * @param l the focus listener
  2349. */
  2350. public void removeFocusListener(FocusListener l) {
  2351. JComponent.this.removeFocusListener(l);
  2352. }
  2353. } // inner class AccessibleJComponent
  2354. /**
  2355. * @return a small Hashtable
  2356. * @see #putClientProperty
  2357. * @see #getClientProperty
  2358. */
  2359. private Dictionary getClientProperties() {
  2360. if (clientProperties == null) {
  2361. clientProperties = new Hashtable(2);
  2362. }
  2363. return clientProperties;
  2364. }
  2365. /**
  2366. * Returns the value of the property with the specified key. Only
  2367. * properties added with <code>putClientProperty</code> will return
  2368. * a non-null value.
  2369. *
  2370. * @return the value of this property or null
  2371. * @see #putClientProperty
  2372. */
  2373. public final Object getClientProperty(Object key) {
  2374. if(clientProperties == null) {
  2375. return null;
  2376. }
  2377. else {
  2378. return getClientProperties().get(key);
  2379. }
  2380. }
  2381. /**
  2382. * Add an arbitrary key/value "client property" to this component.
  2383. * <p>
  2384. * The <code>get/putClientProperty<code> methods provide access to
  2385. * a small per-instance hashtable. Callers can use get/putClientProperty
  2386. * to annotate components that were created by another module, e.g. a
  2387. * layout manager might store per child constraints this way. For example:
  2388. * <pre>
  2389. * componentA.putClientProperty("to the left of", componentB);
  2390. * </pre>
  2391. * <p>
  2392. * If value is null this method will remove the property.
  2393. * Changes to client properties are reported with PropertyChange
  2394. * events. The name of the property (for the sake of PropertyChange
  2395. * events) is <code>key.toString()</code>.
  2396. * <p>
  2397. * The clientProperty dictionary is not intended to support large
  2398. * scale extensions to JComponent nor should be it considered an
  2399. * alternative to subclassing when designing a new component.
  2400. *
  2401. * @see #getClientProperty
  2402. * @see #addPropertyChangeListener
  2403. */
  2404. public final void putClientProperty(Object key, Object value) {
  2405. Object oldValue = getClientProperties().get(key);
  2406. if (value != null) {
  2407. getClientProperties().put(key, value);
  2408. } else {
  2409. getClientProperties().remove(key);
  2410. }
  2411. firePropertyChange(key.toString(), oldValue, value);
  2412. }
  2413. /* --- Transitional java.awt.Component Support ---
  2414. *
  2415. * The methods and fields in this section will migrate to
  2416. * java.awt.Component in the next JDK release.
  2417. *
  2418. */
  2419. private SwingPropertyChangeSupport changeSupport;
  2420. /**
  2421. * Returns true if this component is a lightweight, i.e. if it doesn't
  2422. * have a native window system peer.
  2423. * <p>
  2424. * This method will migrate to java.awt.Component in the next major JDK release
  2425. *
  2426. * @return true if this component is a lightweight
  2427. */
  2428. public static boolean isLightweightComponent(Component c) {
  2429. return c.getPeer() instanceof java.awt.peer.LightweightPeer;
  2430. }
  2431. /**
  2432. * Moves and resizes this component.
  2433. *
  2434. * @see java.awt.Component#setBounds
  2435. */
  2436. public void reshape(int x, int y, int w, int h) {
  2437. if(isShowing()) {
  2438. /* If there is an intersection between the new bounds and the old
  2439. * one, refresh only the visible rects
  2440. */
  2441. if(!((_bounds.x + _bounds.width <= x) ||
  2442. (_bounds.y + _bounds.height <= y) ||
  2443. (_bounds.x >= (x + w)) ||
  2444. (_bounds.y >= (y + h)))) {
  2445. Rectangle[] rev = SwingUtilities.computeDifference(getBounds(),
  2446. new Rectangle(x,y,w,h));
  2447. int i,c;
  2448. Container parent = getParent();
  2449. for(i=0,c=rev.length ; i < c ; i++) {
  2450. parent.repaint(rev[i].x,rev[i].y,rev[i].width,rev[i].height);
  2451. // System.out.println("Repaint " + rev[i]);
  2452. }
  2453. } else {
  2454. getParent().repaint(_bounds.x,_bounds.y,_bounds.width,_bounds.height);
  2455. }
  2456. }
  2457. _bounds.setBounds(x, y, w, h);
  2458. super.reshape(x, y, w, h);
  2459. }
  2460. /**
  2461. * Store the bounds of this component into "return value" <b>rv</b> and
  2462. * return <b>rv</b>. If rv is null a new Rectangle is allocated.
  2463. * This version of getBounds() is useful if the caller
  2464. * wants to avoid allocating a new Rectangle object on the heap.
  2465. *
  2466. * @param rv the return value, modified to the components bounds
  2467. * @return rv
  2468. */
  2469. public Rectangle getBounds(Rectangle rv) {
  2470. if (rv == null) {
  2471. return new Rectangle(getX(), getY(), getWidth(), getHeight());
  2472. }
  2473. else {
  2474. rv.setBounds(getX(), getY(), getWidth(), getHeight());
  2475. return rv;
  2476. }
  2477. }
  2478. /**
  2479. * Store the width/height of this component into "return value" <b>rv</b>
  2480. * and return <b>rv</b>. If rv is null a new Dimension object is
  2481. * allocated. This version of getSize() is useful if the
  2482. * caller wants to avoid allocating a new Dimension object on the heap.
  2483. *
  2484. * @param rv the return value, modified to the components size
  2485. * @return rv
  2486. */
  2487. public Dimension getSize(Dimension rv) {
  2488. if (rv == null) {
  2489. return new Dimension(getWidth(), getHeight());
  2490. }
  2491. else {
  2492. rv.setSize(getWidth(), getHeight());
  2493. return rv;
  2494. }
  2495. }
  2496. /**
  2497. * Store the x,y origin of this component into "return value" <b>rv</b>
  2498. * and return <b>rv</b>. If rv is null a new Point is allocated.
  2499. * This version of getLocation() is useful if the
  2500. * caller wants to avoid allocating a new Point object on the heap.
  2501. *
  2502. * @param rv the return value, modified to the components location
  2503. * @return rv
  2504. */
  2505. public Point getLocation(Point rv) {
  2506. if (rv == null) {
  2507. return new Point(getX(), getY());
  2508. }
  2509. else {
  2510. rv.setLocation(getX(), getY());
  2511. return rv;
  2512. }
  2513. }
  2514. /**
  2515. * Return the current x coordinate of the components origin.
  2516. * This method is preferable to writing component.getBounds().x,
  2517. * or component.getLocation().x because it doesn't cause any
  2518. * heap allocations.
  2519. * <p>
  2520. * This method will migrate to java.awt.Component in the next major JDK release
  2521. *
  2522. * @return the current x coordinate of the components origin.
  2523. */
  2524. public int getX() { return _bounds.x; }
  2525. /**
  2526. * Return the current y coordinate of the components origin.
  2527. * This method is preferable to writing component.getBounds().y,
  2528. * or component.getLocation().y because it doesn't cause any
  2529. * heap allocations.
  2530. * <p>
  2531. * This method will migrate to java.awt.Component in the next major JDK release
  2532. *
  2533. * @return the current y coordinate of the components origin.
  2534. */
  2535. public int getY() { return _bounds.y; }
  2536. /**
  2537. * Return the current width of this component.
  2538. * This method is preferable to writing component.getBounds().width,
  2539. * or component.getSize().width because it doesn't cause any
  2540. * heap allocations.
  2541. * <p>
  2542. * This method will migrate to java.awt.Component in the next major JDK release
  2543. *
  2544. * @return the current width of this component.
  2545. */
  2546. public int getWidth() { return _bounds.width; }
  2547. /**
  2548. * Return the current height of this component.
  2549. * This method is preferable to writing component.getBounds().height,
  2550. * or component.getSize().height because it doesn't cause any
  2551. * heap allocations.
  2552. * <p>
  2553. * This method will migrate to java.awt.Component in the next major JDK release
  2554. *
  2555. * @return the current height of this component.
  2556. */
  2557. public int getHeight() { return _bounds.height; }
  2558. /**
  2559. * Returns true if this Component has the keyboard focus.
  2560. * <p>
  2561. * This method will migrate to java.awt.Component in the next major JDK release
  2562. *
  2563. * @return true if this Component has the keyboard focus.
  2564. */
  2565. public boolean hasFocus() {
  2566. return getFlag(HAS_FOCUS);
  2567. }
  2568. /**
  2569. * Returns true if this component is completely opaque.
  2570. * <p>
  2571. * An opaque component paints every pixel within its
  2572. * rectangular region. A non-opaque component paints only some of
  2573. * its pixels, allowing the pixels underneath it to "show through".
  2574. * A component that does not fully paint its pixels therefore
  2575. * provides a degree of transparency.
  2576. * <p>
  2577. * Subclasses that guarantee to always completely paint their contents should
  2578. * override this method and return true.
  2579. * <p>
  2580. * This method will migrate to java.awt.Component in the next major JDK release
  2581. *
  2582. * @return true if this component is completely opaque.
  2583. * @see #setOpaque
  2584. */
  2585. public boolean isOpaque() {
  2586. return getFlag(IS_OPAQUE);
  2587. }
  2588. /**
  2589. * If true the components background will be filled with the
  2590. * background color. Otherwise, the background is transparent,
  2591. * and whatever is underneath will show through.
  2592. * <p>
  2593. * The default value of this property is false.
  2594. * <p>
  2595. * This is a JavaBeans bound property.
  2596. *
  2597. * @see #isOpaque
  2598. */
  2599. public void setOpaque(boolean isOpaque) {
  2600. boolean oldValue = getFlag(IS_OPAQUE);
  2601. setFlag(IS_OPAQUE, isOpaque);
  2602. firePropertyChange("opaque", oldValue, isOpaque);
  2603. }
  2604. /**
  2605. * If the specified retangle is completely obscured by any of this
  2606. * components opaque children then return true. Only direct children
  2607. * are considered, more distant descendants are ignored. A JComponent
  2608. * is opaque if JComponent.isOpaque() returns true, other lightweight
  2609. * components are always considered transparent, and heavyweight components
  2610. * are always considered opaque.
  2611. *
  2612. * @return true if the specified rectangle is obscured by an opaque child
  2613. */
  2614. boolean rectangleIsObscured(int x,int y,int width,int height)
  2615. {
  2616. int numChildren = getComponentCount();
  2617. for(int i = 0; i < numChildren; i++) {
  2618. Component child = getComponent(i);
  2619. Rectangle childBounds;
  2620. if (child instanceof JComponent) {
  2621. childBounds = ((JComponent)child)._bounds;
  2622. } else {
  2623. childBounds = child.getBounds();
  2624. }
  2625. if (x >= childBounds.x && (x + width) <= (childBounds.x + childBounds.width) &&
  2626. y >= childBounds.y && (y + height) <= (childBounds.y + childBounds.height) && child.isVisible()) {
  2627. if(child instanceof JComponent) {
  2628. // System.out.println("A) checking opaque: " + ((JComponent)child).isOpaque() + " " + child);
  2629. // System.out.print("B) ");
  2630. // Thread.dumpStack();
  2631. return ((JComponent)child).isOpaque();
  2632. } else {
  2633. /** Sometimes a heavy weight can have a bound larger than it's peer size
  2634. * so we should always draw under heavy weights
  2635. */
  2636. return false;
  2637. }
  2638. }
  2639. }
  2640. return false;
  2641. }
  2642. /**
  2643. * Returns the Component's "visible rect rectangle" - the
  2644. * intersection of the visible rectangles for this component
  2645. * and all of its ancestors. The return value is stored in
  2646. * <code>visibleRect</code>
  2647. *
  2648. * @see #getVisibleRect
  2649. */
  2650. static final void computeVisibleRect(Component c, Rectangle visibleRect) {
  2651. Container p = c.getParent();
  2652. Rectangle bounds = c.getBounds();
  2653. if (p == null || p instanceof Window || p instanceof Applet) {
  2654. visibleRect.setBounds(0, 0, bounds.width, bounds.height);
  2655. } else {
  2656. computeVisibleRect(p, visibleRect);
  2657. visibleRect.x -= bounds.x;
  2658. visibleRect.y -= bounds.y;
  2659. SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect);
  2660. }
  2661. }
  2662. /**
  2663. * Returns the Component's "visible rect rectangle" - the
  2664. * intersection of the visible rectangles for this component
  2665. * and all of its ancestors. The return value is stored in
  2666. * <code>visibleRect</code>
  2667. *
  2668. * @see #getVisibleRect
  2669. */
  2670. public void computeVisibleRect(Rectangle visibleRect) {
  2671. computeVisibleRect(this, visibleRect);
  2672. }
  2673. /**
  2674. * Returns the Component's "visible rectangle" - the
  2675. * intersection of this components visible rectangle:
  2676. * <pre>
  2677. * new Rectangle(0, 0, getWidth(), getHeight());
  2678. * </pre>
  2679. * and all of its ancestors visible Rectangles.
  2680. *
  2681. * @return the visible rectangle
  2682. */
  2683. public Rectangle getVisibleRect() {
  2684. Rectangle visibleRect = new Rectangle();
  2685. computeVisibleRect(visibleRect);
  2686. return visibleRect;
  2687. }
  2688. /**
  2689. * Support for reporting bound property changes. If oldValue and
  2690. * newValue are not equal and the PropertyChangeEvent listener list
  2691. * isn't empty, then fire a PropertyChange event to each listener.
  2692. * This method has an overloaded method for each primitive type. For
  2693. * example, here's how to write a bound property set method whose
  2694. * value is an int:
  2695. * <pre>
  2696. * public void setFoo(int newValue) {
  2697. * int oldValue = foo;
  2698. * foo = newValue;
  2699. * firePropertyChange("foo", oldValue, newValue);
  2700. * }
  2701. * </pre>
  2702. * <p>
  2703. * This method will migrate to java.awt.Component in the next major JDK release
  2704. *
  2705. * @param propertyName The programmatic name of the property that was changed.
  2706. * @param oldValue The old value of the property.
  2707. * @param newValue The new value of the property.
  2708. * @see java.beans.PropertyChangeSupport
  2709. */
  2710. protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
  2711. if (changeSupport != null) {
  2712. changeSupport.firePropertyChange(propertyName, oldValue, newValue);
  2713. }
  2714. }
  2715. /*
  2716. * PENDING(hmuller) in JDK1.2 the following firePropertyChange overloads
  2717. * should additional check for a non-empty listener list with
  2718. * changeSupport.hasListeners(propertyName) before calling firePropertyChange.
  2719. */
  2720. /**
  2721. * Reports a bound property change.
  2722. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2723. */
  2724. public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
  2725. if ((changeSupport != null) && (oldValue != newValue)) {
  2726. changeSupport.firePropertyChange(propertyName, new Byte(oldValue), new Byte(newValue));
  2727. }
  2728. }
  2729. /**
  2730. * Reports a bound property change.
  2731. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2732. */
  2733. public void firePropertyChange(String propertyName, char oldValue, char newValue) {
  2734. if ((changeSupport != null) && (oldValue != newValue)) {
  2735. changeSupport.firePropertyChange(propertyName, new Character(oldValue), new Character(newValue));
  2736. }
  2737. }
  2738. /**
  2739. * Reports a bound property change.
  2740. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2741. */
  2742. public void firePropertyChange(String propertyName, short oldValue, short newValue) {
  2743. if ((changeSupport != null) && (oldValue != newValue)) {
  2744. changeSupport.firePropertyChange(propertyName, new Short(oldValue), new Short(newValue));
  2745. }
  2746. }
  2747. /**
  2748. * Reports a bound property change.
  2749. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2750. */
  2751. public void firePropertyChange(String propertyName, int oldValue, int newValue) {
  2752. if ((changeSupport != null) && (oldValue != newValue)) {
  2753. changeSupport.firePropertyChange(propertyName, new Integer(oldValue), new Integer(newValue));
  2754. }
  2755. }
  2756. /**
  2757. * Reports a bound property change.
  2758. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2759. */
  2760. public void firePropertyChange(String propertyName, long oldValue, long newValue) {
  2761. if ((changeSupport != null) && (oldValue != newValue)) {
  2762. changeSupport.firePropertyChange(propertyName, new Long(oldValue), new Long(newValue));
  2763. }
  2764. }
  2765. /**
  2766. * Reports a bound property change.
  2767. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2768. */
  2769. public void firePropertyChange(String propertyName, float oldValue, float newValue) {
  2770. if ((changeSupport != null) && (oldValue != newValue)) {
  2771. changeSupport.firePropertyChange(propertyName, new Float(oldValue), new Float(newValue));
  2772. }
  2773. }
  2774. /**
  2775. * Reports a bound property change.
  2776. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2777. */
  2778. public void firePropertyChange(String propertyName, double oldValue, double newValue) {
  2779. if ((changeSupport != null) && (oldValue != newValue)) {
  2780. changeSupport.firePropertyChange(propertyName, new Double(oldValue), new Double(newValue));
  2781. }
  2782. }
  2783. /**
  2784. * Reports a bound property change.
  2785. * @see #firePropertyChange(java.lang.String, java.lang.Object, java.lang.Object)
  2786. */
  2787. public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
  2788. if ((changeSupport != null) && (oldValue != newValue)) {
  2789. changeSupport.firePropertyChange(propertyName, new Boolean(oldValue), new Boolean(newValue));
  2790. }
  2791. }
  2792. /**
  2793. * Add a PropertyChangeListener to the listener list.
  2794. * The listener is registered for all properties.
  2795. * <p>
  2796. * A PropertyChangeEvent will get fired in response to setting
  2797. * a bound property, e.g. setFont, setBackground, or setForeground.
  2798. * Note that if the current component is inheriting its foreground,
  2799. * background, or font from its container, then no event will be
  2800. * fired in response to a change in the inherited property.
  2801. * <p>
  2802. * This method will migrate to java.awt.Component in the next major JDK release
  2803. *
  2804. * @param listener The PropertyChangeListener to be added
  2805. */
  2806. public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
  2807. if (changeSupport == null) {
  2808. changeSupport = new SwingPropertyChangeSupport(this);
  2809. }
  2810. changeSupport.addPropertyChangeListener(listener);
  2811. }
  2812. /**
  2813. * Add a PropertyChangeListener for a specific property. The listener
  2814. * will be invoked only when a call on firePropertyChange names that
  2815. * specific property.
  2816. *
  2817. * If listener is null, no exception is thrown and no action is performed.
  2818. *
  2819. * @param propertyName The name of the property to listen on.
  2820. * @param listener The PropertyChangeListener to be added
  2821. */
  2822. public synchronized void addPropertyChangeListener(
  2823. String propertyName,
  2824. PropertyChangeListener listener) {
  2825. if (listener == null) {
  2826. return;
  2827. }
  2828. if (changeSupport == null) {
  2829. changeSupport = new SwingPropertyChangeSupport(this);
  2830. }
  2831. changeSupport.addPropertyChangeListener(propertyName, listener);
  2832. }
  2833. /**
  2834. * Remove a PropertyChangeListener from the listener list.
  2835. * This removes a PropertyChangeListener that was registered
  2836. * for all properties.
  2837. * <p>
  2838. * This method will migrate to java.awt.Component in the next major JDK release
  2839. *
  2840. * @param listener The PropertyChangeListener to be removed
  2841. */
  2842. public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
  2843. if (changeSupport != null) {
  2844. changeSupport.removePropertyChangeListener(listener);
  2845. }
  2846. }
  2847. /**
  2848. * Remove a PropertyChangeListener for a specific property.
  2849. * If listener is null, no exception is thrown and no action is performed.
  2850. *
  2851. * @param propertyName The name of the property that was listened on.
  2852. * @param listener The PropertyChangeListener to be removed
  2853. */
  2854. public synchronized void removePropertyChangeListener(
  2855. String propertyName,
  2856. PropertyChangeListener listener) {
  2857. if (listener == null) {
  2858. return;
  2859. }
  2860. if (changeSupport == null) {
  2861. return;
  2862. }
  2863. changeSupport.removePropertyChangeListener(propertyName, listener);
  2864. }
  2865. /**
  2866. * Support for reporting constrained property changes. This method can be called
  2867. * when a constrained property has changed and it will send the appropriate
  2868. * PropertyChangeEvent to any registered VetoableChangeListeners.
  2869. * <p>
  2870. * This method will migrate to java.awt.Component in the next major JDK release
  2871. *
  2872. * @exception PropertyVetoException when the attempt to set the property is vetoed
  2873. * by the receiver.
  2874. */
  2875. protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
  2876. throws java.beans.PropertyVetoException
  2877. {
  2878. if (vetoableChangeSupport == null) {
  2879. return;
  2880. }
  2881. vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
  2882. }
  2883. /**
  2884. * Add a VetoableChangeListener to the listener list.
  2885. * The listener is registered for all properties.
  2886. * <p>
  2887. * This method will migrate to java.awt.Component in the next major JDK release
  2888. *
  2889. * @param listener The VetoableChangeListener to be added
  2890. */
  2891. public synchronized void addVetoableChangeListener(VetoableChangeListener listener) {
  2892. if (vetoableChangeSupport == null) {
  2893. vetoableChangeSupport = new java.beans.VetoableChangeSupport(this);
  2894. }
  2895. vetoableChangeSupport.addVetoableChangeListener(listener);
  2896. }
  2897. /**
  2898. * Remove a VetoableChangeListener from the listener list.
  2899. * This removes a VetoableChangeListener that was registered
  2900. * for all properties.
  2901. * <p>
  2902. * This method will migrate to java.awt.Component in the next major JDK release
  2903. *
  2904. * @param listener The VetoableChangeListener to be removed
  2905. */
  2906. public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) {
  2907. if (vetoableChangeSupport == null) {
  2908. return;
  2909. }
  2910. vetoableChangeSupport.removeVetoableChangeListener(listener);
  2911. }
  2912. /**
  2913. * Returns the top-level ancestor of this component (either the
  2914. * containing Window or Applet), or null if this component has not
  2915. * been added to any container.
  2916. *
  2917. * @return the top-level Container which this component is in.
  2918. */
  2919. public Container getTopLevelAncestor() {
  2920. for(Container p = this; p != null; p = p.getParent()) {
  2921. if(p instanceof Window || p instanceof Applet) {
  2922. return p;
  2923. }
  2924. }
  2925. return null;
  2926. }
  2927. /**
  2928. * Registers <i>listener</i> so that it will receive AncestorEvents
  2929. * when it or any of its ancestors move or are made visible / invisible.
  2930. * Events are also sent when the component or its ancestors are added
  2931. * or removed from the Component hierarchy
  2932. * <p>
  2933. * This method will migrate to java.awt.Component in the next major JDK release
  2934. *
  2935. * @see AncestorEvent
  2936. */
  2937. public void addAncestorListener(AncestorListener listener) {
  2938. if (ancestorNotifier == null) {
  2939. ancestorNotifier = new AncestorNotifier(this);
  2940. }
  2941. ancestorNotifier.addAncestorListener(listener);
  2942. }
  2943. /**
  2944. * Unregisters <i>listener</i> so that it will no longer receive
  2945. * AncestorEvents
  2946. * <p>
  2947. * This method will migrate to java.awt.Component in the next major JDK release
  2948. *
  2949. * @see #addAncestorListener
  2950. */
  2951. public void removeAncestorListener(AncestorListener listener) {
  2952. if (ancestorNotifier == null) {
  2953. return;
  2954. }
  2955. ancestorNotifier.removeAncestorListener(listener);
  2956. if (ancestorNotifier.listenerList.getListenerList().length == 0) {
  2957. ancestorNotifier.removeAllListeners();
  2958. ancestorNotifier = null;
  2959. }
  2960. }
  2961. /**
  2962. * Notification to this component that it now has a parent component.
  2963. * When this method is invoked, the chain of parent components is
  2964. * set up with KeyboardAction event listeners.
  2965. *
  2966. * @see #registerKeyboardAction
  2967. */
  2968. public void addNotify() {
  2969. super.addNotify();
  2970. firePropertyChange("ancestor", null, getParent());
  2971. Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  2972. if( bindings == null)
  2973. return;
  2974. Enumeration iter = bindings.keys();
  2975. while (iter.hasMoreElements()) {
  2976. KeyStroke ks = (KeyStroke)iter.nextElement();
  2977. KeyboardBinding aBinding = (KeyboardBinding)bindings.get(ks);
  2978. if (aBinding.condition == WHEN_IN_FOCUSED_WINDOW) {
  2979. registerWithKeyboardManager(ks);
  2980. }
  2981. }
  2982. }
  2983. /**
  2984. * Notification to this component that it no longer has a parent component.
  2985. * When this method is invoked, any KeyboardActions set up in the
  2986. * the chain of parent components are removed.
  2987. *
  2988. * @see #registerKeyboardAction
  2989. */
  2990. public void removeNotify() {
  2991. super.removeNotify();
  2992. // This isn't strictly correct. The event shouldn't be
  2993. // fired until *after* the parent is set to null. But
  2994. // we only get notified before that happens
  2995. firePropertyChange("ancestor", getParent(), null);
  2996. Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  2997. if( bindings == null)
  2998. return;
  2999. Enumeration iter = bindings.keys();
  3000. while (iter.hasMoreElements()) {
  3001. KeyStroke ks = (KeyStroke)iter.nextElement();
  3002. KeyboardBinding aBinding = (KeyboardBinding)bindings.get(ks);
  3003. if (aBinding.condition == WHEN_IN_FOCUSED_WINDOW) {
  3004. unregisterWithKeyboardManager(ks);
  3005. }
  3006. }
  3007. }
  3008. /**
  3009. * Adds the specified region to the dirty region list if the component
  3010. * is showing. The component will be repainted after all of the
  3011. * currently pending events have been dispatched.
  3012. *
  3013. * @see java.awt.Component#isShowing
  3014. * @see RepaintManager#addDirtyRegion
  3015. */
  3016. public void repaint(long tm, int x, int y, int width, int height) {
  3017. RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
  3018. }
  3019. /**
  3020. * Adds the specified region to the dirty region list if the component
  3021. * is showing. The component will be repainted after all of the
  3022. * currently pending events have been dispatched.
  3023. *
  3024. * @see java.awt.Component#isShowing
  3025. * @see RepaintManager#addDirtyRegion
  3026. */
  3027. public void repaint(Rectangle r) {
  3028. repaint(0,r.x,r.y,r.width,r.height);
  3029. }
  3030. /**
  3031. * Support for deferred automatic layout.
  3032. * <p>
  3033. * Calls invalidate() and then adds this components validateRoot
  3034. * to a list of components that need to be validated. Validation
  3035. * will occur after all currently pending events have been dispatched.
  3036. * In other words after this method is called, the first validateRoot
  3037. * (if any) found when walking up the containment hierarchy of this
  3038. * component will be validated.
  3039. * By default, JRootPane, JScrollPane, and JTextField return true
  3040. * from isValidateRoot().
  3041. * <p>
  3042. * This method will automatically be called on this component
  3043. * when a property value changes such that size, location, or
  3044. * internal layout of this component has been affected. This automatic
  3045. * updating differs from the AWT because programs generally no
  3046. * longer need to invoke validate() to get the contents of the
  3047. * GUI to update.
  3048. * <p>
  3049. *
  3050. * @see java.awt.Component#invalidate
  3051. * @see java.awt.Container#validate
  3052. * @see #isValidateRoot
  3053. * @see RepaintManager#addInvalidComponent
  3054. */
  3055. public void revalidate() {
  3056. if (getParent() == null) {
  3057. invalidate();
  3058. }
  3059. else if (SwingUtilities.isEventDispatchThread()) {
  3060. invalidate();
  3061. RepaintManager.currentManager(this).addInvalidComponent(this);
  3062. }
  3063. else {
  3064. Runnable callRevalidate = new Runnable() {
  3065. public void run() {
  3066. revalidate();
  3067. }
  3068. };
  3069. SwingUtilities.invokeLater(callRevalidate);
  3070. }
  3071. }
  3072. /**
  3073. * If this method returns true, revalidate() calls by descendants of
  3074. * this component will cause the entire tree beginning with this root
  3075. * to be validated. Returns false by default. JScrollPane overrides
  3076. * this method and returns true.
  3077. *
  3078. * @return false
  3079. * @see #revalidate
  3080. * @see java.awt.Component#invalidate
  3081. * @see java.awt.Container#validate
  3082. */
  3083. public boolean isValidateRoot() {
  3084. return false;
  3085. }
  3086. /**
  3087. * Returns true if this component tiles its children, i.e. if
  3088. * it can guarantee that the children will not overlap. The
  3089. * repainting system is substantially more efficient in this
  3090. * common case. JComponent subclasses that can't make this
  3091. * guarantee, e.g. JLayeredPane, should override this method
  3092. * to return false.
  3093. *
  3094. * @return true if this components children don't overlap
  3095. */
  3096. public boolean isOptimizedDrawingEnabled() {
  3097. return true;
  3098. }
  3099. /**
  3100. * Paint the specified region in this component and all of its
  3101. * descendants that overlap the region, immediately.
  3102. * <p>
  3103. * It's rarely neccessary to call this method. In most cases it's
  3104. * more efficient to call repaint which defers the actual painting
  3105. * and can collapse redundant requests into a single paint call.
  3106. * This method is useful if one needs to update the display while
  3107. * the current event is being dispatched.
  3108. *
  3109. * @see #repaint
  3110. */
  3111. public void paintImmediately(int x,int y,int w, int h) {
  3112. Component c = this;
  3113. Component parent;
  3114. Rectangle bounds;
  3115. if(!isShowing()) {
  3116. return;
  3117. }
  3118. while(!((JComponent)c).isOpaque()) {
  3119. parent = c.getParent();
  3120. if(parent != null) {
  3121. if(c instanceof JComponent) {
  3122. bounds = ((JComponent)c)._bounds;
  3123. } else {
  3124. bounds = c.getBounds();
  3125. }
  3126. x += bounds.x;
  3127. y += bounds.y;
  3128. c = parent;
  3129. } else {
  3130. break;
  3131. }
  3132. if(!(c instanceof JComponent)) {
  3133. break;
  3134. }
  3135. }
  3136. if(c instanceof JComponent) {
  3137. ((JComponent)c)._paintImmediately(x,y,w,h);
  3138. } else {
  3139. c.repaint(x,y,w,h);
  3140. }
  3141. }
  3142. /**
  3143. * Paint the specified region now.
  3144. * <p>
  3145. * This method will migrate to java.awt.Component in the next major JDK release
  3146. */
  3147. public void paintImmediately(Rectangle r) {
  3148. paintImmediately(r.x,r.y,r.width,r.height);
  3149. }
  3150. /**
  3151. * Return whether this component should be guaranteed to be on top.
  3152. * For examples, it would make no sense for Menus to pop up under
  3153. * another component, so they would always return true. Most components
  3154. * will want to return false, hence that is the default.
  3155. */
  3156. // package private
  3157. boolean alwaysOnTop() {
  3158. return false;
  3159. }
  3160. private Rectangle paintImmediatelyClip = new Rectangle(0,0,0,0);
  3161. void setPaintingChild(Component paintingChild) {
  3162. this.paintingChild = paintingChild;
  3163. }
  3164. void _paintImmediately(int x, int y, int w, int h) {
  3165. Graphics g;
  3166. Container c;
  3167. Rectangle b;
  3168. int tmpX, tmpY, tmpWidth, tmpHeight;
  3169. int offsetX=0,offsetY=0;
  3170. boolean hasBuffer = false;
  3171. JComponent bufferedComponent = null;
  3172. JComponent paintingComponent = this;
  3173. RepaintManager repaintManager = RepaintManager.currentManager(this);
  3174. // parent Container's up to Window or Applet. First container is
  3175. // the direct parent. Note that in testing it was faster to
  3176. // alloc a new Vector vs keeping a stack of them around, and gc
  3177. // seemed to have a minimal effect on this.
  3178. Vector path = new Vector(7);
  3179. int pIndex = -1;
  3180. int pCount = 0;
  3181. tmpX = tmpY = tmpWidth = tmpHeight = 0;
  3182. paintImmediatelyClip.x = x;
  3183. paintImmediatelyClip.y = y;
  3184. paintImmediatelyClip.width = w;
  3185. paintImmediatelyClip.height = h;
  3186. // System.out.println("1) ************* in _paintImmediately for " + this);
  3187. boolean ontop = alwaysOnTop() && isOpaque();
  3188. for (c = this; c != null && !(c instanceof Window) && !(c instanceof Applet); c = c.getParent()) {
  3189. path.addElement(c);
  3190. if(!ontop && (c instanceof JComponent) &&
  3191. !(((JComponent)c).isOptimizedDrawingEnabled())) {
  3192. paintingComponent = (JComponent)c;
  3193. pIndex = pCount;
  3194. offsetX = offsetY = 0;
  3195. hasBuffer = false; /** Get rid of any buffer since we draw from here and
  3196. * we might draw something larger
  3197. */
  3198. }
  3199. pCount++;
  3200. // look to see if the parent (and therefor this component)
  3201. // is double buffered
  3202. if(repaintManager.isDoubleBufferingEnabled() &&
  3203. (c instanceof JComponent) && ((JComponent)c).isDoubleBuffered()) {
  3204. hasBuffer = true;
  3205. bufferedComponent = (JComponent) c;
  3206. }
  3207. // if we aren't on top, include the parent's clip
  3208. if(!ontop) {
  3209. if(c instanceof JComponent) {
  3210. b = ((JComponent)c)._bounds;
  3211. } else {
  3212. b = c.getBounds();
  3213. }
  3214. tmpWidth = b.width;
  3215. tmpHeight = b.height;
  3216. SwingUtilities.computeIntersection(tmpX,tmpY,tmpWidth,tmpHeight,paintImmediatelyClip);
  3217. paintImmediatelyClip.x += b.x;
  3218. paintImmediatelyClip.y += b.y;
  3219. offsetX += b.x;
  3220. offsetY += b.y;
  3221. }
  3222. }
  3223. if(c == null || c.getPeer() == null) {
  3224. return;
  3225. }
  3226. // If the clip width or height is negative, don't bother painting
  3227. if(paintImmediatelyClip.width <= 0 || paintImmediatelyClip.height <= 0) {
  3228. return;
  3229. }
  3230. paintImmediatelyClip.x -= offsetX;
  3231. paintImmediatelyClip.y -= offsetY;
  3232. // Notify the Components that are going to be painted of the
  3233. // child component to paint to.
  3234. if(paintingComponent != this) {
  3235. Component comp;
  3236. int i = pIndex;
  3237. for(; i > 0 ; i--) {
  3238. comp = (Component) path.elementAt(i);
  3239. if(comp instanceof JComponent) {
  3240. ((JComponent)comp).setPaintingChild
  3241. ((Component)path.elementAt(i-1));
  3242. }
  3243. }
  3244. }
  3245. try {
  3246. try {
  3247. Graphics pcg = paintingComponent.getGraphics();
  3248. g = SwingGraphics.createSwingGraphics(pcg);
  3249. pcg.dispose();
  3250. } catch(NullPointerException e) {
  3251. g = null;
  3252. e.printStackTrace();
  3253. }
  3254. if(g == null) {
  3255. System.err.println("In paintImmediately null graphics");
  3256. return;
  3257. }
  3258. Image offscreen;
  3259. if(hasBuffer && (offscreen = repaintManager.getOffscreenBuffer
  3260. (bufferedComponent,paintImmediatelyClip.width,
  3261. paintImmediatelyClip.height)) != null &&
  3262. offscreen.getWidth(null) > 0 &&
  3263. offscreen.getHeight(null) > 0) {
  3264. paintWithBuffer(paintingComponent,g,paintImmediatelyClip,
  3265. offscreen);
  3266. g.dispose();
  3267. } else {
  3268. //System.out.println("has no buffer");
  3269. g.setClip(paintImmediatelyClip.x,paintImmediatelyClip.y,
  3270. paintImmediatelyClip.width,paintImmediatelyClip.height);
  3271. try {
  3272. paintingComponent.paint(g);
  3273. } finally {
  3274. g.dispose();
  3275. }
  3276. }
  3277. }
  3278. finally {
  3279. // Reset the painting child for the parent components.
  3280. if(paintingComponent != this) {
  3281. Component comp;
  3282. int i = pIndex;
  3283. for(; i > 0 ; i--) {
  3284. comp = (Component) path.elementAt(i);
  3285. if(comp instanceof JComponent) {
  3286. ((JComponent)comp).setPaintingChild(null);
  3287. }
  3288. }
  3289. }
  3290. path.removeAllElements();
  3291. }
  3292. }
  3293. private void paintWithBuffer(JComponent paintingComponent,Graphics g,Rectangle clip,Image offscreen) {
  3294. Graphics og = SwingGraphics.createSwingGraphics(offscreen.getGraphics());
  3295. int bw = offscreen.getWidth(null);
  3296. int bh = offscreen.getHeight(null);
  3297. int x,y,maxx,maxy;
  3298. if(bw > clip.width) {
  3299. bw = clip.width;
  3300. }
  3301. if(bh > clip.height) {
  3302. bh = clip.height;
  3303. }
  3304. try {
  3305. paintingComponent.setFlag(ANCESTOR_USING_BUFFER,true);
  3306. paintingComponent.setFlag(IS_PAINTING_TILE,true);
  3307. for(x = clip.x, maxx = clip.x+clip.width;
  3308. x < maxx ; x += bw ) {
  3309. for(y=clip.y, maxy = clip.y + clip.height;
  3310. y < maxy ; y += bh) {
  3311. if((y+bh) >= maxy && (x+bw) >= maxx) {
  3312. paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3313. }
  3314. og.translate(-x,-y);
  3315. og.setClip(x,y,bw,bh);
  3316. paintingComponent.paint(og);
  3317. g.setClip(x,y,bw,bh);
  3318. g.drawImage(offscreen,x,y,paintingComponent);
  3319. og.translate(x,y);
  3320. }
  3321. }
  3322. } finally {
  3323. paintingComponent.setFlag(ANCESTOR_USING_BUFFER,false);
  3324. paintingComponent.setFlag(IS_PAINTING_TILE,false);
  3325. og.dispose();
  3326. }
  3327. }
  3328. /**
  3329. * Return true if the component at index compIndex is obscured by
  3330. * an opaque sibling that is painted after it.
  3331. * The rectangle is in the receiving component coordinate system.
  3332. */
  3333. // NOTE: This will tweak tmpRect!
  3334. boolean rectangleIsObscuredBySibling(int compIndex, int x, int y,
  3335. int width, int height) {
  3336. int i;
  3337. Component sibling;
  3338. Rectangle siblingRect;
  3339. for(i = compIndex - 1 ; i >= 0 ; i--) {
  3340. sibling = getComponent(i);
  3341. if(!sibling.isVisible())
  3342. continue;
  3343. if(sibling instanceof JComponent) {
  3344. if(!((JComponent)sibling).isOpaque())
  3345. continue;
  3346. siblingRect = ((JComponent)sibling).getBounds(tmpRect);
  3347. }
  3348. else {
  3349. siblingRect = sibling.getBounds();
  3350. }
  3351. // NOTE(sky): I could actually intersect x,y,width,height here.
  3352. // This tests for COMPLETE obscuring by another component,
  3353. // if multiple siblings obscure the region true should be
  3354. // returned.
  3355. if (x >= siblingRect.x && (x + width) <=
  3356. (siblingRect.x + siblingRect.width) &&
  3357. y >= siblingRect.y && (y + height) <=
  3358. (siblingRect.y + siblingRect.height)) {
  3359. return true;
  3360. }
  3361. }
  3362. return false;
  3363. }
  3364. /**
  3365. * Returns true, which implies that before checking if a child should
  3366. * be painted it is first check that the child is not obscured by another
  3367. * sibling. This is only checked if <code>isOptimizedDrawingEnabled</code>
  3368. * return false.
  3369. */
  3370. boolean checkIfChildObscuredBySibling() {
  3371. return true;
  3372. }
  3373. private void setFlag(int aFlag, boolean aValue) {
  3374. if(aValue) {
  3375. flags |= (1 << aFlag);
  3376. } else {
  3377. flags &= ~(1 << aFlag);
  3378. }
  3379. }
  3380. private boolean getFlag(int aFlag) {
  3381. int mask = (1 << aFlag);
  3382. return ((flags & mask) == mask);
  3383. }
  3384. /** Buffering **/
  3385. /** Set whether the receiving component should use a buffer to paint.
  3386. * If set to true, all the drawing from this component will be done
  3387. * in an offscreen painting buffer. The offscreen painting buffer will
  3388. * the be copied onto the screen.
  3389. * Swing's painting system always use a maximum of one double buffer.
  3390. * If a Component is buffered and one of its ancestor is also buffered,
  3391. * the ancestor buffer will be used.
  3392. */
  3393. public void setDoubleBuffered(boolean aFlag) {
  3394. setFlag(IS_DOUBLE_BUFFERED,aFlag);
  3395. }
  3396. /** Return whether the receiving component should use a buffer to paint. **/
  3397. public boolean isDoubleBuffered() {
  3398. return getFlag(IS_DOUBLE_BUFFERED);
  3399. }
  3400. /**
  3401. * Returns the JRootPane ancestor for a component
  3402. *
  3403. * @return the JRootPane that contains this component,
  3404. * or null if no JRootPane is found
  3405. */
  3406. public JRootPane getRootPane() {
  3407. return SwingUtilities.getRootPane(this);
  3408. }
  3409. /** Serialization **/
  3410. /**
  3411. * This class is used to give us an oppportunity to uninstall the UI
  3412. * before java.awt.Container.writeObject() runs. The enableSerialization()
  3413. * method belows adds an instance of this class to the FocusListener
  3414. * field in java.awt.Component. The java.awt.Component.writeObject()
  3415. * method, which always runs before java.awt.Container.writeObject(),
  3416. * effectively calls our writeObject method which takes care of uninstalling
  3417. * the UI.
  3418. * <p>
  3419. * A FocusListener is used (any listener would do) because all Swing
  3420. * components listen for Focus events anyway.
  3421. * <p>
  3422. * Yes this is a hack. Unfortunately we don't know of a better way to make
  3423. * the UI property transient and work correctly on JDK1.1 VMs.
  3424. */
  3425. private class EnableSerializationFocusListener implements FocusListener, Serializable
  3426. {
  3427. public void focusGained(FocusEvent e) {}
  3428. public void focusLost(FocusEvent e) {}
  3429. private void writeObject(ObjectOutputStream s) throws IOException {
  3430. boolean internalFrameCheck = false;
  3431. boolean old = false;
  3432. JInternalFrame j = null;
  3433. s.defaultWriteObject();
  3434. if (ui != null) {
  3435. // need to disable rootpane checking for InternalFrame: 4172083
  3436. if (JComponent.this instanceof JInternalFrame){
  3437. j = (JInternalFrame)JComponent.this;
  3438. internalFrameCheck = true;
  3439. old = j.isRootPaneCheckingEnabled();
  3440. j.setRootPaneCheckingEnabled(false);
  3441. }
  3442. ui.uninstallUI(JComponent.this);
  3443. if (internalFrameCheck){
  3444. j.setRootPaneCheckingEnabled(old);
  3445. j = null;
  3446. }
  3447. }
  3448. if (getToolTipText() != null) {
  3449. ToolTipManager.sharedInstance().unregisterComponent(JComponent.this);
  3450. }
  3451. }
  3452. }
  3453. /**
  3454. * Called by the JComponent constructor. Adds a fake FocusListener
  3455. * whose real purpose is to uninstall the components UI early.
  3456. */
  3457. void enableSerialization() {
  3458. addFocusListener(new EnableSerializationFocusListener());
  3459. }
  3460. /**
  3461. * This object is the ObjectInputStream callback that's called after
  3462. * a complete graph of objects (including at least one JComponent)
  3463. * has been read. It sets the UI property of each Swing component
  3464. * that was read to the current default with updateUI().
  3465. * <p>
  3466. * As each component is read in we keep track of the current set of
  3467. * root components here, in the roots vector. Note that there's only one
  3468. * ReadObjectCallback per ObjectInputStream, they're stored in
  3469. * the static readObjectCallbacks hashtable.
  3470. *
  3471. * @see java.io.ObjectInputStream#registerValidation
  3472. * @see SwingUtilities#updateComponentTreeUI
  3473. */
  3474. private class ReadObjectCallback implements ObjectInputValidation
  3475. {
  3476. private final Vector roots = new Vector(1);
  3477. private final ObjectInputStream inputStream;
  3478. ReadObjectCallback(ObjectInputStream s) throws Exception {
  3479. inputStream = s;
  3480. s.registerValidation(this, 0);
  3481. }
  3482. /**
  3483. * This is the method that's called after the entire graph
  3484. * of objects has been read in. It initializes
  3485. * the UI property of all of the copmonents with
  3486. * SwingUtilities.updateComponentTreeUI().
  3487. */
  3488. public void validateObject() throws InvalidObjectException {
  3489. try {
  3490. for(int i = 0; i < roots.size(); i++) {
  3491. JComponent root = (JComponent)(roots.elementAt(i));
  3492. SwingUtilities.updateComponentTreeUI(root);
  3493. }
  3494. }
  3495. finally {
  3496. readObjectCallbacks.remove(inputStream);
  3497. }
  3498. }
  3499. /**
  3500. * If c isn't a descendant of a component we've already
  3501. * seen, then add it to the roots Vector.
  3502. */
  3503. private void registerComponent(JComponent c)
  3504. {
  3505. /* If the Component c is a descendant of one of the
  3506. * existing roots (or it IS an existing root), we're done.
  3507. */
  3508. for(int i = 0; i < roots.size(); i++) {
  3509. JComponent root = (JComponent)roots.elementAt(i);
  3510. for(Component p = c; p != null; p = p.getParent()) {
  3511. if (p == root) {
  3512. return;
  3513. }
  3514. }
  3515. }
  3516. /* Otherwise: if Component c is an ancestor of any of the
  3517. * existing roots then remove them and add c (the "new root")
  3518. * to the roots vector.
  3519. */
  3520. for(int i = 0; i < roots.size(); i++) {
  3521. JComponent root = (JComponent)roots.elementAt(i);
  3522. for(Component p = root.getParent(); p != null; p = p.getParent()) {
  3523. if (p == c) {
  3524. roots.removeElementAt(i--); // !!
  3525. break;
  3526. }
  3527. }
  3528. }
  3529. roots.addElement(c);
  3530. }
  3531. }
  3532. /**
  3533. * We use the ObjectInputStream "registerValidation" callback to
  3534. * update the UI for the entire tree of components after they've
  3535. * all been read in.
  3536. *
  3537. * @see ReadObjectCallback
  3538. */
  3539. private void readObject(ObjectInputStream s)
  3540. throws IOException, ClassNotFoundException
  3541. {
  3542. s.defaultReadObject();
  3543. /* If there's no ReadObjectCallback for this stream yet, i.e. if
  3544. * this is the first call to JComponent.readObject() for this
  3545. * graph of objects, then create a callback and stash it
  3546. * in the readObjectCallbacks table. Note that the ReadObjectCallback
  3547. * constructor takes care of calling s.registerValidation().
  3548. */
  3549. ReadObjectCallback cb = (ReadObjectCallback)(readObjectCallbacks.get(s));
  3550. if (cb == null) {
  3551. try {
  3552. readObjectCallbacks.put(s, cb = new ReadObjectCallback(s));
  3553. }
  3554. catch (Exception e) {
  3555. throw new IOException(e.toString());
  3556. }
  3557. }
  3558. cb.registerComponent(this);
  3559. if (getToolTipText() != null) {
  3560. ToolTipManager.sharedInstance().registerComponent(this);
  3561. }
  3562. }
  3563. /**
  3564. * Before writing a JComponent to an ObjectOutputStream we temporarily
  3565. * uninstall its UI. This is tricky to do because we want to uninstall
  3566. * the UI before any of the JComponents children (or its LayoutManager etc.)
  3567. * are written, and we don't want to restore the UI until the most derived
  3568. * JComponent subclass has been been stored.
  3569. */
  3570. private void writeObject(ObjectOutputStream s) throws IOException {
  3571. s.defaultWriteObject();
  3572. if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  3573. ui.installUI(this);
  3574. }
  3575. }
  3576. /**
  3577. * Returns a string representation of this JComponent. This method
  3578. * is intended to be used only for debugging purposes, and the
  3579. * content and format of the returned string may vary between
  3580. * implementations. The returned string may be empty but may not
  3581. * be <code>null</code>.
  3582. *
  3583. * @return a string representation of this JComponent.
  3584. */
  3585. protected String paramString() {
  3586. String preferredSizeString = (preferredSize != null ?
  3587. preferredSize.toString() : "");
  3588. String minimumSizeString = (minimumSize != null ?
  3589. minimumSize.toString() : "");
  3590. String maximumSizeString = (maximumSize != null ?
  3591. maximumSize.toString() : "");
  3592. String borderString = (border != null ?
  3593. border.toString() : "");
  3594. return super.paramString() +
  3595. ",alignmentX=" + alignmentX +
  3596. ",alignmentY=" + alignmentY +
  3597. ",border=" + borderString +
  3598. ",flags=" + flags + // should beef this up a bit
  3599. ",maximumSize=" + maximumSizeString +
  3600. ",minimumSize=" + minimumSizeString +
  3601. ",preferredSize=" + preferredSizeString;
  3602. }
  3603. }