1. /*
  2. * @(#)JComponent.java 2.113 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.util.Hashtable;
  9. import java.util.Dictionary;
  10. import java.util.Enumeration;
  11. import java.util.Locale;
  12. import java.util.Vector;
  13. import java.awt.*;
  14. import java.awt.event.*;
  15. import java.beans.*;
  16. import java.applet.Applet;
  17. import java.io.Serializable;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. import java.io.ObjectInputValidation;
  22. import java.io.InvalidObjectException;
  23. import javax.swing.border.*;
  24. import javax.swing.event.*;
  25. import javax.swing.plaf.*;
  26. import javax.accessibility.*;
  27. import java.awt.Graphics2D;
  28. /**
  29. * The base class for the Swing components. JComponent provides:
  30. * <ul>
  31. * <li>A "pluggable look and feel" (l&f) that can be specified by the
  32. * programmer or (optionally) selected by the user at runtime.
  33. * <li>Components that are designed to be combined and extended in order
  34. * to create custom components.
  35. * <li>Comprehensive keystroke-handling that works with nested components.
  36. * <li>Action objects, for single-point control of program actions initiated
  37. * by multiple components.
  38. * <li>A border property that implicitly defines the component's insets.
  39. * <li>The ability to set the preferred, minimim, and maximum size for a
  40. * component.
  41. * <li>ToolTips -- short descriptions that pop up when the cursor lingers
  42. * over a component.
  43. * <li>Autoscrolling -- automatic scrolling in a list, table, or tree that
  44. * occurs when the user is dragging the mouse.
  45. * <li>Simple, easy dialog construction using static methods in the JOptionPane
  46. * class that let you display information and query the user.
  47. * <li>Slow-motion graphics rendering using debugGraphics so you can see
  48. * what is being displayed on screen and whether or not it is being
  49. * overwritten.
  50. * <li>Support for Accessibility.
  51. * <li>Support for international Localization.
  52. * </ul>
  53. * For more information on these subjects, see the
  54. * <a href="package-summary.html#package_description">Swing package description</a>
  55. * <p>
  56. * <strong>Warning:</strong>
  57. * Serialized objects of this class will not be compatible with
  58. * future Swing releases. The current serialization support is appropriate
  59. * for short term storage or RMI between applications running the same
  60. * version of Swing. A future release of Swing will provide support for
  61. * long term persistence.
  62. *
  63. * @see KeyStroke
  64. * @see Action
  65. * @see #setBorder
  66. * @see #registerKeyboardAction
  67. * @see JOptionPane
  68. * @see #setDebugGraphicsOptions
  69. * @see #setToolTipText
  70. * @see #setAutoscrolls
  71. *
  72. * @version 2.113 11/29/01
  73. * @author Hans Muller
  74. * @author Arnaud Weber
  75. */
  76. public abstract class JComponent extends Container implements Serializable
  77. {
  78. /**
  79. * @see #getUIClassID
  80. * @see #writeObject
  81. */
  82. private static final String uiClassID = "ComponentUI";
  83. /**
  84. * @see ReadObjectCallback
  85. * @se #readObject
  86. */
  87. private static final Hashtable readObjectCallbacks = new Hashtable(1);
  88. /* The following fields support set methods for the corresponding
  89. * java.awt.Component properties.
  90. */
  91. private Dimension preferredSize;
  92. private Dimension minimumSize;
  93. private Dimension maximumSize;
  94. private Float alignmentX;
  95. private Float alignmentY;
  96. private AncestorNotifier ancestorNotifier;
  97. Rectangle _bounds = new Rectangle();
  98. /* Backing store for JComponent properties and listeners
  99. */
  100. protected transient ComponentUI ui;
  101. protected EventListenerList listenerList = new EventListenerList();
  102. private Hashtable clientProperties;
  103. private VetoableChangeSupport vetoableChangeSupport;
  104. private Autoscroller autoscroller;
  105. private Border border;
  106. private int flags;
  107. /* A "scratch pad" rectangle used by the painting code.
  108. */
  109. private transient Rectangle tmpRect;
  110. /** Set in _paintImmediately. Will indicate the child that initiated
  111. * the painting operation. If paintingChild is opaque, no need to paint
  112. * any child components after paintingChild. Test used in paintChildren. */
  113. transient Component paintingChild;
  114. /**
  115. * Constant used for registerKeyboardAction() which
  116. * means that the command should be invoked when
  117. * the component has the focus.
  118. */
  119. public static final int WHEN_FOCUSED = 0;
  120. /**
  121. * Constant used for registerKeyboardAction() which
  122. * means that the comand should be invoked when the receiving
  123. * component is an ancestor of the focused component or is
  124. * itself the focused component.
  125. */
  126. public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
  127. /**
  128. * Constant used for registerKeyboardAction() which
  129. * means that the command should be invoked when
  130. * the receiving component is in the window that has the focus
  131. * or is itself the focused component.
  132. */
  133. public static final int WHEN_IN_FOCUSED_WINDOW = 2;
  134. /**
  135. * Constant used by some of the apis to mean that no condition is defined.
  136. */
  137. public static final int UNDEFINED_CONDITION = -1;
  138. /**
  139. * The key used by JComponent to access keyboard bindings.
  140. */
  141. private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
  142. /**
  143. * The comment to display when the cursor is over the component,
  144. * also known as a "value tip", "flyover help", or "flyover label".
  145. */
  146. public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
  147. private static final String NEXT_FOCUS = "nextFocus";
  148. /** Private flags **/
  149. private static final int REQUEST_FOCUS_DISABLED = 0;
  150. private static final int IS_DOUBLE_BUFFERED = 1;
  151. private static final int ANCESTOR_USING_BUFFER = 2;
  152. private static final int IS_PAINTING_TILE = 3;
  153. private static final int HAS_FOCUS = 4;
  154. private static final int IS_OPAQUE = 5;
  155. private static final int IS_PRINTING = 12;
  156. private static final int IS_PRINTING_ALL = 13;
  157. /**
  158. * Default JComponent constructor. This constructor does
  159. * no initialization beyond calling the Container constructor,
  160. * e.g. the initial layout manager is null.
  161. */
  162. public JComponent() {
  163. super();
  164. enableEvents(AWTEvent.FOCUS_EVENT_MASK);
  165. enableSerialization();
  166. }
  167. /**
  168. * Resets the UI property to a value from the current look and feel.
  169. * JComponent subclasses must override this method like this:
  170. * <pre>
  171. * public void updateUI() {
  172. * setUI((SliderUI)UIManager.getUI(this);
  173. * }
  174. * </pre>
  175. *
  176. * @see #setUI
  177. * @see UIManager#getLookAndFeel
  178. * @see UIManager#getUI
  179. */
  180. public void updateUI() {}
  181. /**
  182. * Set the look and feel delegate for this component.
  183. * JComponent subclasses generally override this method
  184. * to narrow the argument type, e.g. in JSlider:
  185. * <pre>
  186. * public void setUI(SliderUI newUI) {
  187. * super.setUI(newUI);
  188. * }
  189. * </pre>
  190. * <p>
  191. * Additionaly JComponent subclasses must provide a getUI
  192. * method that returns the correct type, e.g.
  193. * <pre>
  194. * public SliderUI getUI() {
  195. * return (SliderUI)ui;
  196. * }
  197. * </pre>
  198. *
  199. * @see #updateUI
  200. * @see UIManager#getLookAndFeel
  201. * @see UIManager#getUI
  202. * @beaninfo
  203. * bound: true
  204. * attribute: visualUpdate true
  205. * description: The component's look and feel delegate
  206. */
  207. protected void setUI(ComponentUI newUI) {
  208. /* We do not check that the UI instance is different
  209. * before allowing the switch in order to enable the
  210. * same UI instance *with different default settings*
  211. * to be installed.
  212. */
  213. if (ui != null) {
  214. ui.uninstallUI(this);
  215. }
  216. ComponentUI oldUI = ui;
  217. ui = newUI;
  218. if (ui != null) {
  219. ui.installUI(this);
  220. }
  221. firePropertyChange("UI", oldUI, newUI);
  222. revalidate();
  223. repaint();
  224. }
  225. /**
  226. * Return the UIDefaults key used to look up the name of the
  227. * swing.plaf.ComponentUI class that defines the look and feel
  228. * for this component. Most applications will never need to
  229. * call this method. Subclasses of JComponent that support
  230. * pluggable look and feel should override this method to
  231. * return a UIDefaults key that maps to the ComponentUI subclass
  232. * that defines their look and feel.
  233. *
  234. * @return The UIDefaults key for a ComponentUI subclass.
  235. * @see UIDefaults#getUI
  236. * @beaninfo
  237. * expert: true
  238. * description: UIClassID
  239. */
  240. public String getUIClassID() {
  241. return uiClassID;
  242. }
  243. /**
  244. * Returns the graphics object used to paint this component.
  245. * If DebugGraphics is turned on we create a new DebugGraphics
  246. * object if neccessary otherwise we just configure the
  247. * specified graphics objects foreground and font.
  248. *
  249. * @return A Graphics object configured for this component
  250. */
  251. protected Graphics getComponentGraphics(Graphics g) {
  252. Graphics componentGraphics = g;
  253. if (ui != null) {
  254. if ((DebugGraphics.debugComponentCount() != 0) &&
  255. (shouldDebugGraphics() != 0) &&
  256. !(g instanceof DebugGraphics)) {
  257. if(g instanceof SwingGraphics) {
  258. if(!(((SwingGraphics)g).subGraphics() instanceof DebugGraphics)) {
  259. componentGraphics = new DebugGraphics(((SwingGraphics)g).subGraphics(),this);
  260. componentGraphics = SwingGraphics.createSwingGraphics(componentGraphics);
  261. }
  262. } else {
  263. componentGraphics = new DebugGraphics(g,this);
  264. }
  265. }
  266. }
  267. componentGraphics.setColor(getForeground());
  268. componentGraphics.setFont(getFont());
  269. return componentGraphics;
  270. }
  271. /**
  272. * If the UI delegate is non-null, call its paint
  273. * method. We pass the delegate a copy of the Graphics
  274. * object to protect the rest of the paint code from
  275. * irrevocable changes (e.g. Graphics.translate()).
  276. *
  277. * @see #paint
  278. */
  279. protected void paintComponent(Graphics g) {
  280. if (ui != null) {
  281. Graphics scratchGraphics = SwingGraphics.createSwingGraphics(g);
  282. try {
  283. ui.update(scratchGraphics, this);
  284. }
  285. finally {
  286. scratchGraphics.dispose();
  287. }
  288. }
  289. }
  290. /**
  291. * Paint this component's children.
  292. * If shouldUseBuffer is true, no component ancestor has a buffer and
  293. * the component children can use a buffer if they have one.
  294. * Otherwise, one ancestor has a buffer currently in use and children
  295. * should not use a buffer to paint.
  296. * @see #paint
  297. * @see java.awt.Container#paint
  298. */
  299. protected void paintChildren(Graphics g) {
  300. boolean isJComponent;
  301. Graphics sg = null;
  302. try {
  303. synchronized(getTreeLock()) {
  304. boolean printing = getFlag(IS_PRINTING);
  305. int i = getComponentCount() - 1;
  306. if (i < 0) {
  307. return;
  308. }
  309. sg = SwingGraphics.createSwingGraphics(g);
  310. // If we are only to paint to a specific child, determine
  311. // its index.
  312. if (paintingChild != null &&
  313. (paintingChild instanceof JComponent) &&
  314. ((JComponent)paintingChild).isOpaque()) {
  315. for (; i >= 0; i--) {
  316. if (getComponent(i) == paintingChild){
  317. break;
  318. }
  319. }
  320. }
  321. if(tmpRect == null) {
  322. tmpRect = new Rectangle();
  323. }
  324. boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
  325. checkIfChildObscuredBySibling());
  326. Rectangle clipBounds = null;
  327. if (checkSiblings) {
  328. clipBounds = sg.getClipBounds();
  329. if (clipBounds == null) {
  330. clipBounds = new Rectangle(0, 0, _bounds.width,
  331. _bounds.height);
  332. }
  333. }
  334. for (; i >= 0 ; i--) {
  335. Component comp = getComponent(i);
  336. if (comp != null && isLightweightComponent(comp) &&
  337. (comp.isVisible() == true)) {
  338. Rectangle cr;
  339. isJComponent = (comp instanceof JComponent);
  340. if(isJComponent) {
  341. cr = tmpRect;
  342. ((JComponent)comp).getBounds(cr);
  343. } else {
  344. cr = comp.getBounds();
  345. }
  346. boolean hitClip =
  347. g.hitClip(cr.x, cr.y, cr.width, cr.height);
  348. if (hitClip) {
  349. if (checkSiblings && i > 0) {
  350. int x = cr.x;
  351. int y = cr.y;
  352. int width = cr.width;
  353. int height = cr.height;
  354. SwingUtilities.computeIntersection
  355. (clipBounds.x, clipBounds.y,
  356. clipBounds.width, clipBounds.height, cr);
  357. if(rectangleIsObscuredBySibling(i, cr.x, cr.y,
  358. cr.width, cr.height)) {
  359. continue;
  360. }
  361. cr.x = x;
  362. cr.y = y;
  363. cr.width = width;
  364. cr.height = height;
  365. }
  366. Graphics cg = SwingGraphics.createSwingGraphics(
  367. sg, cr.x, cr.y, cr.width, cr.height);
  368. cg.setColor(comp.getForeground());
  369. cg.setFont(comp.getFont());
  370. boolean shouldSetFlagBack = false;
  371. try {
  372. if(isJComponent) {
  373. if(getFlag(ANCESTOR_USING_BUFFER)) {
  374. ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,true);
  375. shouldSetFlagBack = true;
  376. }
  377. if(getFlag(IS_PAINTING_TILE)) {
  378. ((JComponent)comp).setFlag(IS_PAINTING_TILE,true);
  379. shouldSetFlagBack = true;
  380. }
  381. if(!printing) {
  382. ((JComponent)comp).paint(cg);
  383. }
  384. else {
  385. if (!getFlag(IS_PRINTING_ALL)) {
  386. comp.print(cg);
  387. }
  388. else {
  389. comp.printAll(cg);
  390. }
  391. }
  392. } else {
  393. if (!printing) {
  394. comp.paint(cg);
  395. }
  396. else {
  397. if (!getFlag(IS_PRINTING_ALL)) {
  398. comp.print(cg);
  399. }
  400. else {
  401. comp.printAll(cg);
  402. }
  403. }
  404. }
  405. } finally {
  406. cg.dispose();
  407. if(shouldSetFlagBack) {
  408. ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,false);
  409. ((JComponent)comp).setFlag(IS_PAINTING_TILE,false);
  410. }
  411. }
  412. }
  413. }
  414. }
  415. }
  416. } finally {
  417. if (sg != null) {
  418. sg.dispose();
  419. }
  420. }
  421. }
  422. /**
  423. * Paint the component's border.
  424. *
  425. * @see #paint
  426. * @see #setBorder
  427. */
  428. protected void paintBorder(Graphics g) {
  429. Border border = getBorder();
  430. if (border != null) {
  431. border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
  432. }
  433. }
  434. /**
  435. * Calls paint(g). Doesn't clear the background but see
  436. * ComponentUI.update() which is called by paintComponent.
  437. *
  438. * @see #paint
  439. * @see #paintComponent
  440. * @see javax.swing.plaf.ComponentUI
  441. */
  442. public void update(Graphics g) {
  443. paint(g);
  444. }
  445. /**
  446. * This method is invoked by Swing to draw components.
  447. * Applications should not invoke paint directly,
  448. * but should instead use the <code>repaint</code> method to
  449. * schedule the component for redrawing.
  450. * <p>
  451. * This method actually delegates the work of painting to three
  452. * protected methods: <code>paintComponent</code>, <code>paintBorder</code>,
  453. * and <code>paintChildren</code>. They're called in the order
  454. * listed to ensure that children appear on top of component itself.
  455. * Generally speaking, the component and its children should not
  456. * paint in the insets area allocated to the border. Subclasses can
  457. * just override this method, as always. A subclass that just
  458. * wants to specialize the UI (look and feel) delegates paint
  459. * method should just override <code>paintComponent</code>.
  460. *
  461. * @see #paintComponent
  462. * @see #paintBorder
  463. * @see #paintChildren
  464. * @see #getComponentGraphics
  465. * @see #repaint
  466. */
  467. public void paint(Graphics g) {
  468. boolean shouldClearPaintFlags = false;
  469. if ((getWidth() <= 0) || (getHeight() <= 0)) {
  470. return;
  471. }
  472. Graphics componentGraphics = getComponentGraphics(g);
  473. Graphics co = SwingGraphics.createSwingGraphics(componentGraphics);
  474. try {
  475. Image offscr = null;
  476. RepaintManager repaintManager = RepaintManager.currentManager(this);
  477. Rectangle clipRect = co.getClipBounds();
  478. int clipX;
  479. int clipY;
  480. int clipW;
  481. int clipH;
  482. if (clipRect == null) {
  483. clipX = clipY = 0;
  484. clipW = _bounds.width;
  485. clipH = _bounds.height;
  486. }
  487. else {
  488. clipX = clipRect.x;
  489. clipY = clipRect.y;
  490. clipW = clipRect.width;
  491. clipH = clipRect.height;
  492. }
  493. if(clipW > getWidth()) {
  494. clipW = getWidth();
  495. }
  496. if(clipH > getHeight()) {
  497. clipH = getHeight();
  498. }
  499. if(getParent() != null && !(getParent() instanceof JComponent)) {
  500. adjustPaintFlags();
  501. shouldClearPaintFlags = true;
  502. }
  503. int bw,bh;
  504. boolean printing = getFlag(IS_PRINTING);
  505. if(!printing && repaintManager.isDoubleBufferingEnabled() &&
  506. !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
  507. (offscr = repaintManager.getOffscreenBuffer
  508. (this,clipW,clipH)) != null &&
  509. (bw = offscr.getWidth(null)) > 0 &&
  510. (bh = offscr.getHeight(null)) > 0) {
  511. int x,y,maxx,maxy;
  512. Graphics sg =
  513. SwingGraphics.createSwingGraphics(offscr.getGraphics());
  514. try {
  515. sg.translate(-clipX,-clipY);
  516. bw = offscr.getWidth(null);
  517. bh = offscr.getHeight(null);
  518. if (bw > clipW) {
  519. bw = clipW;
  520. }
  521. if (bh > clipH) {
  522. bh = clipH;
  523. }
  524. setFlag(ANCESTOR_USING_BUFFER,true);
  525. setFlag(IS_PAINTING_TILE,true);
  526. for(x = 0, maxx = clipW; x < maxx ; x += bw ) {
  527. for(y=0, maxy = clipH; y < maxy ; y += bh) {
  528. if((y+bh) >= maxy && (x+bw) >= maxx)
  529. setFlag(IS_PAINTING_TILE,false);
  530. sg.translate(-x,-y);
  531. sg.setClip(clipX+x,clipY + y,bw,bh);
  532. if(!rectangleIsObscured(clipX,clipY,bw,bh)) {
  533. paintComponent(sg);
  534. paintBorder(sg);
  535. }
  536. paintChildren(sg);
  537. co.drawImage(offscr,clipX + x,clipY + y,this);
  538. sg.translate(x,y);
  539. }
  540. }
  541. } finally {
  542. setFlag(ANCESTOR_USING_BUFFER,false);
  543. setFlag(IS_PAINTING_TILE,false);
  544. sg.dispose();
  545. }
  546. } else {
  547. if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
  548. paintComponent(co);
  549. paintBorder(co);
  550. }
  551. paintChildren(co);
  552. }
  553. } finally {
  554. co.dispose();
  555. if(shouldClearPaintFlags) {
  556. setFlag(ANCESTOR_USING_BUFFER,false);
  557. setFlag(IS_PAINTING_TILE,false);
  558. setFlag(IS_PRINTING,false);
  559. setFlag(IS_PRINTING_ALL,false);
  560. }
  561. }
  562. }
  563. private void adjustPaintFlags() {
  564. JComponent jparent = null;
  565. Container parent;
  566. for(parent = getParent() ; parent != null ; parent =
  567. parent.getParent()) {
  568. if(parent instanceof JComponent) {
  569. jparent = (JComponent) parent;
  570. if(jparent.getFlag(ANCESTOR_USING_BUFFER))
  571. setFlag(ANCESTOR_USING_BUFFER, true);
  572. if(jparent.getFlag(IS_PAINTING_TILE))
  573. setFlag(IS_PAINTING_TILE, true);
  574. if(jparent.getFlag(IS_PRINTING))
  575. setFlag(IS_PRINTING, true);
  576. if(jparent.getFlag(IS_PRINTING_ALL))
  577. setFlag(IS_PRINTING_ALL, true);
  578. break;
  579. }
  580. }
  581. }
  582. public void printAll(Graphics g) {
  583. setFlag(IS_PRINTING_ALL, true);
  584. try {
  585. print(g);
  586. }
  587. finally {
  588. setFlag(IS_PRINTING_ALL, false);
  589. }
  590. }
  591. public void print(Graphics g) {
  592. setFlag(IS_PRINTING, true);
  593. try {
  594. paint(g);
  595. }
  596. finally {
  597. setFlag(IS_PRINTING, false);
  598. }
  599. }
  600. /**
  601. * Returns true if the receiving component is currently painting a tile.
  602. * If this method returns true, paint will be called again for another
  603. * tile. This method returns false if you are not painting a tile or
  604. * if the last tile is painted.
  605. * Use this method to keep some state you might need between tiles.
  606. */
  607. public boolean isPaintingTile() {
  608. return getFlag(IS_PAINTING_TILE);
  609. }
  610. /**
  611. * Override this method and return true if your component is the root of
  612. * of a component tree with its own focus cycle.
  613. */
  614. public boolean isFocusCycleRoot() {
  615. return false;
  616. }
  617. /**
  618. * Override this method and return true if your JComponent manages focus.
  619. * If your component manages focus, the focus manager will handle your
  620. * component's children. All key event will be sent to your key listener
  621. * including TAB and SHIFT+TAB. CONTROL + TAB and CONTROL + SHIFT + TAB
  622. * will move the focus to the next / previous component.
  623. */
  624. public boolean isManagingFocus() {
  625. return false;
  626. }
  627. /**
  628. * Specifies the next component to get the focus after this one,
  629. * for example, when the tab key is pressed. Invoke this method
  630. * to override the default focus-change sequence.
  631. * @beaninfo
  632. * expert: true
  633. * description: The next component to get focus after this one.
  634. */
  635. public void setNextFocusableComponent(Component aComponent) {
  636. putClientProperty(NEXT_FOCUS,aComponent);
  637. }
  638. /**
  639. * Return the next focusable component or null if the focus manager
  640. * should choose the next focusable component automatically
  641. */
  642. public Component getNextFocusableComponent() {
  643. return (Component) getClientProperty(NEXT_FOCUS);
  644. }
  645. /**
  646. * Set whether the receiving component can obtain the focus by
  647. * calling requestFocus. The default value is true.
  648. * Note: Setting this property to false will not prevent the focus
  649. * manager from setting the focus to this component, it will prevent
  650. * the component from getting the focus when the focus is requested
  651. * explicitly. Override isFocusTraversable and return false if the
  652. * component should never get the focus.
  653. * @beaninfo
  654. * expert: true
  655. * description: Whether the component can obtain the focus by calling requestFocus.
  656. */
  657. public void setRequestFocusEnabled(boolean aFlag) {
  658. setFlag(REQUEST_FOCUS_DISABLED,(aFlag ? false:true));
  659. }
  660. /** Return whether the receiving component can obtain the focus by
  661. * calling requestFocus
  662. * @see #setRequestFocusEnabled
  663. */
  664. public boolean isRequestFocusEnabled() {
  665. return (getFlag(REQUEST_FOCUS_DISABLED) ? false : true);
  666. }
  667. /** Set focus on the receiving component if isRequestFocusEnabled returns true **/
  668. public void requestFocus() {
  669. /* someone other then the focus manager is requesting focus,
  670. so we clear the focus manager's idea of focus history */
  671. FocusManager focusManager = FocusManager.getCurrentManager();
  672. if (focusManager instanceof DefaultFocusManager)
  673. ((DefaultFocusManager)focusManager).clearHistory();
  674. if(isRequestFocusEnabled()) {
  675. super.requestFocus();
  676. }
  677. }
  678. /** Set the focus on the receiving component. This method is for focus managers, you
  679. * rarely want to call this method, use requestFocus() enstead.
  680. */
  681. public void grabFocus() {
  682. super.requestFocus();
  683. }
  684. /**
  685. * Set the preferred size of the receiving component.
  686. * if <code>preferredSize</code> is null, the UI will
  687. * be asked for the preferred size
  688. * @beaninfo
  689. * preferred: true
  690. * bound: true
  691. * description: The preferred size of the component.
  692. */
  693. public void setPreferredSize(Dimension preferredSize) {
  694. Dimension old = this.preferredSize;
  695. this.preferredSize = preferredSize;
  696. firePropertyChange("preferredSize", old, preferredSize);
  697. }
  698. /**
  699. * If the preferredSize has been set to a non-null value
  700. * just return it. If the UI delegates getPreferredSize()
  701. * method returns a non null then value return that, otherwise
  702. * defer to the components layout manager.
  703. *
  704. * @return the value of the preferredSize property.
  705. * @see #setPreferredSize
  706. */
  707. public Dimension getPreferredSize() {
  708. if (preferredSize != null) {
  709. return preferredSize;
  710. }
  711. Dimension size = null;
  712. if (ui != null) {
  713. size = ui.getPreferredSize(this);
  714. }
  715. return (size != null) ? size : super.getPreferredSize();
  716. }
  717. /**
  718. * Sets the maximumSize of this component to a constant
  719. * value. Subsequent calls to getMaximumSize will always
  720. * return this value, the components UI will not be asked
  721. * to compute it. Setting the maximumSize to null
  722. * restores the default behavior.
  723. *
  724. * @see #getMaximumSize
  725. * @beaninfo
  726. * bound: true
  727. * description: The maximum size of the component.
  728. */
  729. public void setMaximumSize(Dimension maximumSize) {
  730. Dimension old = this.maximumSize;
  731. this.maximumSize = maximumSize;
  732. firePropertyChange("maximumSize", old, maximumSize);
  733. }
  734. /**
  735. * If the maximumSize has been set to a non-null value
  736. * just return it. If the UI delegates getMaximumSize()
  737. * method returns a non null value then return that, otherwise
  738. * defer to the components layout manager.
  739. *
  740. * @return the value of the maximumSize property.
  741. * @see #setMaximumSize
  742. */
  743. public Dimension getMaximumSize() {
  744. if (maximumSize != null) {
  745. return maximumSize;
  746. }
  747. Dimension size = null;
  748. if (ui != null) {
  749. size = ui.getMaximumSize(this);
  750. }
  751. return (size != null) ? size : super.getMaximumSize();
  752. }
  753. /**
  754. * Sets the minimumSize of this component to a constant
  755. * value. Subsequent calls to getMinimumSize will always
  756. * return this value, the components UI will not be asked
  757. * to compute it. Setting the minimumSize to null
  758. * restores the default behavior.
  759. *
  760. * @see #getMinimumSize
  761. * @beaninfo
  762. * bound: true
  763. * description: The minimum size of the component.
  764. */
  765. public void setMinimumSize(Dimension minimumSize) {
  766. Dimension old = this.minimumSize;
  767. this.minimumSize = minimumSize;
  768. firePropertyChange("minimumSize", old, minimumSize);
  769. }
  770. /**
  771. * If the minimumSize has been set to a non-null value
  772. * just return it. If the UI delegates getMinimumSize()
  773. * method returns a non null value then return that, otherwise
  774. * defer to the components layout manager.
  775. *
  776. * @return the value of the minimumSize property.
  777. * @see #setMinimumSize
  778. */
  779. public Dimension getMinimumSize() {
  780. if (minimumSize != null) {
  781. return minimumSize;
  782. }
  783. Dimension size = null;
  784. if (ui != null) {
  785. size = ui.getMinimumSize(this);
  786. }
  787. return (size != null) ? size : super.getMinimumSize();
  788. }
  789. /**
  790. * Give the UI delegate an opportunity to define the precise
  791. * shape of this component for the sake of mouse processing.
  792. *
  793. * @return true if this component logically contains x,y.
  794. * @see java.awt.Component#contains(int, int)
  795. */
  796. public boolean contains(int x, int y) {
  797. return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
  798. }
  799. /**
  800. * Sets the border of this component. The Border object is
  801. * responsible for defining the insets for the component
  802. * (overriding any insets set directly on the component) and
  803. * for optionally rendering any border decorations within the
  804. * bounds of those insets. Borders should be used (rather
  805. * than insets) for creating both decorative and non-decorative
  806. * (e.g. margins and padding) regions for a swing component.
  807. * Compound borders can be used to nest multiple borders within a
  808. * single component.
  809. * <p>
  810. * This is a bound property.
  811. *
  812. * @param border the border to be rendered for this component
  813. * @see Border
  814. * @see CompoundBorder
  815. * @beaninfo
  816. * bound: true
  817. * preferred: true
  818. * attribute: visualUpdate true
  819. * description: The component's border.
  820. */
  821. public void setBorder(Border border) {
  822. Border oldBorder = this.border;
  823. this.border = border;
  824. firePropertyChange("border", oldBorder, border);
  825. if (border != oldBorder) {
  826. if (border == null || oldBorder == null ||
  827. !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
  828. revalidate();
  829. }
  830. repaint();
  831. }
  832. }
  833. /**
  834. * Returns the border of this component or null if no border is
  835. * currently set.
  836. *
  837. * @return the border object for this component
  838. * @see #setBorder
  839. */
  840. public Border getBorder() {
  841. return border;
  842. }
  843. /**
  844. * If a border has been set on this component, returns the
  845. * border's insets, else calls super.getInsets.
  846. *
  847. * @return the value of the insets property.
  848. * @see #setBorder
  849. */
  850. public Insets getInsets() {
  851. if (border != null) {
  852. return border.getBorderInsets(this);
  853. }
  854. return super.getInsets();
  855. }
  856. /**
  857. * Returns an Insets object containing this component's inset
  858. * values. The passed-in Insets object will be reused if possible.
  859. * Calling methods cannot assume that the same object will be returned,
  860. * however. All existing values within this object are overwritten.
  861. *
  862. * @param insets the Insets object which can be reused.
  863. * @see #getInsets
  864. * @beaninfo
  865. * expert: true
  866. */
  867. public Insets getInsets(Insets insets) {
  868. if (border != null) {
  869. if (border instanceof AbstractBorder) {
  870. return ((AbstractBorder)border).getBorderInsets(this, insets);
  871. } else {
  872. // Can't reuse border insets because the Border interface
  873. // can't be enhanced.
  874. return border.getBorderInsets(this);
  875. }
  876. } else {
  877. // super.getInsets() always returns an Insets object with
  878. // all of its value zeroed. No need for a new object here.
  879. insets.left = insets.top = insets.right = insets.bottom = 0;
  880. return insets;
  881. }
  882. }
  883. /**
  884. * Overrides <code>Container.getAlignmentY</code> to return
  885. * the horizontal alignment.
  886. *
  887. * @return the value of the alignmentY property.
  888. * @see #setAlignmentY
  889. * @see java.awt.Component#getAlignmentY
  890. */
  891. public float getAlignmentY() {
  892. return (alignmentY != null) ? alignmentY.floatValue() : super.getAlignmentY();
  893. }
  894. /**
  895. * Set the the horizontal alignment.
  896. *
  897. * @see #getAlignmentY
  898. * @beaninfo
  899. * description: The preferred vertical alignment of the component
  900. */
  901. public void setAlignmentY(float alignmentY) {
  902. this.alignmentY = new Float(alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY);
  903. }
  904. /**
  905. * Overrides <code>Container.getAlignmentX</code> to return
  906. * the vertical alignment.
  907. *
  908. * @return the value of the alignmentX property.
  909. * @see #setAlignmentX
  910. * @see java.awt.Component#getAlignmentX
  911. */
  912. public float getAlignmentX() {
  913. return (alignmentX != null) ? alignmentX.floatValue() : super.getAlignmentX();
  914. }
  915. /**
  916. * Set the the vertical alignment.
  917. *
  918. * @see #getAlignmentX
  919. * @beaninfo
  920. * description: The preferred horizontal alignment of the component
  921. */
  922. public void setAlignmentX(float alignmentX) {
  923. this.alignmentX = new Float(alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX);
  924. }
  925. /**
  926. * Returns this component's graphics context, which lets you draw
  927. * on a component. Use this method get a Graphics object and
  928. * then invoke oeprations on that object to draw on the component.
  929. */
  930. public Graphics getGraphics() {
  931. if (shouldDebugGraphics() != 0) {
  932. DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
  933. this);
  934. return graphics;
  935. }
  936. return super.getGraphics();
  937. }
  938. /** Enables or disables diagnostic information about every graphics
  939. * operation performed within the component or one of its children. The
  940. * value of <b>debugOptions</b> determines how the component should
  941. * display this information:
  942. * <ul>
  943. * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
  944. * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
  945. * times.
  946. * <li>DebugGraphics.BUFFERED_OPTION - creates an ExternalWindow that
  947. * displays the operations performed on the View's offscreen buffer.
  948. * </ul>
  949. * <b>debug</b> is bitwise OR'd into the current value.
  950. * DebugGraphics.NONE_OPTION disables debugging.
  951. * A value of 0 causes no changes to the debugging options.
  952. * @beaninfo
  953. * preferred: true
  954. * description: Diagnostic options for graphics operations.
  955. */
  956. public void setDebugGraphicsOptions(int debugOptions) {
  957. DebugGraphics.setDebugOptions(this, debugOptions);
  958. }
  959. /** Returns the state of graphics debugging.
  960. * @see #setDebugGraphicsOptions
  961. */
  962. public int getDebugGraphicsOptions() {
  963. return DebugGraphics.getDebugOptions(this);
  964. }
  965. /**
  966. * Returns <b>true</b> if debug information is enabled for this JComponent
  967. * or one if its parents.
  968. */
  969. int shouldDebugGraphics() {
  970. return DebugGraphics.shouldComponentDebug(this);
  971. }
  972. /**
  973. * Register a new keyboard action.
  974. * <b>anAction</b> will be invoked if a key event matching <b>aKeyStroke</b> occurs
  975. * and <b>aCondition</b> is verified. The KeyStroke object defines a
  976. * particular combination of a keyboard key and one or more modifiers
  977. * (alt, shift, ctrl, meta).
  978. * <p>
  979. * The <b>aCommand</b> will be set in the delivered event if specified.
  980. * <p>
  981. * The Condition can be one of:
  982. * <blockquote>
  983. * <DL>
  984. * <DT>WHEN_FOCUSED
  985. * <DD>The action will be invoked only when the keystroke occurs
  986. * while the component has the focus.
  987. * <DT>WHEN_IN_FOCUSED_WINDOW
  988. * <DD>The action will be invoked when the keystroke occurs while
  989. * the component has the focus or if the component is in the
  990. * window that has the focus. Note that the component need not
  991. * be an immediate descendent of the window -- it can be
  992. * anywhere in the window's containment hierarchy. In other
  993. * words, whenever <em>any</em> component in the window has the focus,
  994. * the action registered with this component is invoked.
  995. * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
  996. * <DD>The action will be invoked when the keystroke occurs while the
  997. * component has the focus or if the component is an ancestor of
  998. * the component that has the focus.
  999. * </DL>
  1000. * </blockquote>
  1001. * <p>
  1002. * The combination of keystrokes and conditions lets you define high
  1003. * level (semantic) action events for a specified keystroke+modifier
  1004. * combination (using the KeyStroke class) and direct to a parent or
  1005. * child of a component that has the focus, or to the component itself.
  1006. * In other words, in any hierarchical structure of components, an
  1007. * arbitrary key-combination can be immediately directed to the
  1008. * appropriate component in the hierarchy, and cause a specific method
  1009. * to be invoked (usually by way of adapter objects).
  1010. * <p>
  1011. * If an action has already been registered for the receiving
  1012. * container, with the same charCode and the same modifiers,
  1013. * <b>anAction</b> will replace the action.
  1014. *
  1015. * @see KeyStroke
  1016. */
  1017. public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
  1018. Hashtable bindings;
  1019. boolean firstKeyboardAction = false;
  1020. synchronized(this) {
  1021. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1022. if(bindings == null) {
  1023. bindings = new Hashtable();
  1024. putClientProperty(KEYBOARD_BINDINGS_KEY,bindings);
  1025. firstKeyboardAction = true;
  1026. }
  1027. }
  1028. synchronized(bindings) {
  1029. bindings.put(aKeyStroke,new KeyboardBinding(anAction,aCommand,aKeyStroke,aCondition));
  1030. }
  1031. /* This is the first time a keyboard binding is added, let's order
  1032. * keyboard events...
  1033. * ALERT: we need to enable events. Adding a listener will not work since
  1034. * we want our listener to be after all other listeners.
  1035. */
  1036. if(firstKeyboardAction) {
  1037. enableEvents(AWTEvent.KEY_EVENT_MASK);
  1038. }
  1039. if (getParent() != null && aCondition == WHEN_IN_FOCUSED_WINDOW) {
  1040. registerWithKeyboardManager(aKeyStroke);
  1041. }
  1042. }
  1043. void registerWithKeyboardManager(KeyStroke aKeyStroke) {
  1044. KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke, this);
  1045. }
  1046. void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
  1047. KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke, this);
  1048. }
  1049. /**
  1050. * Calls registerKeyboardAction(ActionListener,String,KeyStroke,condition) with a null command.
  1051. */
  1052. public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
  1053. registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
  1054. }
  1055. private Hashtable keyboardBindings() {
  1056. Hashtable bindings;
  1057. synchronized(this) {
  1058. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1059. }
  1060. return bindings;
  1061. }
  1062. /**
  1063. * Unregister a keyboard action.
  1064. *
  1065. * @see #registerKeyboardAction
  1066. */
  1067. public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
  1068. Hashtable bindings = keyboardBindings();
  1069. KeyboardBinding aBinding;
  1070. if(bindings == null)
  1071. return;
  1072. synchronized(bindings) {
  1073. aBinding = (KeyboardBinding)bindings.remove(aKeyStroke);
  1074. }
  1075. if(bindings.size() == 0) {
  1076. /** ALERT. We need a way to disable keyboard events only if there is no
  1077. * keyboard listener.
  1078. */
  1079. }
  1080. if ( aBinding != null && aBinding.condition == WHEN_IN_FOCUSED_WINDOW) {
  1081. unregisterWithKeyboardManager(aKeyStroke);
  1082. }
  1083. }
  1084. /**
  1085. * Return the KeyStrokes that will initiate registered actions.
  1086. *
  1087. * @return an array of KeyStroke objects
  1088. * @see #registerKeyboardAction
  1089. */
  1090. public KeyStroke[] getRegisteredKeyStrokes() {
  1091. Hashtable bindings = keyboardBindings();
  1092. KeyStroke result[];
  1093. int i;
  1094. Enumeration keys;
  1095. if(bindings == null)
  1096. return new KeyStroke[0];
  1097. synchronized(bindings) {
  1098. result = new KeyStroke[bindings.size()];
  1099. i = 0;
  1100. keys = bindings.keys();
  1101. while(keys.hasMoreElements())
  1102. result[i++] = (KeyStroke) keys.nextElement();
  1103. }
  1104. return result;
  1105. }
  1106. /**
  1107. * Return the condition that determines whether a registered action
  1108. * occurs in response to the specified keystroke.
  1109. *
  1110. * @return the action-keystroke condition
  1111. * @see #registerKeyboardAction
  1112. */
  1113. public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
  1114. Hashtable bindings = keyboardBindings();
  1115. if(bindings == null)
  1116. return UNDEFINED_CONDITION;
  1117. synchronized(bindings) {
  1118. KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1119. if(kb != null) {
  1120. return kb.getCondition();
  1121. }
  1122. }
  1123. return UNDEFINED_CONDITION;
  1124. }
  1125. /**
  1126. * Return the object that will perform the action registered for a
  1127. * given keystroke.
  1128. *
  1129. * @return the ActionListener object invoked when the keystroke occurs
  1130. * @see #registerKeyboardAction
  1131. */
  1132. public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
  1133. Hashtable bindings = keyboardBindings();
  1134. if(bindings == null)
  1135. return null;
  1136. synchronized(bindings) {
  1137. KeyboardBinding kb = (KeyboardBinding) bindings.get(aKeyStroke);
  1138. if(kb != null) {
  1139. return kb.getAction();
  1140. }
  1141. }
  1142. return null;
  1143. }
  1144. /**
  1145. * Unregister all keyboard actions
  1146. *
  1147. * @see #registerKeyboardAction
  1148. */
  1149. public void resetKeyboardActions() {
  1150. synchronized(this) {
  1151. Hashtable bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1152. if(bindings != null) {
  1153. bindings.clear();
  1154. }
  1155. }
  1156. /* ALERT. We need a way to disable keyboard events only if there is no
  1157. * keyboard listener.
  1158. */
  1159. }
  1160. /**
  1161. * Request the focus for the component that should have the focus
  1162. * by default. The default implementation will recursively request
  1163. * the focus on the first component that is focus-traversable.
  1164. *
  1165. * @return false if the focus has not been set, otherwise
  1166. * return true
  1167. */
  1168. public boolean requestDefaultFocus() {
  1169. Component ca[] = getComponents();
  1170. int i;
  1171. for(i=0 ; i < ca.length ; i++) {
  1172. if(ca[i].isFocusTraversable()) {
  1173. if(ca[i] instanceof JComponent) {
  1174. ((JComponent)ca[i]).grabFocus();
  1175. } else {
  1176. ca[i].requestFocus();
  1177. }
  1178. return true;
  1179. }
  1180. if(ca[i] instanceof JComponent && !((JComponent)ca[i]).isManagingFocus()) {
  1181. if(((JComponent)(ca[i])).requestDefaultFocus()) {
  1182. return true;
  1183. }
  1184. }
  1185. }
  1186. return false;
  1187. }
  1188. /**
  1189. * Makes the component visible or invisible.
  1190. * Overrides <code>Component.setVisible</code>.
  1191. *
  1192. * @param aFlag true to make the component visible
  1193. *
  1194. * @beaninfo
  1195. * attribute: visualUpdate true
  1196. */
  1197. public void setVisible(boolean aFlag) {
  1198. if(aFlag != isVisible()) {
  1199. super.setVisible(aFlag);
  1200. Container parent = getParent();
  1201. if(parent != null) {
  1202. Rectangle r = getBounds();
  1203. parent.repaint(r.x,r.y,r.width,r.height);
  1204. }
  1205. // Some (all should) LayoutManagers do not consider components
  1206. // that are not visible. As such we need to revalidate when the
  1207. // visible bit changes.
  1208. revalidate();
  1209. if (accessibleContext != null) {
  1210. if (aFlag) {
  1211. accessibleContext.firePropertyChange(
  1212. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1213. null, AccessibleState.VISIBLE);
  1214. } else {
  1215. accessibleContext.firePropertyChange(
  1216. AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1217. AccessibleState.VISIBLE, null);
  1218. }
  1219. }
  1220. }
  1221. }
  1222. /**
  1223. * Sets whether or not this component is enabled.
  1224. * A component which is enabled may respond to user input,
  1225. * while a component which is not enabled cannot respond to
  1226. * user input. Some components may alter their visual
  1227. * representation when they are disabled in order to
  1228. * provide feedback to the user that they cannot take input.
  1229. *
  1230. * @see java.awt.Component#isEnabled
  1231. *
  1232. * @beaninfo
  1233. * preferred: true
  1234. * bound: true
  1235. * attribute: visualUpdate true
  1236. * description: The enabled state of the component
  1237. */
  1238. public void setEnabled(boolean enabled) {
  1239. boolean oldEnabled = isEnabled();
  1240. super.setEnabled(enabled);
  1241. if (!enabled && hasFocus()) {
  1242. FocusManager.getCurrentManager().focusPreviousComponent(this);
  1243. }
  1244. firePropertyChange("enabled", oldEnabled, enabled);
  1245. if (enabled != oldEnabled) {
  1246. repaint();
  1247. }
  1248. }
  1249. /**
  1250. * Sets the foreground color of this component.
  1251. *
  1252. * @see java.awt.Component#getForeground
  1253. *
  1254. * @beaninfo
  1255. * preferred: true
  1256. * bound: true
  1257. * attribute: visualUpdate true
  1258. * description: The foreground color of the component.
  1259. */
  1260. public void setForeground(Color fg) {
  1261. Color oldFg = getForeground();
  1262. super.setForeground(fg);
  1263. if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) {
  1264. // foreground already bound in AWT1.2
  1265. if (!SwingUtilities.is1dot2) {
  1266. firePropertyChange("foreground", oldFg, fg);
  1267. }
  1268. repaint();
  1269. }
  1270. }
  1271. /**
  1272. * Sets the background color of this component.
  1273. *
  1274. * @see java.awt.Component#getBackground
  1275. *
  1276. * @beaninfo
  1277. * preferred: true
  1278. * bound: true
  1279. * attribute: visualUpdate true
  1280. * description: The background color of the component.
  1281. */
  1282. public void setBackground(Color bg) {
  1283. Color oldBg = getBackground();
  1284. super.setBackground(bg);
  1285. if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg.equals(oldBg))) {
  1286. // background already bound in AWT1.2
  1287. if (!SwingUtilities.is1dot2) {
  1288. firePropertyChange("background", oldBg, bg);
  1289. }
  1290. repaint();
  1291. }
  1292. }
  1293. /**
  1294. * Sets the font for this component.
  1295. *
  1296. * @see java.awt.Component#getFont
  1297. *
  1298. * @beaninfo
  1299. * preferred: true
  1300. * bound: true
  1301. * attribute: visualUpdate true
  1302. * description: The font for the component.
  1303. */
  1304. public void setFont(Font font) {
  1305. Font oldFont = getFont();
  1306. super.setFont(font);
  1307. // font already bound in AWT1.2
  1308. if (!SwingUtilities.is1dot2) {
  1309. firePropertyChange("font", oldFont, font);
  1310. }
  1311. if (font != oldFont) {
  1312. revalidate();
  1313. repaint();
  1314. }
  1315. }
  1316. /**
  1317. * Identifies whether or not this component can receive the focus.
  1318. * A disabled button, for example, would return false.
  1319. *
  1320. * @return true if this component can receive the focus
  1321. */
  1322. public boolean isFocusTraversable() {
  1323. boolean result = false;
  1324. Hashtable bindings;
  1325. synchronized(this) {
  1326. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1327. }
  1328. if(bindings != null) {
  1329. synchronized(bindings) {
  1330. Enumeration keys = bindings.keys();
  1331. KeyboardBinding b;
  1332. while(keys.hasMoreElements()) {
  1333. b = (KeyboardBinding) bindings.get(keys.nextElement());
  1334. if(b.getCondition() == WHEN_FOCUSED) {
  1335. result = true;
  1336. break;
  1337. }
  1338. }
  1339. }
  1340. }
  1341. return result;
  1342. }
  1343. protected void processFocusEvent(FocusEvent e) {
  1344. switch(e.getID()) {
  1345. case FocusEvent.FOCUS_GAINED:
  1346. setFlag(HAS_FOCUS, true);
  1347. break;
  1348. case FocusEvent.FOCUS_LOST:
  1349. setFlag(HAS_FOCUS, false);
  1350. break;
  1351. }
  1352. // Call super *after* setting flag, in case listener calls paint.
  1353. super.processFocusEvent(e);
  1354. }
  1355. /**
  1356. * Process any key events that the component itself
  1357. * recognizes. This will be called after the focus
  1358. * manager and any interested listeners have been
  1359. * given a chance to steal away the event. This
  1360. * method will only be called is the event has not
  1361. * yet been consumed. This method is called prior
  1362. * to the keyboard UI logic.
  1363. * <p>
  1364. * This is implemented to do nothing. Subclasses would
  1365. * normally override this method if they process some
  1366. * key events themselves. If the event is processed,
  1367. * it should be consumed.
  1368. */
  1369. protected void processComponentKeyEvent(KeyEvent e) {
  1370. }
  1371. /** Override processKeyEvent to process events **/
  1372. protected void processKeyEvent(KeyEvent e) {
  1373. // focus manager gets to steal the event if it wants it.
  1374. boolean result;
  1375. boolean shouldProcessKey = false;
  1376. if(FocusManager.isFocusManagerEnabled()) {
  1377. FocusManager focusManager = FocusManager.getCurrentManager();
  1378. focusManager.processKeyEvent(this,e);
  1379. if(e.isConsumed()) {
  1380. return;
  1381. }
  1382. }
  1383. // This gives the key event listeners a crack at the event
  1384. super.processKeyEvent(e);
  1385. // give the component itself a crack at the event
  1386. if (! e.isConsumed()) {
  1387. processComponentKeyEvent(e);
  1388. }
  1389. if(e.getID() == KeyEvent.KEY_PRESSED) {
  1390. shouldProcessKey = true;
  1391. if(!KeyboardState.keyIsPressed(e.getKeyCode()))
  1392. KeyboardState.registerKeyPressed(e.getKeyCode());
  1393. } else if(e.getID() == KeyEvent.KEY_RELEASED) {
  1394. if(KeyboardState.keyIsPressed(e.getKeyCode())) {
  1395. shouldProcessKey = true;
  1396. KeyboardState.registerKeyReleased(e.getKeyCode());
  1397. }
  1398. } else if(e.getID() == KeyEvent.KEY_TYPED) {
  1399. shouldProcessKey = true;
  1400. }
  1401. if(e.isConsumed()) {
  1402. return;
  1403. }
  1404. // (PENDING) Hania & Steve - take out this block? Do we need to do this pressed stuff?
  1405. // And, shouldProcessKey, do we need it?
  1406. if(shouldProcessKey && e.getID() == KeyEvent.KEY_PRESSED) {
  1407. result = processKeyBindings(e,true);
  1408. if(result)
  1409. e.consume();
  1410. } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_RELEASED) {
  1411. result = processKeyBindings(e,false);
  1412. if(result) {
  1413. e.consume();
  1414. }
  1415. } else if(shouldProcessKey && e.getID() == KeyEvent.KEY_TYPED) {
  1416. result = processKeyBindings(e,false);
  1417. if(result) {
  1418. e.consume();
  1419. }
  1420. }
  1421. }
  1422. KeyboardBinding bindingForKeyStroke(KeyStroke ks,int condition) {
  1423. Hashtable bindings;
  1424. KeyboardBinding b;
  1425. KeyboardBinding result = null;
  1426. // synchronized(this) {
  1427. bindings = (Hashtable) getClientProperty(KEYBOARD_BINDINGS_KEY);
  1428. // }
  1429. if(bindings != null) {
  1430. // synchronized(bindings) {
  1431. b = (KeyboardBinding) bindings.get(ks);
  1432. // System.out.println("Bindings are " + bindings);
  1433. if(b != null) {
  1434. ActionListener action = b.getAction();
  1435. if((action instanceof Action) && !(((Action)action).isEnabled()))
  1436. action = null;
  1437. if(action != null) {
  1438. switch(b.getCondition()) {
  1439. case WHEN_FOCUSED:
  1440. if(condition == WHEN_FOCUSED)
  1441. result = b;
  1442. break;
  1443. case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
  1444. if(condition == WHEN_FOCUSED ||
  1445. condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
  1446. result = b;
  1447. break;
  1448. case WHEN_IN_FOCUSED_WINDOW:
  1449. if(condition == WHEN_FOCUSED ||
  1450. conditio