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