1 /*
2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package javax.swing;
26
27
28 import java.util.HashSet;
29 import java.util.Hashtable;
30 import java.util.Dictionary;
31 import java.util.Enumeration;
32 import java.util.Locale;
33 import java.util.Vector;
34 import java.util.EventListener;
35 import java.util.Set;
36 import java.util.Map;
37 import java.util.HashMap;
38
39 import java.awt;
40 import java.awt.event;
41 import java.awt.image.VolatileImage;
42 import java.awt.Graphics2D;
43 import java.awt.peer.LightweightPeer;
44 import java.awt.dnd.DropTarget;
45 import java.awt.font.FontRenderContext;
46 import java.beans.PropertyChangeListener;
47 import java.beans.VetoableChangeListener;
48 import java.beans.VetoableChangeSupport;
49 import java.beans.Transient;
50
51 import java.applet.Applet;
52
53 import java.io.Serializable;
54 import java.io.ObjectOutputStream;
55 import java.io.ObjectInputStream;
56 import java.io.IOException;
57 import java.io.ObjectInputValidation;
58 import java.io.InvalidObjectException;
59
60 import javax.swing.border;
61 import javax.swing.event;
62 import javax.swing.plaf;
63 import static javax.swing.ClientPropertyKey.*;
64 import javax.accessibility;
65
66 import sun.swing.SwingUtilities2;
67 import sun.swing.UIClientPropertyKey;
68
69 /**
70 * The base class for all Swing components except top-level containers.
71 * To use a component that inherits from <code>JComponent</code>,
72 * you must place the component in a containment hierarchy
73 * whose root is a top-level Swing container.
74 * Top-level Swing containers --
75 * such as <code>JFrame</code>, <code>JDialog</code>,
76 * and <code>JApplet</code> --
77 * are specialized components
78 * that provide a place for other Swing components to paint themselves.
79 * For an explanation of containment hierarchies, see
80 * <a
81 href="http://java.sun.com/docs/books/tutorial/uiswing/overview/hierarchy.html">Swing Components and the Containment Hierarchy</a>,
82 * a section in <em>The Java Tutorial</em>.
83 *
84 * <p>
85 * The <code>JComponent</code> class provides:
86 * <ul>
87 * <li>The base class for both standard and custom components
88 * that use the Swing architecture.
89 * <li>A "pluggable look and feel" (L&F) that can be specified by the
90 * programmer or (optionally) selected by the user at runtime.
91 * The look and feel for each component is provided by a
92 * <em>UI delegate</em> -- an object that descends from
93 * {@link javax.swing.plaf.ComponentUI}.
94 * See <a
95 * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/plaf.html">How
96 * to Set the Look and Feel</a>
97 * in <em>The Java Tutorial</em>
98 * for more information.
99 * <li>Comprehensive keystroke handling.
100 * See the document <a
101 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">Keyboard
102 * Bindings in Swing</a>,
103 * an article in <em>The Swing Connection</em>,
104 * for more information.
105 * <li>Support for tool tips --
106 * short descriptions that pop up when the cursor lingers
107 * over a component.
108 * See <a
109 * href="http://java.sun.com/docs/books/tutorial/uiswing/components/tooltip.html">How
110 * to Use Tool Tips</a>
111 * in <em>The Java Tutorial</em>
112 * for more information.
113 * <li>Support for accessibility.
114 * <code>JComponent</code> contains all of the methods in the
115 * <code>Accessible</code> interface,
116 * but it doesn't actually implement the interface. That is the
117 * responsibility of the individual classes
118 * that extend <code>JComponent</code>.
119 * <li>Support for component-specific properties.
120 * With the {@link #putClientProperty}
121 * and {@link #getClientProperty} methods,
122 * you can associate name-object pairs
123 * with any object that descends from <code>JComponent</code>.
124 * <li>An infrastructure for painting
125 * that includes double buffering and support for borders.
126 * For more information see <a
127 * href="http://java.sun.com/docs/books/tutorial/uiswing/overview/draw.html">Painting</a> and
128 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/border.html">How
129 * to Use Borders</a>,
130 * both of which are sections in <em>The Java Tutorial</em>.
131 * </ul>
132 * For more information on these subjects, see the
133 * <a href="package-summary.html#package_description">Swing package description</a>
134 * and <em>The Java Tutorial</em> section
135 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
136 * <p>
137 * <code>JComponent</code> and its subclasses document default values
138 * for certain properties. For example, <code>JTable</code> documents the
139 * default row height as 16. Each <code>JComponent</code> subclass
140 * that has a <code>ComponentUI</code> will create the
141 * <code>ComponentUI</code> as part of its constructor. In order
142 * to provide a particular look and feel each
143 * <code>ComponentUI</code> may set properties back on the
144 * <code>JComponent</code> that created it. For example, a custom
145 * look and feel may require <code>JTable</code>s to have a row
146 * height of 24. The documented defaults are the value of a property
147 * BEFORE the <code>ComponentUI</code> has been installed. If you
148 * need a specific value for a particular property you should
149 * explicitly set it.
150 * <p>
151 * In release 1.4, the focus subsystem was rearchitected.
152 * For more information, see
153 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
154 * How to Use the Focus Subsystem</a>,
155 * a section in <em>The Java Tutorial</em>.
156 * <p>
157 * <strong>Warning:</strong> Swing is not thread safe. For more
158 * information see <a
159 * href="package-summary.html#threading">Swing's Threading
160 * Policy</a>.
161 * <p>
162 * <strong>Warning:</strong>
163 * Serialized objects of this class will not be compatible with
164 * future Swing releases. The current serialization support is
165 * appropriate for short term storage or RMI between applications running
166 * the same version of Swing. As of 1.4, support for long term storage
167 * of all JavaBeans<sup><font size="-2">TM</font></sup>
168 * has been added to the <code>java.beans</code> package.
169 * Please see {@link java.beans.XMLEncoder}.
170 *
171 * @see KeyStroke
172 * @see Action
173 * @see #setBorder
174 * @see #registerKeyboardAction
175 * @see JOptionPane
176 * @see #setDebugGraphicsOptions
177 * @see #setToolTipText
178 * @see #setAutoscrolls
179 *
180 * @author Hans Muller
181 * @author Arnaud Weber
182 */
183 public abstract class JComponent extends Container implements Serializable,
184 TransferHandler.HasGetTransferHandler
185 {
186 /**
187 * @see #getUIClassID
188 * @see #writeObject
189 */
190 private static final String uiClassID = "ComponentUI";
191
192 /**
193 * @see #readObject
194 */
195 private static final Hashtable readObjectCallbacks = new Hashtable(1);
196
197 /**
198 * Keys to use for forward focus traversal when the JComponent is
199 * managing focus.
200 */
201 private static Set<KeyStroke> managingFocusForwardTraversalKeys;
202
203 /**
204 * Keys to use for backward focus traversal when the JComponent is
205 * managing focus.
206 */
207 private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
208
209 // Following are the possible return values from getObscuredState.
210 private static final int NOT_OBSCURED = 0;
211 private static final int PARTIALLY_OBSCURED = 1;
212 private static final int COMPLETELY_OBSCURED = 2;
213
214 /**
215 * Set to true when DebugGraphics has been loaded.
216 */
217 static boolean DEBUG_GRAPHICS_LOADED;
218
219 /**
220 * Key used to look up a value from the AppContext to determine the
221 * JComponent the InputVerifier is running for. That is, if
222 * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it
223 * indicates the EDT is calling into the InputVerifier from the
224 * returned component.
225 */
226 private static final Object INPUT_VERIFIER_SOURCE_KEY =
227 new StringBuilder("InputVerifierSourceKey");
228
229 /* The following fields support set methods for the corresponding
230 * java.awt.Component properties.
231 */
232 private boolean isAlignmentXSet;
233 private float alignmentX;
234 private boolean isAlignmentYSet;
235 private float alignmentY;
236
237 /**
238 * Backing store for JComponent properties and listeners
239 */
240
241 /** The look and feel delegate for this component. */
242 protected transient ComponentUI ui;
243 /** A list of event listeners for this component. */
244 protected EventListenerList listenerList = new EventListenerList();
245
246 private transient ArrayTable clientProperties;
247 private VetoableChangeSupport vetoableChangeSupport;
248 /**
249 * Whether or not autoscroll has been enabled.
250 */
251 private boolean autoscrolls;
252 private Border border;
253 private int flags;
254
255 /* Input verifier for this component */
256 private InputVerifier inputVerifier = null;
257
258 private boolean verifyInputWhenFocusTarget = true;
259
260 /**
261 * Set in <code>_paintImmediately</code>.
262 * Will indicate the child that initiated the painting operation.
263 * If <code>paintingChild</code> is opaque, no need to paint
264 * any child components after <code>paintingChild</code>.
265 * Test used in <code>paintChildren</code>.
266 */
267 transient Component paintingChild;
268
269 /**
270 * Constant used for <code>registerKeyboardAction</code> that
271 * means that the command should be invoked when
272 * the component has the focus.
273 */
274 public static final int WHEN_FOCUSED = 0;
275
276 /**
277 * Constant used for <code>registerKeyboardAction</code> that
278 * means that the command should be invoked when the receiving
279 * component is an ancestor of the focused component or is
280 * itself the focused component.
281 */
282 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
283
284 /**
285 * Constant used for <code>registerKeyboardAction</code> that
286 * means that the command should be invoked when
287 * the receiving component is in the window that has the focus
288 * or is itself the focused component.
289 */
290 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
291
292 /**
293 * Constant used by some of the APIs to mean that no condition is defined.
294 */
295 public static final int UNDEFINED_CONDITION = -1;
296
297 /**
298 * The key used by <code>JComponent</code> to access keyboard bindings.
299 */
300 private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
301
302 /**
303 * An array of <code>KeyStroke</code>s used for
304 * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed
305 * in the client properties under this string.
306 */
307 private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow";
308
309 /**
310 * The comment to display when the cursor is over the component,
311 * also known as a "value tip", "flyover help", or "flyover label".
312 */
313 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
314
315 private static final String NEXT_FOCUS = "nextFocus";
316
317 /**
318 * <code>JPopupMenu</code> assigned to this component
319 * and all of its childrens
320 */
321 private JPopupMenu popupMenu;
322
323 /** Private flags **/
324 private static final int IS_DOUBLE_BUFFERED = 0;
325 private static final int ANCESTOR_USING_BUFFER = 1;
326 private static final int IS_PAINTING_TILE = 2;
327 private static final int IS_OPAQUE = 3;
328 private static final int KEY_EVENTS_ENABLED = 4;
329 private static final int FOCUS_INPUTMAP_CREATED = 5;
330 private static final int ANCESTOR_INPUTMAP_CREATED = 6;
331 private static final int WIF_INPUTMAP_CREATED = 7;
332 private static final int ACTIONMAP_CREATED = 8;
333 private static final int CREATED_DOUBLE_BUFFER = 9;
334 // bit 10 is free
335 private static final int IS_PRINTING = 11;
336 private static final int IS_PRINTING_ALL = 12;
337 private static final int IS_REPAINTING = 13;
338 /** Bits 14-21 are used to handle nested writeObject calls. **/
339 private static final int WRITE_OBJ_COUNTER_FIRST = 14;
340 private static final int RESERVED_1 = 15;
341 private static final int RESERVED_2 = 16;
342 private static final int RESERVED_3 = 17;
343 private static final int RESERVED_4 = 18;
344 private static final int RESERVED_5 = 19;
345 private static final int RESERVED_6 = 20;
346 private static final int WRITE_OBJ_COUNTER_LAST = 21;
347
348 private static final int REQUEST_FOCUS_DISABLED = 22;
349 private static final int INHERITS_POPUP_MENU = 23;
350 private static final int OPAQUE_SET = 24;
351 private static final int AUTOSCROLLS_SET = 25;
352 private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26;
353 private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27;
354 private static final int REVALIDATE_RUNNABLE_SCHEDULED = 28;
355
356 /**
357 * Temporary rectangles.
358 */
359 private static java.util.List tempRectangles = new java.util.ArrayList(11);
360
361 /** Used for <code>WHEN_FOCUSED</code> bindings. */
362 private InputMap focusInputMap;
363 /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */
364 private InputMap ancestorInputMap;
365 /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */
366 private ComponentInputMap windowInputMap;
367
368 /** ActionMap. */
369 private ActionMap actionMap;
370
371 /** Key used to store the default locale in an AppContext **/
372 private static final String defaultLocale = "JComponent.defaultLocale";
373
374 private static Component componentObtainingGraphicsFrom;
375 private static Object componentObtainingGraphicsFromLock = new
376 StringBuilder("componentObtainingGraphicsFrom");
377
378 /**
379 * AA text hints.
380 */
381 transient private Object aaTextInfo;
382
383 static Graphics safelyGetGraphics(Component c) {
384 return safelyGetGraphics(c, SwingUtilities.getRoot(c));
385 }
386
387 static Graphics safelyGetGraphics(Component c, Component root) {
388 synchronized(componentObtainingGraphicsFromLock) {
389 componentObtainingGraphicsFrom = root;
390 Graphics g = c.getGraphics();
391 componentObtainingGraphicsFrom = null;
392 return g;
393 }
394 }
395
396 static void getGraphicsInvoked(Component root) {
397 if (!JComponent.isComponentObtainingGraphicsFrom(root)) {
398 JRootPane rootPane = ((RootPaneContainer)root).getRootPane();
399 if (rootPane != null) {
400 rootPane.disableTrueDoubleBuffering();
401 }
402 }
403 }
404
405
406 /**
407 * Returns true if {@code c} is the component the graphics is being
408 * requested of. This is intended for use when getGraphics is invoked.
409 */
410 private static boolean isComponentObtainingGraphicsFrom(Component c) {
411 synchronized(componentObtainingGraphicsFromLock) {
412 return (componentObtainingGraphicsFrom == c);
413 }
414 }
415
416 /**
417 * Returns the Set of <code>KeyStroke</code>s to use if the component
418 * is managing focus for forward focus traversal.
419 */
420 static Set<KeyStroke> getManagingFocusForwardTraversalKeys() {
421 synchronized(JComponent.class) {
422 if (managingFocusForwardTraversalKeys == null) {
423 managingFocusForwardTraversalKeys = new HashSet<KeyStroke>(1);
424 managingFocusForwardTraversalKeys.add(
425 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
426 InputEvent.CTRL_MASK));
427 }
428 }
429 return managingFocusForwardTraversalKeys;
430 }
431
432 /**
433 * Returns the Set of <code>KeyStroke</code>s to use if the component
434 * is managing focus for backward focus traversal.
435 */
436 static Set<KeyStroke> getManagingFocusBackwardTraversalKeys() {
437 synchronized(JComponent.class) {
438 if (managingFocusBackwardTraversalKeys == null) {
439 managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>(1);
440 managingFocusBackwardTraversalKeys.add(
441 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
442 InputEvent.SHIFT_MASK |
443 InputEvent.CTRL_MASK));
444 }
445 }
446 return managingFocusBackwardTraversalKeys;
447 }
448
449 private static Rectangle fetchRectangle() {
450 synchronized(tempRectangles) {
451 Rectangle rect;
452 int size = tempRectangles.size();
453 if (size > 0) {
454 rect = (Rectangle)tempRectangles.remove(size - 1);
455 }
456 else {
457 rect = new Rectangle(0, 0, 0, 0);
458 }
459 return rect;
460 }
461 }
462
463 private static void recycleRectangle(Rectangle rect) {
464 synchronized(tempRectangles) {
465 tempRectangles.add(rect);
466 }
467 }
468
469 /**
470 * Sets whether or not <code>getComponentPopupMenu</code> should delegate
471 * to the parent if this component does not have a <code>JPopupMenu</code>
472 * assigned to it.
473 * <p>
474 * The default value for this is false, but some <code>JComponent</code>
475 * subclasses that are implemented as a number of <code>JComponent</code>s
476 * may set this to true.
477 * <p>
478 * This is a bound property.
479 *
480 * @param value whether or not the JPopupMenu is inherited
481 * @see #setComponentPopupMenu
482 * @beaninfo
483 * bound: true
484 * description: Whether or not the JPopupMenu is inherited
485 * @since 1.5
486 */
487 public void setInheritsPopupMenu(boolean value) {
488 boolean oldValue = getFlag(INHERITS_POPUP_MENU);
489 setFlag(INHERITS_POPUP_MENU, value);
490 firePropertyChange("inheritsPopupMenu", oldValue, value);
491 }
492
493 /**
494 * Returns true if the JPopupMenu should be inherited from the parent.
495 *
496 * @see #setComponentPopupMenu
497 * @since 1.5
498 */
499 public boolean getInheritsPopupMenu() {
500 return getFlag(INHERITS_POPUP_MENU);
501 }
502
503 /**
504 * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>.
505 * The UI is responsible for registering bindings and adding the necessary
506 * listeners such that the <code>JPopupMenu</code> will be shown at
507 * the appropriate time. When the <code>JPopupMenu</code> is shown
508 * depends upon the look and feel: some may show it on a mouse event,
509 * some may enable a key binding.
510 * <p>
511 * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code>
512 * returns true, then <code>getComponentPopupMenu</code> will be delegated
513 * to the parent. This provides for a way to make all child components
514 * inherit the popupmenu of the parent.
515 * <p>
516 * This is a bound property.
517 *
518 * @param popup - the popup that will be assigned to this component
519 * may be null
520 * @see #getComponentPopupMenu
521 * @beaninfo
522 * bound: true
523 * preferred: true
524 * description: Popup to show
525 * @since 1.5
526 */
527 public void setComponentPopupMenu(JPopupMenu popup) {
528 if(popup != null) {
529 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
530 }
531 JPopupMenu oldPopup = this.popupMenu;
532 this.popupMenu = popup;
533 firePropertyChange("componentPopupMenu", oldPopup, popup);
534 }
535
536 /**
537 * Returns <code>JPopupMenu</code> that assigned for this component.
538 * If this component does not have a <code>JPopupMenu</code> assigned
539 * to it and <code>getInheritsPopupMenu</code> is true, this
540 * will return <code>getParent().getComponentPopupMenu()</code> (assuming
541 * the parent is valid.)
542 *
543 * @return <code>JPopupMenu</code> assigned for this component
544 * or <code>null</code> if no popup assigned
545 * @see #setComponentPopupMenu
546 * @since 1.5
547 */
548 public JPopupMenu getComponentPopupMenu() {
549
550 if(!getInheritsPopupMenu()) {
551 return popupMenu;
552 }
553
554 if(popupMenu == null) {
555 // Search parents for its popup
556 Container parent = getParent();
557 while (parent != null) {
558 if(parent instanceof JComponent) {
559 return ((JComponent)parent).getComponentPopupMenu();
560 }
561 if(parent instanceof Window ||
562 parent instanceof Applet) {
563 // Reached toplevel, break and return null
564 break;
565 }
566 parent = parent.getParent();
567 }
568 return null;
569 }
570
571 return popupMenu;
572 }
573
574 /**
575 * Default <code>JComponent</code> constructor. This constructor does
576 * very little initialization beyond calling the <code>Container</code>
577 * constructor. For example, the initial layout manager is
578 * <code>null</code>. It does, however, set the component's locale
579 * property to the value returned by
580 * <code>JComponent.getDefaultLocale</code>.
581 *
582 * @see #getDefaultLocale
583 */
584 public JComponent() {
585 super();
586 // We enable key events on all JComponents so that accessibility
587 // bindings will work everywhere. This is a partial fix to BugID
588 // 4282211.
589 enableEvents(AWTEvent.KEY_EVENT_MASK);
590 if (isManagingFocus()) {
591 LookAndFeel.installProperty(this,
592 "focusTraversalKeysForward",
593 getManagingFocusForwardTraversalKeys());
594 LookAndFeel.installProperty(this,
595 "focusTraversalKeysBackward",
596 getManagingFocusBackwardTraversalKeys());
597 }
598
599 super.setLocale( JComponent.getDefaultLocale() );
600 }
601
602
603 /**
604 * Resets the UI property to a value from the current look and feel.
605 * <code>JComponent</code> subclasses must override this method
606 * like this:
607 * <pre>
608 * public void updateUI() {
609 * setUI((SliderUI)UIManager.getUI(this);
610 * }
611 * </pre>
612 *
613 * @see #setUI
614 * @see UIManager#getLookAndFeel
615 * @see UIManager#getUI
616 */
617 public void updateUI() {}
618
619
620 /**
621 * Sets the look and feel delegate for this component.
622 * <code>JComponent</code> subclasses generally override this method
623 * to narrow the argument type. For example, in <code>JSlider</code>:
624 * <pre>
625 * public void setUI(SliderUI newUI) {
626 * super.setUI(newUI);
627 * }
628 * </pre>
629 * <p>
630 * Additionally <code>JComponent</code> subclasses must provide a
631 * <code>getUI</code> method that returns the correct type. For example:
632 * <pre>
633 * public SliderUI getUI() {
634 * return (SliderUI)ui;
635 * }
636 * </pre>
637 *
638 * @param newUI the new UI delegate
639 * @see #updateUI
640 * @see UIManager#getLookAndFeel
641 * @see UIManager#getUI
642 * @beaninfo
643 * bound: true
644 * hidden: true
645 * attribute: visualUpdate true
646 * description: The component's look and feel delegate.
647 */
648 protected void setUI(ComponentUI newUI) {
649 /* We do not check that the UI instance is different
650 * before allowing the switch in order to enable the
651 * same UI instance *with different default settings*
652 * to be installed.
653 */
654
655 uninstallUIAndProperties();
656
657 // aaText shouldn't persist between look and feels, reset it.
658 aaTextInfo =
659 UIManager.getDefaults().get(SwingUtilities2.AA_TEXT_PROPERTY_KEY);
660 ComponentUI oldUI = ui;
661 ui = newUI;
662 if (ui != null) {
663 ui.installUI(this);
664 }
665
666 firePropertyChange("UI", oldUI, newUI);
667 revalidate();
668 repaint();
669 }
670
671 /**
672 * Uninstalls the UI, if any, and any client properties designated
673 * as being specific to the installed UI - instances of
674 * {@code UIClientPropertyKey}.
675 */
676 private void uninstallUIAndProperties() {
677 if (ui != null) {
678 ui.uninstallUI(this);
679 //clean UIClientPropertyKeys from client properties
680 if (clientProperties != null) {
681 synchronized(clientProperties) {
682 Object[] clientPropertyKeys =
683 clientProperties.getKeys(null);
684 if (clientPropertyKeys != null) {
685 for (Object key : clientPropertyKeys) {
686 if (key instanceof UIClientPropertyKey) {
687 putClientProperty(key, null);
688 }
689 }
690 }
691 }
692 }
693 }
694 }
695
696 /**
697 * Returns the <code>UIDefaults</code> key used to
698 * look up the name of the <code>swing.plaf.ComponentUI</code>
699 * class that defines the look and feel
700 * for this component. Most applications will never need to
701 * call this method. Subclasses of <code>JComponent</code> that support
702 * pluggable look and feel should override this method to
703 * return a <code>UIDefaults</code> key that maps to the
704 * <code>ComponentUI</code> subclass that defines their look and feel.
705 *
706 * @return the <code>UIDefaults</code> key for a
707 * <code>ComponentUI</code> subclass
708 * @see UIDefaults#getUI
709 * @beaninfo
710 * expert: true
711 * description: UIClassID
712 */
713 public String getUIClassID() {
714 return uiClassID;
715 }
716
717
718 /**
719 * Returns the graphics object used to paint this component.
720 * If <code>DebugGraphics</code> is turned on we create a new
721 * <code>DebugGraphics</code> object if necessary.
722 * Otherwise we just configure the
723 * specified graphics object's foreground and font.
724 *
725 * @param g the original <code>Graphics</code> object
726 * @return a <code>Graphics</code> object configured for this component
727 */
728 protected Graphics getComponentGraphics(Graphics g) {
729 Graphics componentGraphics = g;
730 if (ui != null && DEBUG_GRAPHICS_LOADED) {
731 if ((DebugGraphics.debugComponentCount() != 0) &&
732 (shouldDebugGraphics() != 0) &&
733 !(g instanceof DebugGraphics)) {
734 componentGraphics = new DebugGraphics(g,this);
735 }
736 }
737 componentGraphics.setColor(getForeground());
738 componentGraphics.setFont(getFont());
739
740 return componentGraphics;
741 }
742
743
744 /**
745 * Calls the UI delegate's paint method, if the UI delegate
746 * is non-<code>null</code>. We pass the delegate a copy of the
747 * <code>Graphics</code> object to protect the rest of the
748 * paint code from irrevocable changes
749 * (for example, <code>Graphics.translate</code>).
750 * <p>
751 * If you override this in a subclass you should not make permanent
752 * changes to the passed in <code>Graphics</code>. For example, you
753 * should not alter the clip <code>Rectangle</code> or modify the
754 * transform. If you need to do these operations you may find it
755 * easier to create a new <code>Graphics</code> from the passed in
756 * <code>Graphics</code> and manipulate it. Further, if you do not
757 * invoker super's implementation you must honor the opaque property,
758 * that is
759 * if this component is opaque, you must completely fill in the background
760 * in a non-opaque color. If you do not honor the opaque property you
761 * will likely see visual artifacts.
762 * <p>
763 * The passed in <code>Graphics</code> object might
764 * have a transform other than the identify transform
765 * installed on it. In this case, you might get
766 * unexpected results if you cumulatively apply
767 * another transform.
768 *
769 * @param g the <code>Graphics</code> object to protect
770 * @see #paint
771 * @see ComponentUI
772 */
773 protected void paintComponent(Graphics g) {
774 if (ui != null) {
775 Graphics scratchGraphics = (g == null) ? null : g.create();
776 try {
777 ui.update(scratchGraphics, this);
778 }
779 finally {
780 scratchGraphics.dispose();
781 }
782 }
783 }
784
785 /**
786 * Paints this component's children.
787 * If <code>shouldUseBuffer</code> is true,
788 * no component ancestor has a buffer and
789 * the component children can use a buffer if they have one.
790 * Otherwise, one ancestor has a buffer currently in use and children
791 * should not use a buffer to paint.
792 * @param g the <code>Graphics</code> context in which to paint
793 * @see #paint
794 * @see java.awt.Container#paint
795 */
796 protected void paintChildren(Graphics g) {
797 boolean isJComponent;
798 Graphics sg = g;
799
800 synchronized(getTreeLock()) {
801 int i = getComponentCount() - 1;
802 if (i < 0) {
803 return;
804 }
805 // If we are only to paint to a specific child, determine
806 // its index.
807 if (paintingChild != null &&
808 (paintingChild instanceof JComponent) &&
809 ((JComponent)paintingChild).isOpaque()) {
810 for (; i >= 0; i--) {
811 if (getComponent(i) == paintingChild){
812 break;
813 }
814 }
815 }
816 Rectangle tmpRect = fetchRectangle();
817 boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
818 checkIfChildObscuredBySibling());
819 Rectangle clipBounds = null;
820 if (checkSiblings) {
821 clipBounds = sg.getClipBounds();
822 if (clipBounds == null) {
823 clipBounds = new Rectangle(0, 0, getWidth(),
824 getHeight());
825 }
826 }
827 boolean printing = getFlag(IS_PRINTING);
828 for (; i >= 0 ; i--) {
829 Component comp = getComponent(i);
830 isJComponent = (comp instanceof JComponent);
831 if (comp != null &&
832 (isJComponent || isLightweightComponent(comp)) &&
833 (comp.isVisible() == true)) {
834 Rectangle cr;
835
836 cr = comp.getBounds(tmpRect);
837
838 boolean hitClip = g.hitClip(cr.x, cr.y, cr.width,
839 cr.height);
840
841 if (hitClip) {
842 if (checkSiblings && i > 0) {
843 int x = cr.x;
844 int y = cr.y;
845 int width = cr.width;
846 int height = cr.height;
847 SwingUtilities.computeIntersection
848 (clipBounds.x, clipBounds.y,
849 clipBounds.width, clipBounds.height, cr);
850
851 if(getObscuredState(i, cr.x, cr.y, cr.width,
852 cr.height) == COMPLETELY_OBSCURED) {
853 continue;
854 }
855 cr.x = x;
856 cr.y = y;
857 cr.width = width;
858 cr.height = height;
859 }
860 Graphics cg = sg.create(cr.x, cr.y, cr.width,
861 cr.height);
862 cg.setColor(comp.getForeground());
863 cg.setFont(comp.getFont());
864 boolean shouldSetFlagBack = false;
865 try {
866 if(isJComponent) {
867 if(getFlag(ANCESTOR_USING_BUFFER)) {
868 ((JComponent)comp).setFlag(
869 ANCESTOR_USING_BUFFER,true);
870 shouldSetFlagBack = true;
871 }
872 if(getFlag(IS_PAINTING_TILE)) {
873 ((JComponent)comp).setFlag(
874 IS_PAINTING_TILE,true);
875 shouldSetFlagBack = true;
876 }
877 if(!printing) {
878 ((JComponent)comp).paint(cg);
879 }
880 else {
881 if (!getFlag(IS_PRINTING_ALL)) {
882 comp.print(cg);
883 }
884 else {
885 comp.printAll(cg);
886 }
887 }
888 } else {
889 if (!printing) {
890 comp.paint(cg);
891 }
892 else {
893 if (!getFlag(IS_PRINTING_ALL)) {
894 comp.print(cg);
895 }
896 else {
897 comp.printAll(cg);
898 }
899 }
900 }
901 } finally {
902 cg.dispose();
903 if(shouldSetFlagBack) {
904 ((JComponent)comp).setFlag(
905 ANCESTOR_USING_BUFFER,false);
906 ((JComponent)comp).setFlag(
907 IS_PAINTING_TILE,false);
908 }
909 }
910 }
911 }
912
913 }
914 recycleRectangle(tmpRect);
915 }
916 }
917
918 /**
919 * Paints the component's border.
920 * <p>
921 * If you override this in a subclass you should not make permanent
922 * changes to the passed in <code>Graphics</code>. For example, you
923 * should not alter the clip <code>Rectangle</code> or modify the
924 * transform. If you need to do these operations you may find it
925 * easier to create a new <code>Graphics</code> from the passed in
926 * <code>Graphics</code> and manipulate it.
927 *
928 * @param g the <code>Graphics</code> context in which to paint
929 *
930 * @see #paint
931 * @see #setBorder
932 */
933 protected void paintBorder(Graphics g) {
934 Border border = getBorder();
935 if (border != null) {
936 border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
937 }
938 }
939
940
941 /**
942 * Calls <code>paint</code>. Doesn't clear the background but see
943 * <code>ComponentUI.update</code>, which is called by
944 * <code>paintComponent</code>.
945 *
946 * @param g the <code>Graphics</code> context in which to paint
947 * @see #paint
948 * @see #paintComponent
949 * @see javax.swing.plaf.ComponentUI
950 */
951 public void update(Graphics g) {
952 paint(g);
953 }
954
955
956 /**
957 * Invoked by Swing to draw components.
958 * Applications should not invoke <code>paint</code> directly,
959 * but should instead use the <code>repaint</code> method to
960 * schedule the component for redrawing.
961 * <p>
962 * This method actually delegates the work of painting to three
963 * protected methods: <code>paintComponent</code>,
964 * <code>paintBorder</code>,
965 * and <code>paintChildren</code>. They're called in the order
966 * listed to ensure that children appear on top of component itself.
967 * Generally speaking, the component and its children should not
968 * paint in the insets area allocated to the border. Subclasses can
969 * just override this method, as always. A subclass that just
970 * wants to specialize the UI (look and feel) delegate's
971 * <code>paint</code> method should just override
972 * <code>paintComponent</code>.
973 *
974 * @param g the <code>Graphics</code> context in which to paint
975 * @see #paintComponent
976 * @see #paintBorder
977 * @see #paintChildren
978 * @see #getComponentGraphics
979 * @see #repaint
980 */
981 public void paint(Graphics g) {
982 boolean shouldClearPaintFlags = false;
983
984 if ((getWidth() <= 0) || (getHeight() <= 0)) {
985 return;
986 }
987
988 Graphics componentGraphics = getComponentGraphics(g);
989 Graphics co = componentGraphics.create();
990 try {
991 RepaintManager repaintManager = RepaintManager.currentManager(this);
992 Rectangle clipRect = co.getClipBounds();
993 int clipX;
994 int clipY;
995 int clipW;
996 int clipH;
997 if (clipRect == null) {
998 clipX = clipY = 0;
999 clipW = getWidth();
1000 clipH = getHeight();
1001 }
1002 else {
1003 clipX = clipRect.x;
1004 clipY = clipRect.y;
1005 clipW = clipRect.width;
1006 clipH = clipRect.height;
1007 }
1008
1009 if(clipW > getWidth()) {
1010 clipW = getWidth();
1011 }
1012 if(clipH > getHeight()) {
1013 clipH = getHeight();
1014 }
1015
1016 if(getParent() != null && !(getParent() instanceof JComponent)) {
1017 adjustPaintFlags();
1018 shouldClearPaintFlags = true;
1019 }
1020
1021 int bw,bh;
1022 boolean printing = getFlag(IS_PRINTING);
1023 if(!printing && repaintManager.isDoubleBufferingEnabled() &&
1024 !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
1025 repaintManager.beginPaint();
1026 try {
1027 repaintManager.paint(this, this, co, clipX, clipY, clipW,
1028 clipH);
1029 } finally {
1030 repaintManager.endPaint();
1031 }
1032 }
1033 else {
1034 // Will ocassionaly happen in 1.2, especially when printing.
1035 if (clipRect == null) {
1036 co.setClip(clipX, clipY, clipW, clipH);
1037 }
1038
1039 if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
1040 if (!printing) {
1041 paintComponent(co);
1042 paintBorder(co);
1043 }
1044 else {
1045 printComponent(co);
1046 printBorder(co);
1047 }
1048 }
1049 if (!printing) {
1050 paintChildren(co);
1051 }
1052 else {
1053 printChildren(co);
1054 }
1055 }
1056 } finally {
1057 co.dispose();
1058 if(shouldClearPaintFlags) {
1059 setFlag(ANCESTOR_USING_BUFFER,false);
1060 setFlag(IS_PAINTING_TILE,false);
1061 setFlag(IS_PRINTING,false);
1062 setFlag(IS_PRINTING_ALL,false);
1063 }
1064 }
1065 }
1066
1067 // paint forcing use of the double buffer. This is used for historical
1068 // reasons: JViewport, when scrolling, previously directly invoked paint
1069 // while turning off double buffering at the RepaintManager level, this
1070 // codes simulates that.
1071 void paintForceDoubleBuffered(Graphics g) {
1072 RepaintManager rm = RepaintManager.currentManager(this);
1073 Rectangle clip = g.getClipBounds();
1074 rm.beginPaint();
1075 setFlag(IS_REPAINTING, true);
1076 try {
1077 rm.paint(this, this, g, clip.x, clip.y, clip.width, clip.height);
1078 } finally {
1079 rm.endPaint();
1080 setFlag(IS_REPAINTING, false);
1081 }
1082 }
1083
1084 /**
1085 * Returns true if this component, or any of its ancestors, are in
1086 * the processing of painting.
1087 */
1088 boolean isPainting() {
1089 Container component = this;
1090 while (component != null) {
1091 if (component instanceof JComponent &&
1092 ((JComponent)component).getFlag(ANCESTOR_USING_BUFFER)) {
1093 return true;
1094 }
1095 component = component.getParent();
1096 }
1097 return false;
1098 }
1099
1100 private void adjustPaintFlags() {
1101 JComponent jparent = null;
1102 Container parent;
1103 for(parent = getParent() ; parent != null ; parent =
1104 parent.getParent()) {
1105 if(parent instanceof JComponent) {
1106 jparent = (JComponent) parent;
1107 if(jparent.getFlag(ANCESTOR_USING_BUFFER))
1108 setFlag(ANCESTOR_USING_BUFFER, true);
1109 if(jparent.getFlag(IS_PAINTING_TILE))
1110 setFlag(IS_PAINTING_TILE, true);
1111 if(jparent.getFlag(IS_PRINTING))
1112 setFlag(IS_PRINTING, true);
1113 if(jparent.getFlag(IS_PRINTING_ALL))
1114 setFlag(IS_PRINTING_ALL, true);
1115 break;
1116 }
1117 }
1118 }
1119
1120 /**
1121 * Invoke this method to print the component. This method invokes
1122 * <code>print</code> on the component.
1123 *
1124 * @param g the <code>Graphics</code> context in which to paint
1125 * @see #print
1126 * @see #printComponent
1127 * @see #printBorder
1128 * @see #printChildren
1129 */
1130 public void printAll(Graphics g) {
1131 setFlag(IS_PRINTING_ALL, true);
1132 try {
1133 print(g);
1134 }
1135 finally {
1136 setFlag(IS_PRINTING_ALL, false);
1137 }
1138 }
1139
1140 /**
1141 * Invoke this method to print the component to the specified
1142 * <code>Graphics</code>. This method will result in invocations
1143 * of <code>printComponent</code>, <code>printBorder</code> and
1144 * <code>printChildren</code>. It is recommended that you override
1145 * one of the previously mentioned methods rather than this one if
1146 * your intention is to customize the way printing looks. However,
1147 * it can be useful to override this method should you want to prepare
1148 * state before invoking the superclass behavior. As an example,
1149 * if you wanted to change the component's background color before
1150 * printing, you could do the following:
1151 * <pre>
1152 * public void print(Graphics g) {
1153 * Color orig = getBackground();
1154 * setBackground(Color.WHITE);
1155 *
1156 * // wrap in try/finally so that we always restore the state
1157 * try {
1158 * super.print(g);
1159 * } finally {
1160 * setBackground(orig);
1161 * }
1162 * }
1163 * </pre>
1164 * <p>
1165 * Alternatively, or for components that delegate painting to other objects,
1166 * you can query during painting whether or not the component is in the
1167 * midst of a print operation. The <code>isPaintingForPrint</code> method provides
1168 * this ability and its return value will be changed by this method: to
1169 * <code>true</code> immediately before rendering and to <code>false</code>
1170 * immediately after. With each change a property change event is fired on
1171 * this component with the name <code>"paintingForPrint"</code>.
1172 * <p>
1173 * This method sets the component's state such that the double buffer
1174 * will not be used: painting will be done directly on the passed in
1175 * <code>Graphics</code>.
1176 *
1177 * @param g the <code>Graphics</code> context in which to paint
1178 * @see #printComponent
1179 * @see #printBorder
1180 * @see #printChildren
1181 * @see #isPaintingForPrint
1182 */
1183 public void print(Graphics g) {
1184 setFlag(IS_PRINTING, true);
1185 firePropertyChange("paintingForPrint", false, true);
1186 try {
1187 paint(g);
1188 }
1189 finally {
1190 setFlag(IS_PRINTING, false);
1191 firePropertyChange("paintingForPrint", true, false);
1192 }
1193 }
1194
1195 /**
1196 * This is invoked during a printing operation. This is implemented to
1197 * invoke <code>paintComponent</code> on the component. Override this
1198 * if you wish to add special painting behavior when printing.
1199 *
1200 * @param g the <code>Graphics</code> context in which to paint
1201 * @see #print
1202 * @since 1.3
1203 */
1204 protected void printComponent(Graphics g) {
1205 paintComponent(g);
1206 }
1207
1208 /**
1209 * Prints this component's children. This is implemented to invoke
1210 * <code>paintChildren</code> on the component. Override this if you
1211 * wish to print the children differently than painting.
1212 *
1213 * @param g the <code>Graphics</code> context in which to paint
1214 * @see #print
1215 * @since 1.3
1216 */
1217 protected void printChildren(Graphics g) {
1218 paintChildren(g);
1219 }
1220
1221 /**
1222 * Prints the component's border. This is implemented to invoke
1223 * <code>paintBorder</code> on the component. Override this if you
1224 * wish to print the border differently that it is painted.
1225 *
1226 * @param g the <code>Graphics</code> context in which to paint
1227 * @see #print
1228 * @since 1.3
1229 */
1230 protected void printBorder(Graphics g) {
1231 paintBorder(g);
1232 }
1233
1234 /**
1235 * Returns true if the component is currently painting a tile.
1236 * If this method returns true, paint will be called again for another
1237 * tile. This method returns false if you are not painting a tile or
1238 * if the last tile is painted.
1239 * Use this method to keep some state you might need between tiles.
1240 *
1241 * @return true if the component is currently painting a tile,
1242 * false otherwise
1243 */
1244 public boolean isPaintingTile() {
1245 return getFlag(IS_PAINTING_TILE);
1246 }
1247
1248 /**
1249 * Returns <code>true</code> if the current painting operation on this
1250 * component is part of a <code>print</code> operation. This method is
1251 * useful when you want to customize what you print versus what you show
1252 * on the screen.
1253 * <p>
1254 * You can detect changes in the value of this property by listening for
1255 * property change events on this component with name
1256 * <code>"paintingForPrint"</code>.
1257 * <p>
1258 * Note: This method provides complimentary functionality to that provided
1259 * by other high level Swing printing APIs. However, it deals strictly with
1260 * painting and should not be confused as providing information on higher
1261 * level print processes. For example, a {@link javax.swing.JTable#print()}
1262 * operation doesn't necessarily result in a continuous rendering of the
1263 * full component, and the return value of this method can change multiple
1264 * times during that operation. It is even possible for the component to be
1265 * painted to the screen while the printing process is ongoing. In such a
1266 * case, the return value of this method is <code>true</code> when, and only
1267 * when, the table is being painted as part of the printing process.
1268 *
1269 * @return true if the current painting operation on this component
1270 * is part of a print operation
1271 * @see #print
1272 * @since 1.6
1273 */
1274 public final boolean isPaintingForPrint() {
1275 return getFlag(IS_PRINTING);
1276 }
1277
1278 /**
1279 * In release 1.4, the focus subsystem was rearchitected.
1280 * For more information, see
1281 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1282 * How to Use the Focus Subsystem</a>,
1283 * a section in <em>The Java Tutorial</em>.
1284 * <p>
1285 * Changes this <code>JComponent</code>'s focus traversal keys to
1286 * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents
1287 * <code>SortingFocusTraversalPolicy</code> from considering descendants
1288 * of this JComponent when computing a focus traversal cycle.
1289 *
1290 * @see java.awt.Component#setFocusTraversalKeys
1291 * @see SortingFocusTraversalPolicy
1292 * @deprecated As of 1.4, replaced by
1293 * <code>Component.setFocusTraversalKeys(int, Set)</code> and
1294 * <code>Container.setFocusCycleRoot(boolean)</code>.
1295 */
1296 @Deprecated
1297 public boolean isManagingFocus() {
1298 return false;
1299 }
1300
1301 private void registerNextFocusableComponent() {
1302 registerNextFocusableComponent(getNextFocusableComponent());
1303 }
1304
1305 private void registerNextFocusableComponent(Component
1306 nextFocusableComponent) {
1307 if (nextFocusableComponent == null) {
1308 return;
1309 }
1310
1311 Container nearestRoot =
1312 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1313 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1314 if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) {
1315 policy = new LegacyGlueFocusTraversalPolicy(policy);
1316 nearestRoot.setFocusTraversalPolicy(policy);
1317 }
1318 ((LegacyGlueFocusTraversalPolicy)policy).
1319 setNextFocusableComponent(this, nextFocusableComponent);
1320 }
1321
1322 private void deregisterNextFocusableComponent() {
1323 Component nextFocusableComponent = getNextFocusableComponent();
1324 if (nextFocusableComponent == null) {
1325 return;
1326 }
1327
1328 Container nearestRoot =
1329 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1330 if (nearestRoot == null) {
1331 return;
1332 }
1333 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1334 if (policy instanceof LegacyGlueFocusTraversalPolicy) {
1335 ((LegacyGlueFocusTraversalPolicy)policy).
1336 unsetNextFocusableComponent(this, nextFocusableComponent);
1337 }
1338 }
1339
1340 /**
1341 * In release 1.4, the focus subsystem was rearchitected.
1342 * For more information, see
1343 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1344 * How to Use the Focus Subsystem</a>,
1345 * a section in <em>The Java Tutorial</em>.
1346 * <p>
1347 * Overrides the default <code>FocusTraversalPolicy</code> for this
1348 * <code>JComponent</code>'s focus traversal cycle by unconditionally
1349 * setting the specified <code>Component</code> as the next
1350 * <code>Component</code> in the cycle, and this <code>JComponent</code>
1351 * as the specified <code>Component</code>'s previous
1352 * <code>Component</code> in the cycle.
1353 *
1354 * @param aComponent the <code>Component</code> that should follow this
1355 * <code>JComponent</code> in the focus traversal cycle
1356 *
1357 * @see #getNextFocusableComponent
1358 * @see java.awt.FocusTraversalPolicy
1359 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>
1360 */
1361 @Deprecated
1362 public void setNextFocusableComponent(Component aComponent) {
1363 boolean displayable = isDisplayable();
1364 if (displayable) {
1365 deregisterNextFocusableComponent();
1366 }
1367 putClientProperty(NEXT_FOCUS, aComponent);
1368 if (displayable) {
1369 registerNextFocusableComponent(aComponent);
1370 }
1371 }
1372
1373 /**
1374 * In release 1.4, the focus subsystem was rearchitected.
1375 * For more information, see
1376 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1377 * How to Use the Focus Subsystem</a>,
1378 * a section in <em>The Java Tutorial</em>.
1379 * <p>
1380 * Returns the <code>Component</code> set by a prior call to
1381 * <code>setNextFocusableComponent(Component)</code> on this
1382 * <code>JComponent</code>.
1383 *
1384 * @return the <code>Component</code> that will follow this
1385 * <code>JComponent</code> in the focus traversal cycle, or
1386 * <code>null</code> if none has been explicitly specified
1387 *
1388 * @see #setNextFocusableComponent
1389 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
1390 */
1391 @Deprecated
1392 public Component getNextFocusableComponent() {
1393 return (Component)getClientProperty(NEXT_FOCUS);
1394 }
1395
1396 /**
1397 * Provides a hint as to whether or not this <code>JComponent</code>
1398 * should get focus. This is only a hint, and it is up to consumers that
1399 * are requesting focus to honor this property. This is typically honored
1400 * for mouse operations, but not keyboard operations. For example, look
1401 * and feels could verify this property is true before requesting focus
1402 * during a mouse operation. This would often times be used if you did
1403 * not want a mouse press on a <code>JComponent</code> to steal focus,
1404 * but did want the <code>JComponent</code> to be traversable via the
1405 * keyboard. If you do not want this <code>JComponent</code> focusable at
1406 * all, use the <code>setFocusable</code> method instead.
1407 * <p>
1408 * Please see
1409 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1410 * How to Use the Focus Subsystem</a>,
1411 * a section in <em>The Java Tutorial</em>,
1412 * for more information.
1413 *
1414 * @param requestFocusEnabled indicates whether you want this
1415 * <code>JComponent</code> to be focusable or not
1416 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
1417 * @see java.awt.Component#setFocusable
1418 */
1419 public void setRequestFocusEnabled(boolean requestFocusEnabled) {
1420 setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled);
1421 }
1422
1423 /**
1424 * Returns <code>true</code> if this <code>JComponent</code> should
1425 * get focus; otherwise returns <code>false</code>.
1426 * <p>
1427 * Please see
1428 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1429 * How to Use the Focus Subsystem</a>,
1430 * a section in <em>The Java Tutorial</em>,
1431 * for more information.
1432 *
1433 * @return <code>true</code> if this component should get focus,
1434 * otherwise returns <code>false</code>
1435 * @see #setRequestFocusEnabled
1436 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus
1437 * Specification</a>
1438 * @see java.awt.Component#isFocusable
1439 */
1440 public boolean isRequestFocusEnabled() {
1441 return !getFlag(REQUEST_FOCUS_DISABLED);
1442 }
1443
1444 /**
1445 * Requests that this <code>Component</code> gets the input focus.
1446 * Refer to {@link java.awt.Component#requestFocus()
1447 * Component.requestFocus()} for a complete description of
1448 * this method.
1449 * <p>
1450 * Note that the use of this method is discouraged because
1451 * its behavior is platform dependent. Instead we recommend the
1452 * use of {@link #requestFocusInWindow() requestFocusInWindow()}.
1453 * If you would like more information on focus, see
1454 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1455 * How to Use the Focus Subsystem</a>,
1456 * a section in <em>The Java Tutorial</em>.
1457 *
1458 * @see java.awt.Component#requestFocusInWindow()
1459 * @see java.awt.Component#requestFocusInWindow(boolean)
1460 * @since 1.4
1461 */
1462 public void requestFocus() {
1463 super.requestFocus();
1464 }
1465
1466 /**
1467 * Requests that this <code>Component</code> gets the input focus.
1468 * Refer to {@link java.awt.Component#requestFocus(boolean)
1469 * Component.requestFocus(boolean)} for a complete description of
1470 * this method.
1471 * <p>
1472 * Note that the use of this method is discouraged because
1473 * its behavior is platform dependent. Instead we recommend the
1474 * use of {@link #requestFocusInWindow(boolean)
1475 * requestFocusInWindow(boolean)}.
1476 * If you would like more information on focus, see
1477 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1478 * How to Use the Focus Subsystem</a>,
1479 * a section in <em>The Java Tutorial</em>.
1480 *
1481 * @param temporary boolean indicating if the focus change is temporary
1482 * @return <code>false</code> if the focus change request is guaranteed to
1483 * fail; <code>true</code> if it is likely to succeed
1484 * @see java.awt.Component#requestFocusInWindow()
1485 * @see java.awt.Component#requestFocusInWindow(boolean)
1486 * @since 1.4
1487 */
1488 public boolean requestFocus(boolean temporary) {
1489 return super.requestFocus(temporary);
1490 }
1491
1492 /**
1493 * Requests that this <code>Component</code> gets the input focus.
1494 * Refer to {@link java.awt.Component#requestFocusInWindow()
1495 * Component.requestFocusInWindow()} for a complete description of
1496 * this method.
1497 * <p>
1498 * If you would like more information on focus, see
1499 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1500 * How to Use the Focus Subsystem</a>,
1501 * a section in <em>The Java Tutorial</em>.
1502 *
1503 * @return <code>false</code> if the focus change request is guaranteed to
1504 * fail; <code>true</code> if it is likely to succeed
1505 * @see java.awt.Component#requestFocusInWindow()
1506 * @see java.awt.Component#requestFocusInWindow(boolean)
1507 * @since 1.4
1508 */
1509 public boolean requestFocusInWindow() {
1510 return super.requestFocusInWindow();
1511 }
1512
1513 /**
1514 * Requests that this <code>Component</code> gets the input focus.
1515 * Refer to {@link java.awt.Component#requestFocusInWindow(boolean)
1516 * Component.requestFocusInWindow(boolean)} for a complete description of
1517 * this method.
1518 * <p>
1519 * If you would like more information on focus, see
1520 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1521 * How to Use the Focus Subsystem</a>,
1522 * a section in <em>The Java Tutorial</em>.
1523 *
1524 * @param temporary boolean indicating if the focus change is temporary
1525 * @return <code>false</code> if the focus change request is guaranteed to
1526 * fail; <code>true</code> if it is likely to succeed
1527 * @see java.awt.Component#requestFocusInWindow()
1528 * @see java.awt.Component#requestFocusInWindow(boolean)
1529 * @since 1.4
1530 */
1531 protected boolean requestFocusInWindow(boolean temporary) {
1532 return super.requestFocusInWindow(temporary);
1533 }
1534
1535 /**
1536 * Requests that this Component get the input focus, and that this
1537 * Component's top-level ancestor become the focused Window. This component
1538 * must be displayable, visible, and focusable for the request to be
1539 * granted.
1540 * <p>
1541 * This method is intended for use by focus implementations. Client code
1542 * should not use this method; instead, it should use
1543 * <code>requestFocusInWindow()</code>.
1544 *
1545 * @see #requestFocusInWindow()
1546 */
1547 public void grabFocus() {
1548 requestFocus();
1549 }
1550
1551 /**
1552 * Sets the value to indicate whether input verifier for the
1553 * current focus owner will be called before this component requests
1554 * focus. The default is true. Set to false on components such as a
1555 * Cancel button or a scrollbar, which should activate even if the
1556 * input in the current focus owner is not "passed" by the input
1557 * verifier for that component.
1558 *
1559 * @param verifyInputWhenFocusTarget value for the
1560 * <code>verifyInputWhenFocusTarget</code> property
1561 * @see InputVerifier
1562 * @see #setInputVerifier
1563 * @see #getInputVerifier
1564 * @see #getVerifyInputWhenFocusTarget
1565 *
1566 * @since 1.3
1567 * @beaninfo
1568 * bound: true
1569 * description: Whether the Component verifies input before accepting
1570 * focus.
1571 */
1572 public void setVerifyInputWhenFocusTarget(boolean
1573 verifyInputWhenFocusTarget) {
1574 boolean oldVerifyInputWhenFocusTarget =
1575 this.verifyInputWhenFocusTarget;
1576 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
1577 firePropertyChange("verifyInputWhenFocusTarget",
1578 oldVerifyInputWhenFocusTarget,
1579 verifyInputWhenFocusTarget);
1580 }
1581
1582 /**
1583 * Returns the value that indicates whether the input verifier for the
1584 * current focus owner will be called before this component requests
1585 * focus.
1586 *
1587 * @return value of the <code>verifyInputWhenFocusTarget</code> property
1588 *
1589 * @see InputVerifier
1590 * @see #setInputVerifier
1591 * @see #getInputVerifier
1592 * @see #setVerifyInputWhenFocusTarget
1593 *
1594 * @since 1.3
1595 */
1596 public boolean getVerifyInputWhenFocusTarget() {
1597 return verifyInputWhenFocusTarget;
1598 }
1599
1600
1601 /**
1602 * Gets the <code>FontMetrics</code> for the specified <code>Font</code>.
1603 *
1604 * @param font the font for which font metrics is to be
1605 * obtained
1606 * @return the font metrics for <code>font</code>
1607 * @throws NullPointerException if <code>font</code> is null
1608 * @since 1.5
1609 */
1610 public FontMetrics getFontMetrics(Font font) {
1611 return SwingUtilities2.getFontMetrics(this, font);
1612 }
1613
1614
1615 /**
1616 * Sets the preferred size of this component.
1617 * If <code>preferredSize</code> is <code>null</code>, the UI will
1618 * be asked for the preferred size.
1619 * @beaninfo
1620 * preferred: true
1621 * bound: true
1622 * description: The preferred size of the component.
1623 */
1624 public void setPreferredSize(Dimension preferredSize) {
1625 super.setPreferredSize(preferredSize);
1626 }
1627
1628
1629 /**
1630 * If the <code>preferredSize</code> has been set to a
1631 * non-<code>null</code> value just returns it.
1632 * If the UI delegate's <code>getPreferredSize</code>
1633 * method returns a non <code>null</code> value then return that;
1634 * otherwise defer to the component's layout manager.
1635 *
1636 * @return the value of the <code>preferredSize</code> property
1637 * @see #setPreferredSize
1638 * @see ComponentUI
1639 */
1640 @Transient
1641 public Dimension getPreferredSize() {
1642 if (isPreferredSizeSet()) {
1643 return super.getPreferredSize();
1644 }
1645 Dimension size = null;
1646 if (ui != null) {
1647 size = ui.getPreferredSize(this);
1648 }
1649 return (size != null) ? size : super.getPreferredSize();
1650 }
1651
1652
1653 /**
1654 * Sets the maximum size of this component to a constant
1655 * value. Subsequent calls to <code>getMaximumSize</code> will always
1656 * return this value; the component's UI will not be asked
1657 * to compute it. Setting the maximum size to <code>null</code>
1658 * restores the default behavior.
1659 *
1660 * @param maximumSize a <code>Dimension</code> containing the
1661 * desired maximum allowable size
1662 * @see #getMaximumSize
1663 * @beaninfo
1664 * bound: true
1665 * description: The maximum size of the component.
1666 */
1667 public void setMaximumSize(Dimension maximumSize) {
1668 super.setMaximumSize(maximumSize);
1669 }
1670
1671
1672 /**
1673 * If the maximum size has been set to a non-<code>null</code> value
1674 * just returns it. If the UI delegate's <code>getMaximumSize</code>
1675 * method returns a non-<code>null</code> value then return that;
1676 * otherwise defer to the component's layout manager.
1677 *
1678 * @return the value of the <code>maximumSize</code> property
1679 * @see #setMaximumSize
1680 * @see ComponentUI
1681 */
1682 @Transient
1683 public Dimension getMaximumSize() {
1684 if (isMaximumSizeSet()) {
1685 return super.getMaximumSize();
1686 }
1687 Dimension size = null;
1688 if (ui != null) {
1689 size = ui.getMaximumSize(this);
1690 }
1691 return (size != null) ? size : super.getMaximumSize();
1692 }
1693
1694
1695 /**
1696 * Sets the minimum size of this component to a constant
1697 * value. Subsequent calls to <code>getMinimumSize</code> will always
1698 * return this value; the component's UI will not be asked
1699 * to compute it. Setting the minimum size to <code>null</code>
1700 * restores the default behavior.
1701 *
1702 * @param minimumSize the new minimum size of this component
1703 * @see #getMinimumSize
1704 * @beaninfo
1705 * bound: true
1706 * description: The minimum size of the component.
1707 */
1708 public void setMinimumSize(Dimension minimumSize) {
1709 super.setMinimumSize(minimumSize);
1710 }
1711
1712 /**
1713 * If the minimum size has been set to a non-<code>null</code> value
1714 * just returns it. If the UI delegate's <code>getMinimumSize</code>
1715 * method returns a non-<code>null</code> value then return that; otherwise
1716 * defer to the component's layout manager.
1717 *
1718 * @return the value of the <code>minimumSize</code> property
1719 * @see #setMinimumSize
1720 * @see ComponentUI
1721 */
1722 @Transient
1723 public Dimension getMinimumSize() {
1724 if (isMinimumSizeSet()) {
1725 return super.getMinimumSize();
1726 }
1727 Dimension size = null;
1728 if (ui != null) {
1729 size = ui.getMinimumSize(this);
1730 }
1731 return (size != null) ? size : super.getMinimumSize();
1732 }
1733
1734 /**
1735 * Gives the UI delegate an opportunity to define the precise
1736 * shape of this component for the sake of mouse processing.
1737 *
1738 * @return true if this component logically contains x,y
1739 * @see java.awt.Component#contains(int, int)
1740 * @see ComponentUI
1741 */
1742 public boolean contains(int x, int y) {
1743 return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
1744 }
1745
1746 /**
1747 * Sets the border of this component. The <code>Border</code> object is
1748 * responsible for defining the insets for the component
1749 * (overriding any insets set directly on the component) and
1750 * for optionally rendering any border decorations within the
1751 * bounds of those insets. Borders should be used (rather
1752 * than insets) for creating both decorative and non-decorative
1753 * (such as margins and padding) regions for a swing component.
1754 * Compound borders can be used to nest multiple borders within a
1755 * single component.
1756 * <p>
1757 * Although technically you can set the border on any object
1758 * that inherits from <code>JComponent</code>, the look and
1759 * feel implementation of many standard Swing components
1760 * doesn't work well with user-set borders. In general,
1761 * when you want to set a border on a standard Swing
1762 * component other than <code>JPanel</code> or <code>JLabel</code>,
1763 * we recommend that you put the component in a <code>JPanel</code>
1764 * and set the border on the <code>JPanel</code>.
1765 * <p>
1766 * This is a bound property.
1767 *
1768 * @param border the border to be rendered for this component
1769 * @see Border
1770 * @see CompoundBorder
1771 * @beaninfo
1772 * bound: true
1773 * preferred: true
1774 * attribute: visualUpdate true
1775 * description: The component's border.
1776 */
1777 public void setBorder(Border border) {
1778 Border oldBorder = this.border;
1779
1780 this.border = border;
1781 firePropertyChange("border", oldBorder, border);
1782 if (border != oldBorder) {
1783 if (border == null || oldBorder == null ||
1784 !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
1785 revalidate();
1786 }
1787 repaint();
1788 }
1789 }
1790
1791 /**
1792 * Returns the border of this component or <code>null</code> if no
1793 * border is currently set.
1794 *
1795 * @return the border object for this component
1796 * @see #setBorder
1797 */
1798 public Border getBorder() {
1799 return border;
1800 }
1801
1802 /**
1803 * If a border has been set on this component, returns the
1804 * border's insets; otherwise calls <code>super.getInsets</code>.
1805 *
1806 * @return the value of the insets property
1807 * @see #setBorder
1808 */
1809 public Insets getInsets() {
1810 if (border != null) {
1811 return border.getBorderInsets(this);
1812 }
1813 return super.getInsets();
1814 }
1815
1816 /**
1817 * Returns an <code>Insets</code> object containing this component's inset
1818 * values. The passed-in <code>Insets</code> object will be reused
1819 * if possible.
1820 * Calling methods cannot assume that the same object will be returned,
1821 * however. All existing values within this object are overwritten.
1822 * If <code>insets</code> is null, this will allocate a new one.
1823 *
1824 * @param insets the <code>Insets</code> object, which can be reused
1825 * @return the <code>Insets</code> object
1826 * @see #getInsets
1827 * @beaninfo
1828 * expert: true
1829 */
1830 public Insets getInsets(Insets insets) {
1831 if (insets == null) {
1832 insets = new Insets(0, 0, 0, 0);
1833 }
1834 if (border != null) {
1835 if (border instanceof AbstractBorder) {
1836 return ((AbstractBorder)border).getBorderInsets(this, insets);
1837 } else {
1838 // Can't reuse border insets because the Border interface
1839 // can't be enhanced.
1840 return border.getBorderInsets(this);
1841 }
1842 } else {
1843 // super.getInsets() always returns an Insets object with
1844 // all of its value zeroed. No need for a new object here.
1845 insets.left = insets.top = insets.right = insets.bottom = 0;
1846 return insets;
1847 }
1848 }
1849
1850 /**
1851 * Overrides <code>Container.getAlignmentY</code> to return
1852 * the horizontal alignment.
1853 *
1854 * @return the value of the <code>alignmentY</code> property
1855 * @see #setAlignmentY
1856 * @see java.awt.Component#getAlignmentY
1857 */
1858 public float getAlignmentY() {
1859 if (isAlignmentYSet) {
1860 return alignmentY;
1861 }
1862 return super.getAlignmentY();
1863 }
1864
1865 /**
1866 * Sets the the horizontal alignment.
1867 *
1868 * @param alignmentY the new horizontal alignment
1869 * @see #getAlignmentY
1870 * @beaninfo
1871 * description: The preferred vertical alignment of the component.
1872 */
1873 public void setAlignmentY(float alignmentY) {
1874 this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY;
1875 isAlignmentYSet = true;
1876 }
1877
1878
1879 /**
1880 * Overrides <code>Container.getAlignmentX</code> to return
1881 * the vertical alignment.
1882 *
1883 * @return the value of the <code>alignmentX</code> property
1884 * @see #setAlignmentX
1885 * @see java.awt.Component#getAlignmentX
1886 */
1887 public float getAlignmentX() {
1888 if (isAlignmentXSet) {
1889 return alignmentX;
1890 }
1891 return super.getAlignmentX();
1892 }
1893
1894 /**
1895 * Sets the the vertical alignment.
1896 *
1897 * @param alignmentX the new vertical alignment
1898 * @see #getAlignmentX
1899 * @beaninfo
1900 * description: The preferred horizontal alignment of the component.
1901 */
1902 public void setAlignmentX(float alignmentX) {
1903 this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX;
1904 isAlignmentXSet = true;
1905 }
1906
1907 /**
1908 * Sets the input verifier for this component.
1909 *
1910 * @param inputVerifier the new input verifier
1911 * @since 1.3
1912 * @see InputVerifier
1913 * @beaninfo
1914 * bound: true
1915 * description: The component's input verifier.
1916 */
1917 public void setInputVerifier(InputVerifier inputVerifier) {
1918 InputVerifier oldInputVerifier = (InputVerifier)getClientProperty(
1919 JComponent_INPUT_VERIFIER);
1920 putClientProperty(JComponent_INPUT_VERIFIER, inputVerifier);
1921 firePropertyChange("inputVerifier", oldInputVerifier, inputVerifier);
1922 }
1923
1924 /**
1925 * Returns the input verifier for this component.
1926 *
1927 * @return the <code>inputVerifier</code> property
1928 * @since 1.3
1929 * @see InputVerifier
1930 */
1931 public InputVerifier getInputVerifier() {
1932 return (InputVerifier)getClientProperty(JComponent_INPUT_VERIFIER);
1933 }
1934
1935 /**
1936 * Returns this component's graphics context, which lets you draw
1937 * on a component. Use this method to get a <code>Graphics</code> object and
1938 * then invoke operations on that object to draw on the component.
1939 * @return this components graphics context
1940 */
1941 public Graphics getGraphics() {
1942 if (DEBUG_GRAPHICS_LOADED && shouldDebugGraphics() != 0) {
1943 DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
1944 this);
1945 return graphics;
1946 }
1947 return super.getGraphics();
1948 }
1949
1950
1951 /** Enables or disables diagnostic information about every graphics
1952 * operation performed within the component or one of its children.
1953 *
1954 * @param debugOptions determines how the component should display
1955 * the information; one of the following options:
1956 * <ul>
1957 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1958 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1959 * times.
1960 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1961 * <code>ExternalWindow</code> that displays the operations
1962 * performed on the View's offscreen buffer.
1963 * <li>DebugGraphics.NONE_OPTION disables debugging.
1964 * <li>A value of 0 causes no changes to the debugging options.
1965 * </ul>
1966 * <code>debugOptions</code> is bitwise OR'd into the current value
1967 *
1968 * @beaninfo
1969 * preferred: true
1970 * enum: NONE_OPTION DebugGraphics.NONE_OPTION
1971 * LOG_OPTION DebugGraphics.LOG_OPTION
1972 * FLASH_OPTION DebugGraphics.FLASH_OPTION
1973 * BUFFERED_OPTION DebugGraphics.BUFFERED_OPTION
1974 * description: Diagnostic options for graphics operations.
1975 */
1976 public void setDebugGraphicsOptions(int debugOptions) {
1977 DebugGraphics.setDebugOptions(this, debugOptions);
1978 }
1979
1980 /** Returns the state of graphics debugging.
1981 *
1982 * @return a bitwise OR'd flag of zero or more of the following options:
1983 * <ul>
1984 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1985 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1986 * times.
1987 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1988 * <code>ExternalWindow</code> that displays the operations
1989 * performed on the View's offscreen buffer.
1990 * <li>DebugGraphics.NONE_OPTION disables debugging.
1991 * <li>A value of 0 causes no changes to the debugging options.
1992 * </ul>
1993 * @see #setDebugGraphicsOptions
1994 */
1995 public int getDebugGraphicsOptions() {
1996 return DebugGraphics.getDebugOptions(this);
1997 }
1998
1999
2000 /**
2001 * Returns true if debug information is enabled for this
2002 * <code>JComponent</code> or one of its parents.
2003 */
2004 int shouldDebugGraphics() {
2005 return DebugGraphics.shouldComponentDebug(this);
2006 }
2007
2008 /**
2009 * This method is now obsolete, please use a combination of
2010 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2011 * similiar behavior. For example, to bind the <code>KeyStroke</code>
2012 * <code>aKeyStroke</code> to the <code>Action</code> <code>anAction</code>
2013 * now use:
2014 * <pre>
2015 * component.getInputMap().put(aKeyStroke, aCommand);
2016 * component.getActionMap().put(aCommmand, anAction);
2017 * </pre>
2018 * The above assumes you want the binding to be applicable for
2019 * <code>WHEN_FOCUSED</code>. To register bindings for other focus
2020 * states use the <code>getInputMap</code> method that takes an integer.
2021 * <p>
2022 * Register a new keyboard action.
2023 * <code>anAction</code> will be invoked if a key event matching
2024 * <code>aKeyStroke</code> occurs and <code>aCondition</code> is verified.
2025 * The <code>KeyStroke</code> object defines a
2026 * particular combination of a keyboard key and one or more modifiers
2027 * (alt, shift, ctrl, meta).
2028 * <p>
2029 * The <code>aCommand</code> will be set in the delivered event if
2030 * specified.
2031 * <p>
2032 * The <code>aCondition</code> can be one of:
2033 * <blockquote>
2034 * <DL>
2035 * <DT>WHEN_FOCUSED
2036 * <DD>The action will be invoked only when the keystroke occurs
2037 * while the component has the focus.
2038 * <DT>WHEN_IN_FOCUSED_WINDOW
2039 * <DD>The action will be invoked when the keystroke occurs while
2040 * the component has the focus or if the component is in the
2041 * window that has the focus. Note that the component need not
2042 * be an immediate descendent of the window -- it can be
2043 * anywhere in the window's containment hierarchy. In other
2044 * words, whenever <em>any</em> component in the window has the focus,
2045 * the action registered with this component is invoked.
2046 * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2047 * <DD>The action will be invoked when the keystroke occurs while the
2048 * component has the focus or if the component is an ancestor of
2049 * the component that has the focus.
2050 * </DL>
2051 * </blockquote>
2052 * <p>
2053 * The combination of keystrokes and conditions lets you define high
2054 * level (semantic) action events for a specified keystroke+modifier
2055 * combination (using the KeyStroke class) and direct to a parent or
2056 * child of a component that has the focus, or to the component itself.
2057 * In other words, in any hierarchical structure of components, an
2058 * arbitrary key-combination can be immediately directed to the
2059 * appropriate component in the hierarchy, and cause a specific method
2060 * to be invoked (usually by way of adapter objects).
2061 * <p>
2062 * If an action has already been registered for the receiving
2063 * container, with the same charCode and the same modifiers,
2064 * <code>anAction</code> will replace the action.
2065 *
2066 * @param anAction the <code>Action</code> to be registered
2067 * @param aCommand the command to be set in the delivered event
2068 * @param aKeyStroke the <code>KeyStroke</code> to bind to the action
2069 * @param aCondition the condition that needs to be met, see above
2070 * @see KeyStroke
2071 */
2072 public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
2073
2074 InputMap inputMap = getInputMap(aCondition, true);
2075
2076 if (inputMap != null) {
2077 ActionMap actionMap = getActionMap(true);
2078 ActionStandin action = new ActionStandin(anAction, aCommand);
2079 inputMap.put(aKeyStroke, action);
2080 if (actionMap != null) {
2081 actionMap.put(action, action);
2082 }
2083 }
2084 }
2085
2086 /**
2087 * Registers any bound <code>WHEN_IN_FOCUSED_WINDOW</code> actions with
2088 * the <code>KeyboardManager</code>. If <code>onlyIfNew</code>
2089 * is true only actions that haven't been registered are pushed
2090 * to the <code>KeyboardManager</code>;
2091 * otherwise all actions are pushed to the <code>KeyboardManager</code>.
2092 *
2093 * @param onlyIfNew if true, only actions that haven't been registered
2094 * are pushed to the <code>KeyboardManager</code>
2095 */
2096 private void registerWithKeyboardManager(boolean onlyIfNew) {
2097 InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2098 KeyStroke[] strokes;
2099 Hashtable registered = (Hashtable)getClientProperty
2100 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2101
2102 if (inputMap != null) {
2103 // Push any new KeyStrokes to the KeyboardManager.
2104 strokes = inputMap.allKeys();
2105 if (strokes != null) {
2106 for (int counter = strokes.length - 1; counter >= 0;
2107 counter--) {
2108 if (!onlyIfNew || registered == null ||
2109 registered.get(strokes[counter]) == null) {
2110 registerWithKeyboardManager(strokes[counter]);
2111 }
2112 if (registered != null) {
2113 registered.remove(strokes[counter]);
2114 }
2115 }
2116 }
2117 }
2118 else {
2119 strokes = null;
2120 }
2121 // Remove any old ones.
2122 if (registered != null && registered.size() > 0) {
2123 Enumeration keys = registered.keys();
2124
2125 while (keys.hasMoreElements()) {
2126 KeyStroke ks = (KeyStroke)keys.nextElement();
2127 unregisterWithKeyboardManager(ks);
2128 }
2129 registered.clear();
2130 }
2131 // Updated the registered Hashtable.
2132 if (strokes != null && strokes.length > 0) {
2133 if (registered == null) {
2134 registered = new Hashtable(strokes.length);
2135 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, registered);
2136 }
2137 for (int counter = strokes.length - 1; counter >= 0; counter--) {
2138 registered.put(strokes[counter], strokes[counter]);
2139 }
2140 }
2141 else {
2142 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2143 }
2144 }
2145
2146 /**
2147 * Unregisters all the previously registered
2148 * <code>WHEN_IN_FOCUSED_WINDOW</code> <code>KeyStroke</code> bindings.
2149 */
2150 private void unregisterWithKeyboardManager() {
2151 Hashtable registered = (Hashtable)getClientProperty
2152 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2153
2154 if (registered != null && registered.size() > 0) {
2155 Enumeration keys = registered.keys();
2156
2157 while (keys.hasMoreElements()) {
2158 KeyStroke ks = (KeyStroke)keys.nextElement();
2159 unregisterWithKeyboardManager(ks);
2160 }
2161 }
2162 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2163 }
2164
2165 /**
2166 * Invoked from <code>ComponentInputMap</code> when its bindings change.
2167 * If <code>inputMap</code> is the current <code>windowInputMap</code>
2168 * (or a parent of the window <code>InputMap</code>)
2169 * the <code>KeyboardManager</code> is notified of the new bindings.
2170 *
2171 * @param inputMap the map containing the new bindings
2172 */
2173 void componentInputMapChanged(ComponentInputMap inputMap) {
2174 InputMap km = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2175
2176 while (km != inputMap && km != null) {
2177 km = (ComponentInputMap)km.getParent();
2178 }
2179 if (km != null) {
2180 registerWithKeyboardManager(false);
2181 }
2182 }
2183
2184 private void registerWithKeyboardManager(KeyStroke aKeyStroke) {
2185 KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke,this);
2186 }
2187
2188 private void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
2189 KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke,
2190 this);
2191 }
2192
2193 /**
2194 * This method is now obsolete, please use a combination of
2195 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2196 * similiar behavior.
2197 */
2198 public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
2199 registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
2200 }
2201
2202 /**
2203 * This method is now obsolete. To unregister an existing binding
2204 * you can either remove the binding from the
2205 * <code>ActionMap/InputMap</code>, or place a dummy binding the
2206 * <code>InputMap</code>. Removing the binding from the
2207 * <code>InputMap</code> allows bindings in parent <code>InputMap</code>s
2208 * to be active, whereas putting a dummy binding in the
2209 * <code>InputMap</code> effectively disables
2210 * the binding from ever happening.
2211 * <p>
2212 * Unregisters a keyboard action.
2213 * This will remove the binding from the <code>ActionMap</code>
2214 * (if it exists) as well as the <code>InputMap</code>s.
2215 */
2216 public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
2217 ActionMap am = getActionMap(false);
2218 for (int counter = 0; counter < 3; counter++) {
2219 InputMap km = getInputMap(counter, false);
2220 if (km != null) {
2221 Object actionID = km.get(aKeyStroke);
2222
2223 if (am != null && actionID != null) {
2224 am.remove(actionID);
2225 }
2226 km.remove(aKeyStroke);
2227 }
2228 }
2229 }
2230
2231 /**
2232 * Returns the <code>KeyStrokes</code> that will initiate
2233 * registered actions.
2234 *
2235 * @return an array of <code>KeyStroke</code> objects
2236 * @see #registerKeyboardAction
2237 */
2238 public KeyStroke[] getRegisteredKeyStrokes() {
2239 int[] counts = new int[3];
2240 KeyStroke[][] strokes = new KeyStroke[3][];
2241
2242 for (int counter = 0; counter < 3; counter++) {
2243 InputMap km = getInputMap(counter, false);
2244 strokes[counter] = (km != null) ? km.allKeys() : null;
2245 counts[counter] = (strokes[counter] != null) ?
2246 strokes[counter].length : 0;
2247 }
2248 KeyStroke[] retValue = new KeyStroke[counts[0] + counts[1] +
2249 counts[2]];
2250 for (int counter = 0, last = 0; counter < 3; counter++) {
2251 if (counts[counter] > 0) {
2252 System.arraycopy(strokes[counter], 0, retValue, last,
2253 counts[counter]);
2254 last += counts[counter];
2255 }
2256 }
2257 return retValue;
2258 }
2259
2260 /**
2261 * Returns the condition that determines whether a registered action
2262 * occurs in response to the specified keystroke.
2263 * <p>
2264 * For Java 2 platform v1.3, a <code>KeyStroke</code> can be associated
2265 * with more than one condition.
2266 * For example, 'a' could be bound for the two
2267 * conditions <code>WHEN_FOCUSED</code> and
2268 * <code>WHEN_IN_FOCUSED_WINDOW</code> condition.
2269 *
2270 * @return the action-keystroke condition
2271 */
2272 public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
2273 for (int counter = 0; counter < 3; counter++) {
2274 InputMap inputMap = getInputMap(counter, false);
2275 if (inputMap != null && inputMap.get(aKeyStroke) != null) {
2276 return counter;
2277 }
2278 }
2279 return UNDEFINED_CONDITION;
2280